This commit is contained in:
2026-02-11 15:28:33 +01:00
parent 67ed085b38
commit a4a8f6882b
2 changed files with 74 additions and 37 deletions

View File

@@ -24,14 +24,14 @@
},
"MailToTaskImporter.php": {
"type": "-",
"size": 24511,
"lmtime": 1770587036920,
"size": 37407,
"lmtime": 1770734028354,
"modified": false
},
"TaskAttachmentRepository.php": {
"type": "-",
"size": 8411,
"lmtime": 0,
"size": 8806,
"lmtime": 1770731454505,
"modified": false
},
"WorkTimeRepository.php": {
@@ -138,8 +138,8 @@
".claude": {
"settings.local.json": {
"type": "-",
"size": 72,
"lmtime": 1770583517578,
"size": 265,
"lmtime": 1770734134148,
"modified": false
}
},
@@ -175,6 +175,12 @@
},
"layout": {},
"libraries": {},
"logs.txt": {
"type": "-",
"size": 1016,
"lmtime": 1770733260000,
"modified": false
},
"REFACTORING_PLAN.md": {
"type": "-",
"size": 3576,
@@ -210,8 +216,8 @@
},
"task_edit.php": {
"type": "-",
"size": 10202,
"lmtime": 0,
"size": 10285,
"lmtime": 1770733553999,
"modified": false
},
"task_popup.php": {
@@ -272,6 +278,22 @@
"lmtime": 0,
"modified": false
}
},
"html": {
"textarea.php": {
"type": "-",
"size": 1383,
"lmtime": 1770733546656,
"modified": false
}
},
"projects": {
"task-edit.php": {
"type": "-",
"size": 7739,
"lmtime": 1770733570166,
"modified": false
}
}
},
"tests": {

View File

@@ -172,24 +172,30 @@ class MailToTaskImporter
continue;
}
// Konwertuj inline images do Base64 i osadź w treści
$cid_to_data_uri = [];
// Zapisz inline images jako załączniki i zbierz URLe
$cid_to_url = [];
if ( isset( $content['inline_images'] ) && is_array( $content['inline_images'] ) )
{
foreach ( $content['inline_images'] as $cid => $inline_image )
{
// Konwertuj obraz do Base64 data URI
$data_uri = $this -> convertToDataUri( $inline_image['content'], $inline_image['mime'] );
if ( $data_uri !== '' )
$cid_to_data_uri[$cid] = $data_uri;
$img_name = trim( $inline_image['name'] );
if ( $img_name === '' )
$img_name = 'inline_' . md5( $cid ) . '.' . $this -> guessExtensionFromMime( $inline_image['mime'] );
$result = $this -> attachments -> uploadFromContent( $task_id, self::TASK_USER_ID, $img_name, $inline_image['content'] );
if ( is_array( $result ) && $result['status'] === 'success' )
$cid_to_url[$cid] = '/upload/task_attachments/' . $result['relative_path'] . '/' . $result['stored_name'];
}
}
// Jeśli są inline images i HTML, zastąp CIDy na Base64 data URI i użyj HTML jako treść
if ( !empty( $cid_to_data_uri ) && isset( $content['html'] ) && trim( $content['html'] ) !== '' )
// Jeśli jest HTML, zastąp CIDy na URLe załączników i wyczyść style
if ( isset( $content['html'] ) && trim( $content['html'] ) !== '' )
{
$html_with_images = $this -> replaceCidReferences( $content['html'], $cid_to_data_uri );
$task_text = $this -> prepareImportedTaskTextFromHtml( $html_with_images );
$html_clean = $content['html'];
if ( !empty( $cid_to_url ) )
$html_clean = $this -> replaceCidReferences( $html_clean, $cid_to_url );
$task_text = $this -> prepareImportedTaskTextFromHtml( $html_clean );
// Zaktualizuj treść zadania
$this -> mdb -> update( 'tasks', [ 'text' => $task_text ], [ 'id' => $task_id ] );
@@ -1041,18 +1047,20 @@ class MailToTaskImporter
return '';
}
private function convertToDataUri( $content, $mime_type )
private function guessExtensionFromMime( $mime )
{
$content = (string)$content;
if ( $content === '' )
return '';
$map = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
'image/webp' => 'webp',
'image/bmp' => 'bmp',
'image/svg+xml' => 'svg',
'image/tiff' => 'tiff'
];
$mime_type = trim( (string)$mime_type );
if ( $mime_type === '' || $mime_type === 'application/octet-stream' )
$mime_type = 'image/png'; // Domyślny typ dla obrazów
$base64 = base64_encode( $content );
return 'data:' . $mime_type . ';base64,' . $base64;
$mime = strtolower( trim( (string)$mime ) );
return isset( $map[$mime] ) ? $map[$mime] : 'png';
}
private function replaceCidReferences( $html, array $cid_to_url )
@@ -1085,6 +1093,21 @@ class MailToTaskImporter
$html = preg_replace( '/<blockquote\b[^>]*>.*?<\/blockquote>/is', ' ', $html );
$html = preg_replace( '/<div[^>]*class="[^"]*(gmail_quote|gmail_signature)[^"]*"[^>]*>.*?<\/div>/is', ' ', $html );
// Usuń tagi MS Office: <o:p>, </o:p>, <w:sdt>, itp.
$html = preg_replace( '/<\/?[a-z]+:[^>]*>/is', '', $html );
// Usuń xmlns atrybuty
$html = preg_replace( '/\s+xmlns:[a-z]+="[^"]*"/i', '', $html );
// Usuń atrybuty class (MsoNormal, itp.)
$html = preg_replace( '/\s+class="[^"]*"/i', '', $html );
// Usuń atrybuty style
$html = preg_replace( '/\s+style="[^"]*"/i', '', $html );
// Usuń puste paragrafy (z samym &nbsp; lub spacjami)
$html = preg_replace( '/<p[^>]*>\s*(&nbsp;|\xC2\xA0)?\s*<\/p>/i', '', $html );
// Usuń niepotrzebne atrybuty z obrazów (zostaw tylko src, alt, width, height)
$html = preg_replace_callback(
'/<img([^>]*)>/i',
@@ -1092,16 +1115,8 @@ class MailToTaskImporter
$attrs = $matches[1];
$new_attrs = [];
// Wyciągnij ważne atrybuty
if ( preg_match( '/\bsrc=["\']([^"\']+)["\']/i', $attrs, $src ) )
{
// Nie używaj htmlspecialchars dla data URI (Base64), tylko dla zwykłych URLi
$src_value = $src[1];
if ( strpos( $src_value, 'data:' ) !== 0 )
$src_value = htmlspecialchars( $src_value, ENT_QUOTES );
$new_attrs[] = 'src="' . $src_value . '"';
}
$new_attrs[] = 'src="' . htmlspecialchars( $src[1], ENT_QUOTES ) . '"';
if ( preg_match( '/\balt=["\']([^"\']+)["\']/i', $attrs, $alt ) )
$new_attrs[] = 'alt="' . htmlspecialchars( $alt[1], ENT_QUOTES ) . '"';