Skip to content

Instantly share code, notes, and snippets.

@JamshidbekAkhlidinov
Last active June 18, 2025 12:48
Show Gist options
  • Save JamshidbekAkhlidinov/13ac7dc258f6386575b2ae83aecbcfb0 to your computer and use it in GitHub Desktop.
Save JamshidbekAkhlidinov/13ac7dc258f6386575b2ae83aecbcfb0 to your computer and use it in GitHub Desktop.
TinyMce content clear and photo upload server then change src
<?php
/*
* Jamshidbek Akhlidinov
* 18 - 6 2025 16:42:58
* https://ustadev.uz
* https://github.com/JamshidbekAkhlidinov
*/
use dosamigos\tinymce\TinyMce;
echo TinyMce::widget([
'name' => 'test',
'options' => ['rows' => 10],
'language' => 'en',
'clientOptions' => [
'height' => '80vh',
'plugins' => [
"code",
"lists link image preview",
'code', 'preview', 'image', 'media', 'link',
'table', 'lists', 'fullscreen', 'wordcount'
],
'toolbar' => 'undo redo | bold italic | alignleft aligncenter alignright | clearhtml | optimizeimages | code',
'setup' => new \yii\web\JsExpression(<<<JS
function (editor) {
// Clear HTML tugmasi
editor.ui.registry.addButton('clearhtml', {
text: 'Clear HTML',
icon: 'remove-format',
tooltip: 'Remove attributes from all tags except src in img, video, iframe',
onAction: function () {
let content = editor.getContent();
let div = document.createElement('div');
div.innerHTML = content;
function cleanAttributes(el) {
if (el.nodeType === 1) {
let tag = el.tagName.toLowerCase();
let keepSrc = ['img', 'iframe', 'video'].includes(tag);
let attrs = Array.from(el.attributes);
for (let attr of attrs) {
if (keepSrc && attr.name === 'src') {
continue; // src ni saqlab qolamiz
}
el.removeAttribute(attr.name);
}
if (tag === 'img') {
el.setAttribute('width', '500');
}
for (let i = 0; i < el.childNodes.length; i++) {
cleanAttributes(el.childNodes[i]);
}
}
}
cleanAttributes(div);
editor.setContent(div.innerHTML);
}
});
// Optimize Images tugmasi
editor.ui.registry.addButton('optimizeimages', {
text: 'Optimize Images',
icon: 'refresh',
tooltip: 'Download and convert all external images to webp',
onAction: function () {
const content = editor.getContent();
let progressSpan = document.getElementById('image-optimize-progress');
if (!progressSpan) {
progressSpan = document.createElement('span');
progressSpan.id = 'image-optimize-progress';
progressSpan.style.marginLeft = '10px';
progressSpan.style.fontWeight = 'bold';
editor.getContainer().parentNode.insertBefore(progressSpan, editor.getContainer());
}
let percent = 1;
progressSpan.textContent = 'Processing: 1%';
const interval = setInterval(() => {
if (percent < 95) {
percent++;
progressSpan.textContent = 'Processing: ' + percent + '%';
}
}, 150);
$.ajax({
url: '/admin/test/convert-images',
method: 'POST',
data: {
html: content,
name: 'ustadev'
},
headers: {
'X-CSRF-Token': yii.getCsrfToken()
},
success: function (data) {
clearInterval(interval);
progressSpan.textContent = 'Done ✅';
if (data.success && data.html) {
editor.setContent(data.html);
} else {
alert('Xatolik: ' + (data.error || 'HTML topilmadi'));
}
},
error: function (xhr, status, error) {
clearInterval(interval);
progressSpan.textContent = 'Xato ❌';
console.error('API error:', error);
}
});
}
});
}
JS
),
]
]);
<?php
/*
* Jamshidbek Akhlidinov
* 18 - 6 2025 16:42:43
* https://ustadev.uz
* https://github.com/JamshidbekAkhlidinov
*/
namespace app\modules\admin\controllers;
use DOMDocument;
use Yii;
use yii\web\Controller;
use yii\web\Response;
class TestController extends Controller
{
public function actionIndex()
{
return $this->render('form');
}
public function actionConvertImages()
{
Yii::$app->response->format = Response::FORMAT_JSON;
$html = Yii::$app->request->post('html');
if (empty($html)) {
return ['success' => false, 'error' => 'HTML not provided'];
}
$cleanHtml = $this->convertImagesToLocalWebp($html);
return ['success' => true, 'html' => $cleanHtml];
}
private function convertImagesToLocalWebp($htmlContent)
{
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($htmlContent, 'HTML-ENTITIES', 'UTF-8'));
$images = $dom->getElementsByTagName('img');
foreach ($images as $img) {
$src = $img->getAttribute('src');
if (filter_var($src, FILTER_VALIDATE_URL)) {
$imgData = @file_get_contents($src);
if ($imgData === false) continue;
// Rasm nomi va serverga saqlash yo‘li
$fileName = 'img_' . uniqid() . '.webp';
$savePath = Yii::getAlias('@webroot/uploads/' . $fileName);
$webPath = Yii::getAlias('@web/uploads/' . $fileName);
$tmpPath = sys_get_temp_dir() . '/' . uniqid() . '.img';
file_put_contents($tmpPath, $imgData);
$mime = mime_content_type($tmpPath);
switch ($mime) {
case 'image/jpeg':
case 'image/pjpeg':
$imgRes = imagecreatefromjpeg($tmpPath);
break;
case 'image/png':
$imgRes = imagecreatefrompng($tmpPath);
break;
case 'image/gif':
$imgRes = imagecreatefromgif($tmpPath);
break;
case 'image/bmp':
case 'image/x-ms-bmp':
if (function_exists('imagecreatefrombmp')) {
$imgRes = imagecreatefrombmp($tmpPath);
} else {
continue 2;
}
break;
case 'image/webp':
if (function_exists('imagecreatefromwebp')) {
$imgRes = imagecreatefromwebp($tmpPath);
} else {
continue 2;
}
break;
default:
continue 2;
}
// webp saqlash
imagewebp($imgRes, $savePath, 80);
imagedestroy($imgRes);
$img->setAttribute('src', $webPath);
$img->setAttribute('width', '500');
}
}
// Qayta string holatga qaytarish
return $dom->saveHTML($dom->getElementsByTagName('body')->item(0));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment