View file upload/engine/editor/comments.php

File size: 14.29Kb
<?php
/*
=====================================================
 DataLife Engine - by SoftNews Media Group
-----------------------------------------------------
 https://dle-news.ru/
-----------------------------------------------------
 Copyright (c) 2004-2025 SoftNews Media Group
=====================================================
 This code is protected by copyright
=====================================================
 File: comments.php
-----------------------------------------------------
 Use: WYSIWYG for comments
=====================================================
*/

if( !defined( 'DATALIFEENGINE' ) ) {
	header( "HTTP/1.1 403 Forbidden" );
	header ( 'Location: ../../' );
	die( "Hacking attempt!" );
}

$p_id = isset($p_id) ? intval($p_id) : 0;
$p_name= isset($p_name) ? $p_name : '';
$comments_image_uploader_loaded = isset($comments_image_uploader_loaded) ? $comments_image_uploader_loaded : false;
$comments_mobile_editor = isset($comments_mobile_editor) ? $comments_mobile_editor : false;

$dark_theme = "";

if (defined('TEMPLATE_DIR')) {
	$template_dir = TEMPLATE_DIR;
} else $template_dir = ROOT_DIR . "/templates/" . $config['skin'];

if (is_file($template_dir . "/info.json")) {

	$data = json_decode(trim(file_get_contents($template_dir . "/info.json")), true);

	if (isset($data['type']) and $data['type'] == "dark") {
		$dark_theme = " dle_theme_dark";
	}
}

$e_plugins = '';

if ($user_group[$member_id['user_group']]['allow_url']) { $link_icon = "link unlink dleleech "; $e_plugins = 'link autolink '; } else $link_icon = "";

$mobile_link_icon = $link_icon;

if ($user_group[$member_id['user_group']]['allow_image']) {
	
	if($config['bbimages_in_wysiwyg']) {
		
		$link_icon .= "| dleimage ";
		
	} else {
		$link_icon .= "| image ";
	}

	$e_plugins .= 'image ';
}

$image_upload = array();

if ( $user_group[$member_id['user_group']]['allow_up_image'] ) {

	if(!$comments_image_uploader_loaded) {
			$link_icon .= "dleupload ";
			$mobile_link_icon .= "dleupload ";
	}

	$image_upload[1] = <<<HTML
var dle_image_upload_handler = (blobInfo, progress) => new Promise((resolve, reject) => {
  var xhr, formData;

  xhr = new XMLHttpRequest();
  xhr.withCredentials = false;
  xhr.open('POST', dle_root + 'index.php?controller=ajax&mod=upload');
  
  xhr.upload.onprogress = (e) => {
    progress(e.loaded / e.total * 100);
  };

  xhr.onload = function() {
    var json;

    if (xhr.status === 403) {
      reject('HTTP Error: ' + xhr.status, { remove: true });
      return;
    }

    if (xhr.status < 200 || xhr.status >= 300) {
      reject('HTTP Error: ' + xhr.status);
      return;
    }

    json = JSON.parse(xhr.responseText);

    if (!json || typeof json.link != 'string') {

		if(typeof json.error == 'string') {
			reject(json.error);
		} else {
			reject('Invalid JSON: ' + xhr.responseText);	
		}
		
		var editor = tinymce.activeEditor;
		var node = editor.selection.getEnd();
		editor.selection.select(node);
		editor.insertContent('');
		
      return;
    }

	if( json.flink ) {
		
		resolve(json.link);

		setTimeout(() => {
			var editor = tinymce.activeEditor;
			if (!editor) return;

			var imageElement = editor.getBody().querySelector('img[src^="'+json.link+'"]');

			if (imageElement) {

				editor.dom.setStyles(imageElement, {
                	'display': 'block',
                	'margin-left': 'auto',
                	'margin-right': 'auto'
           		});

				var linkElement = editor.dom.create('a', {
					href: json.flink,
					class: 'highslide'
				});

				editor.dom.insertAfter(linkElement, imageElement);
				linkElement.appendChild(imageElement);
				var brElement = editor.dom.create('br');
            	editor.dom.insertAfter(brElement, linkElement);
				editor.selection.setCursorLocation(brElement, 0);
			}

		}, 100);

		$('#mediaupload').remove();

	} else {
		resolve(json.link);
		$('#mediaupload').remove();
	}
	
  };

  xhr.onerror = function () {
    reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
  };

  formData = new FormData();
  formData.append('qqfile', blobInfo.blob(), blobInfo.filename());
  formData.append("subaction", "upload");
  formData.append("news_id", "{$p_id}");
  formData.append("area", "comments");
  formData.append("author", "{$p_name}");
  formData.append("mode", "quickload");
  formData.append("editor_mode", "tinymce");
  formData.append("user_hash", "{$dle_login_hash}");
  
  xhr.send(formData);
});
HTML;

		$image_upload[2] = <<<HTML
paste_data_images: true,
automatic_uploads: true,
images_upload_handler: dle_image_upload_handler,
images_reuse_filename: true,
image_uploadtab: false,
images_file_types: 'gif,jpg,png,jpeg,bmp,webp,avif',
file_picker_types: 'image',

file_picker_callback: function (cb, value, meta) {
    const input = document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('accept', 'image/*');

    input.addEventListener('change', (e) => {
      const file = e.target.files[0];

		var filename = file.name;
		filename = filename.split('.').slice(0, -1).join('.');
	
      const reader = new FileReader();
      reader.addEventListener('load', () => {

        const id = filename;
        const blobCache =  tinymce.activeEditor.editorUpload.blobCache;
        const base64 = reader.result.split(',')[1];
        const blobInfo = blobCache.create(id, file, base64);
        blobCache.add(blobInfo);

        cb(blobInfo.blobUri());

      });
      reader.readAsDataURL(file);
    });

    input.click();
},
HTML;
		
	} else {
		
		$image_upload[0] = "";
		$image_upload[1] = "";
		$image_upload[2] = "paste_data_images: false,\n";
		
	}

	if ($user_group[$member_id['user_group']]['video_comments'] AND !$comments_mobile_editor) $link_icon .= "dlemp dlaudio ";

	if ($user_group[$member_id['user_group']]['media_comments'] AND !$comments_mobile_editor) $link_icon .= "dletube ";

	if( @file_exists( ROOT_DIR . '/templates/'. $config['skin'].'/editor.css' ) ) {
		
			$editor_css = "templates/{$config['skin']}/editor.css?v={$config['cache_id']}";
			
	} else $editor_css = "public/editor/css/content.css?v={$config['cache_id']}";

	$tiny_mce_conf = <<<HTML

	{$image_upload[1]}
	
	tinyMCE.baseURL = dle_root + 'public/editor/tiny_mce';
	tinyMCE.suffix = '.min';
	var dle_theme = '{$dark_theme}';
	dle_theme = dle_theme.trim();

	if(dle_theme != '') {
		$('body').addClass( dle_theme );
	} else {
		if ( $("body").hasClass('dle_theme_dark') ) {
			dle_theme = 'dle_theme_dark';
		}
	}
HTML;

	if( $comments_mobile_editor ) {

		$tiny_mce_conf .= <<<HTML
tinymce.init({
	selector: "textarea#comments",

	language : "{$lang['language_code']}",
	directionality: '{$lang['direction']}',
	body_class: dle_theme,
	skin: dle_theme == 'dle_theme_dark' ? 'oxide-dark' : 'oxide',
	content_css : dle_root + "{$editor_css}",
	element_format : 'html',
		
	width : "100%",
	min_height : 40,
	max_height : 250,

	deprecation_warnings: false,
	promotion: false,
	cache_suffix: '?v={$config['cache_id']}',
	license_key: 'gpl',
	plugins: "{$e_plugins}autoresize lists dlebutton codesample",
	
	draggable_modal: true,
	toolbar_mode: 'floating',
	contextmenu: false,
	relative_urls : false,
	convert_urls : false,
	remove_script_host : false,
	browser_spellcheck: true,
	extended_valid_elements : "div[align|style|class|data-commenttime|data-commentuser|data-commentid|data-commentpostid|data-commentgast|contenteditable],span[id|data-username|data-userurl|align|style|class|contenteditable],b/strong,i/em,u,s,p[align|style|class|contenteditable],pre[class],code",
	
	formats: {
		bold: {inline: 'b'},
		italic: {inline: 'i'},
		underline: {inline: 'u', exact : true},
		strikethrough: {inline: 's', exact : true}
	},
	paste_postprocess: (editor, args) => {
		args = DLEPasteSafeText(args, {$user_group[$member_id['user_group']]['allow_url']});
	},
	paste_as_text: true,
	elementpath: false,
	branding: false,
	text_patterns: [],
	dle_root : dle_root,
	dle_upload_area : "comments",
	dle_upload_user : "{$p_name}",
	dle_upload_news : "{$p_id}",

	link_default_target: '_blank',
	editable_class: 'contenteditable',
	noneditable_class: 'noncontenteditable',
	image_dimensions: true,
	{$image_upload[2]}

	toolbar: "formatgroup paragraphgroup insertgroup",
	placeholder: "{$lang['comm_placeholder']}",
	menubar: false,
	statusbar: false,
	toolbar_location: "bottom",
	object_resizing: false,
	contextmenu: false,
	autoresize_overflow_padding: 10,
	autoresize_bottom_margin: 1,

	toolbar_groups: {
		formatgroup: {
		icon: "format",
		tooltip: "Formatting",
		items:
			"bold italic underline strikethrough | removeformat"
		},
		paragraphgroup: {
		icon: "paragraph",
		tooltip: "Paragraph format",
		items:
			"bullist numlist | alignleft aligncenter alignright"
		},
		insertgroup: {
			icon: "plus",
			tooltip: "Insert",
			items: "dleemo {$link_icon} | dlequote dlespoiler dlehide"
		}
	},

	mobile: {
		toolbar_mode: "floating"
	},

	setup: (editor) => {

		const onCompeteAction = (autocompleteApi, rng, value) => {
			editor.selection.setRng(rng);
			editor.insertContent(value);
			autocompleteApi.hide();
		};

		editor.ui.registry.addAutocompleter('getusers', {
		trigger: '@',
		minChars: 1,
		columns: 1,
		onAction: onCompeteAction,
		fetch: (pattern) => {

			return new Promise((resolve) => {

				$.get(dle_root + "index.php?controller=ajax&mod=find_tags", { mode: 'users', term: pattern, skin: dle_skin, user_hash: dle_login_hash }, function(data){
					if ( data.found ) {
						resolve(data.items);
					}
				}, "json");

			});
		}
		});

		editor.on("focus", () => {
			$("#mobilewseditor").addClass("focused");
		});

		editor.on("blur", () => {
			$("#mobilewseditor").removeClass("focused");
		});

		editor.ui.registry.addContextToolbar("editimage", {
			predicate: (node) => {
				return node.nodeName.toLowerCase() === "img";
			},
			items: "editimage removeimage",
			position: "node",
			scope: "node"
		});

		editor.ui.registry.addButton("editimage", {
			icon: "edit-block",
			onAction: () => {
				editor.execCommand("mceImage");
			}
		});

		editor.ui.registry.addButton("removeimage", {
			icon: "remove",
			onAction: () => {
				const node = tinymce.activeEditor.selection.getNode();
				node.remove();
			}
		});
	}
});

HTML;

	} else {

		$tiny_mce_conf .= <<<HTML

	var additionalplugins = '';
	var maxheight = $(window).height() * .8;
	
	if (typeof getBaseSize === "function") {
		var height = 260 * getBaseSize();
	} else {
		var height = 260;
	}

	if($('body').hasClass('editor-autoheight')) {
       additionalplugins += ' autoresize';
    }

	tinymce.init({
		selector: 'textarea#comments',
		language : "{$lang['language_code']}",
		directionality: '{$lang['direction']}',
		body_class: dle_theme,
		skin: dle_theme == 'dle_theme_dark' ? 'oxide-dark' : 'oxide',
		element_format : 'html',
		width : "100%",
		height : height,
		min_height : 40,
		max_height: maxheight,
		autoresize_bottom_margin: 1,
		statusbar: false,
		deprecation_warnings: false,
		promotion: false,
		cache_suffix: '?v={$config['cache_id']}',
		license_key: 'gpl',
		plugins: "{$e_plugins}lists quickbars dlebutton codesample"+additionalplugins,
		
		draggable_modal: true,
		toolbar_mode: 'floating',
		contextmenu: false,
		relative_urls : false,
		convert_urls : false,
		remove_script_host : false,
		browser_spellcheck: true,
		extended_valid_elements : "div[align|style|class|data-commenttime|data-commentuser|data-commentid|data-commentpostid|data-commentgast|contenteditable],span[id|data-username|data-userurl|align|style|class|contenteditable],b/strong,i/em,u,s,p[align|style|class|contenteditable],pre[class],code",
		quickbars_insert_toolbar: '',
		quickbars_selection_toolbar: 'bold italic underline | dlequote dlespoiler dlehide',
		paste_postprocess: (editor, args) => {
			args = DLEPasteSafeText(args, {$user_group[$member_id['user_group']]['allow_url']});
		},
		paste_as_text: true,

	    formats: {
	      bold: {inline: 'b'},
	      italic: {inline: 'i'},
	      underline: {inline: 'u', exact : true},
	      strikethrough: {inline: 's', exact : true}
	    },

		elementpath: false,
		branding: false,
		text_patterns: [],
		dle_root : dle_root,
		dle_upload_area : "comments",
		dle_upload_user : "{$p_name}",
		dle_upload_news : "{$p_id}",
		
		menubar: false,
		link_default_target: '_blank',
		editable_class: 'contenteditable',
		noneditable_class: 'noncontenteditable',
		image_dimensions: true,
		{$image_upload[2]}
		
		toolbar: "bold italic underline | alignleft aligncenter alignright | bullist numlist | dleemo {$link_icon} | dlequote codesample dlespoiler dlehide",
		
		mobile: {
			toolbar_mode: "sliding",
			toolbar: "bold italic underline | alignleft aligncenter alignright | bullist numlist | dleemo {$mobile_link_icon} dlequote dlespoiler dlehide",
			
		},
		
		content_css : dle_root + "{$editor_css}",
		
		codesample_languages: [
			{ text: 'HTML/XML', value: 'markup' },
			{ text: 'JavaScript', value: 'javascript' },
			{ text: 'CSS', value: 'css' },
			{ text: 'PHP', value: 'php' },
			{ text: 'SQL', value: 'sql' },
			{ text: 'Ruby', value: 'ruby' },
			{ text: 'Python', value: 'python' },
			{ text: 'Java', value: 'java' },
			{ text: 'C', value: 'c' },
			{ text: 'C#', value: 'csharp' },
			{ text: 'C++', value: 'cpp' }
		],

		setup: (editor) => {

			const onCompeteAction = (autocompleteApi, rng, value) => {
				editor.selection.setRng(rng);
				editor.insertContent(value);
				autocompleteApi.hide();
			};

			editor.ui.registry.addAutocompleter('getusers', {
			trigger: '@',
			minChars: 1,
			columns: 1,
			onAction: onCompeteAction,
			fetch: (pattern) => {

				return new Promise((resolve) => {

					$.get(dle_root + "index.php?controller=ajax&mod=find_tags", { mode: 'users', term: pattern, skin: dle_skin, user_hash: dle_login_hash }, function(data){
						if ( data.found ) {
							resolve(data.items);
						}
					}, "json");

				});
			}
			});
		}

	});
HTML;

	}

	$onload_scripts[] = $tiny_mce_conf;
	unset($tiny_mce_conf);

	$wysiwyg = <<<HTML
<script>
	var text_upload = "{$lang['bb_t_up']}";
	var dle_quote_title  = "{$lang['i_quote']}";
</script>
HTML;

	if ($comments_mobile_editor) {

$wysiwyg .= <<<HTML
<div class="dleaddcomments-editor mobilewseditor dlecomments-editor{$dark_theme}" id="mobilewseditor">
  <textarea id="comments" name="comments" style="width:100%;height:40px;"></textarea>
</div>
HTML;

	} else {
		$wysiwyg .= <<<HTML
<div class="dleaddcomments-editor wseditor dlecomments-editor{$dark_theme}">
	<textarea id="comments" name="comments" style="width:100%;height:260px;"></textarea>
</div>
HTML;
	}