<?php
class cmsWysiwygTinymce {
private static $redactor_loaded = false;
private $buttons = [
'|','bold','italic','underline','strikethrough','alignleft','aligncenter','alignright','alignjustify','alignnone','styles','blocks','fontfamily','fontsize','cut','copy','paste','outdent','indent','blockquote','undo','redo','removeformat','subscript','superscript','visualaid','insert','forecolor','backcolor'
];
private $block_formats = [
'p' => LANG_TINYMCE_P,
'h2' => LANG_TITLE.' 2',
'h3' => LANG_TITLE.' 3',
'h4' => LANG_TITLE.' 4',
'h5' => LANG_TITLE.' 5',
'h6' => LANG_TITLE.' 6'
];
private $quickbars_selection_buttons = [
'bold', 'italic', 'underline', '|', 'quicklink', 'h2', 'h3', 'blockquote'
];
private $quickbars_insert_buttons = [
'quickimage', 'quicktable'
];
private $buttons_mapping = [
'wordcount','nonbreaking','media','insertdatetime','image','fullscreen','code',
'charmap','anchor','smiles', 'emoticons',
'codesample' => [
'codesample'
],
'icmsspoiler' => [
'spoiler-add'
],
'lists' => [
'bullist', 'numlist'
],
'link' => [
'link', 'unlink', 'openlink'
],
'table' => [
'table', 'tabledelete', 'tablecellprops', 'tablemergecells', 'tablesplitcells', 'tableinsertrowbefore',
'tableinsertrowafter', 'tabledeleterow', 'tablerowprops', 'tablecutrow', 'tablecopyrow', 'tablepasterowbefore',
'tablepasterowafter', 'tableinsertcolbefore', 'tableinsertcolafter', 'tabledeletecol'
]
];
private $options = [
'plugins' => [
'autoresize'
],
'text_patterns' => [
['start' => '>', 'format' => 'blockquote'],
['start' => '1. ', 'cmd' => 'InsertOrderedList', 'trigger' => 'enter'],
['start' => '* ', 'cmd' => 'InsertUnorderedList', 'trigger' => 'enter']
],
'codesample_languages' => [
['text' => 'HTML/XML', 'value' => 'html'],
['text' => 'PHP', 'value' => 'php'],
['text' => 'JavaScript', 'value' => 'javascript'],
['text' => 'CSS', 'value' => 'css'],
['text' => 'SQL', 'value' => 'sql'],
['text' => 'Bash', 'value' => 'bash'],
],
'toolbar' => 'blocks | bold italic strikethrough forecolor backcolor | link image media table | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat',
'min_height' => 200,
'max_height' => 700,
'browser_spellcheck' => true,
'contextmenu' => false,
'menubar' => false,
'statusbar' => false,
'relative_urls' => false,
'convert_urls' => false,
'paste_data_images' => true,
'highlight_on_focus' => true,
'link_quicklink' => true,
'link_context_toolbar' => true,
'image_caption' => false,
'toolbar_mode' => 'floating',
'toolbar_sticky' => false,
'spoiler_caption' => LANG_TINYMCE_SP,
'resize' => 'both',
'theme' => 'silver',
'mobile' => [
'theme' => 'silver'
],
'smiles_url' => false,
'file_picker_types' => 'file media',
'file_upload' => [],
'allow_mime_types' => [],
'skin' => 'oxide',
'images_preset' => 'big',
'placeholder' => '',
'license_key' => 'gpl',
'referrer_policy' => 'origin'
];
public function __construct($config = []) {
$this->options = array_replace_recursive($this->options, $config);
if(!$this->options['plugins']){
$this->options['plugins'] = [];
}
$user = cmsUser::getInstance();
$core = cmsCore::getInstance();
$lang = cmsCore::getLanguageName();
if($lang !== 'en'){
$this->options['language'] = $lang;
}
// формируем плагины по кнопкам тулбаров
$toolbar = explode(' ', preg_replace('#\s+#', ' ', $this->options['toolbar']));
$quickbars_selection_toolbar = !empty($this->options['quickbars_selection_toolbar']) ? explode(' ', preg_replace('#\s+#', ' ', $this->options['quickbars_selection_toolbar'])) : [];
$quickbars_insert_toolbar = !empty($this->options['quickbars_insert_toolbar']) ? explode(' ', preg_replace('#\s+#', ' ', $this->options['quickbars_insert_toolbar'])) : [];
foreach ($this->buttons_mapping as $pname => $buttons) {
if(is_numeric($pname)){
$pname = $buttons;
$buttons = [$pname];
}
if(in_array($pname, $this->options['plugins'])){
continue;
}
foreach ($buttons as $button) {
if(in_array($button, $toolbar)){
$this->options['plugins'][] = $pname;
}
if(in_array($button, $quickbars_selection_toolbar)){
$this->options['plugins'][] = $pname;
}
if(in_array($button, $quickbars_insert_toolbar)){
$this->options['plugins'][] = $pname;
}
}
}
$this->options['plugins'] = array_unique($this->options['plugins']);
if ($user->is_logged) {
$context = $core->getUriData();
$upload_params = ['csrf_token' => cmsForm::getCSRFToken()];
if($context['controller']){
$upload_params['target_controller'] = $context['controller'];
}
if($context['action']){
$upload_params['target_subject'] = mb_substr($context['action'], 0, 32);
}
if(strpos($core->uri, '/add/') === false && !empty($context['params'][1]) && is_numeric($context['params'][1])){
$upload_params['target_id'] = $context['params'][1];
}
$upload_params_string = '?'.http_build_query($upload_params);
$this->options['images_upload_url'] = href_to('images', 'upload_with_preset', ['file', $this->options['images_preset']]).$upload_params_string;
$this->options['image_list'] = href_to('files', 'files_list', ['image']).$upload_params_string;
// В allow_mime_types расширения файлов, так уж получилось :)
if (!empty($this->options['allow_mime_types'])) {
$allowed_ext = [];
foreach ($user->groups as $group_id) {
if (!empty($this->options['allow_mime_types'][$group_id])) {
foreach ($this->options['allow_mime_types'][$group_id] as $file_ext) {
if (!in_array($file_ext, $allowed_ext)) {
$allowed_ext[] = $file_ext;
}
}
}
}
if ($allowed_ext) {
unset($upload_params['csrf_token']);
cmsUser::sessionSet('ww_allowed_file_ext' . ($upload_params ? ':' . implode(':', $upload_params) : ''), $allowed_ext);
$this->options['file_upload'] = [
'url' => href_to('files', 'upload_with_wysiwyg', ['inline_upload_file']) . $upload_params_string
];
}
}
}
$this->options['smiles_url'] = href_to('typograph', 'get_smiles');
$this->options['plugins'] = implode(' ', $this->options['plugins']);
if(!empty($this->options['block_formats'])){
$block_formats = [];
foreach ($this->options['block_formats'] as $tag) {
$block_formats[] = $this->block_formats[$tag].'='.$tag.';';
}
$this->options['block_formats'] = implode(' ', $block_formats);
} else {
unset($this->options['block_formats']);
}
foreach ($this->options as $key => $value) {
if(!$value && !is_string($value)){
$this->options[$key] = false;
continue;
}
if($value === 1){
$this->options[$key] = true;
continue;
}
if(is_numeric($value)){
$this->options[$key] = intval($value);
continue;
}
}
}
public function displayEditor($field_name, $content = '', $config = []){
$this->loadRedactor();
$dom_id = isset($this->options['id']) ? $this->options['id'] : 'wysiwyg-' . uniqid(); unset($this->options['id']);
if($dom_id){
if(!empty($this->options['wysiwyg_toolbar'])){
echo '<div data-field_id="'.$dom_id.'" id="wysiwyg_toolbar_'.$dom_id.'" class="wysiwyg_toolbar_wrap">'.$this->options['wysiwyg_toolbar'].'</div>';
unset($this->options['wysiwyg_toolbar']);
}
echo html_textarea($field_name, $content, ['id' => $dom_id, 'class' => 'tinymce_redactor']);
}
ob_start(); ?>
<script>
<?php if($dom_id){ ?>
tiny_global_options['field_<?php echo $dom_id; ?>'] = <?php echo json_encode($this->options, JSON_UNESCAPED_UNICODE); ?>;
$(function(){
init_tinymce('<?php echo $dom_id; ?>');
});
<?php } else { ?>
tiny_global_options['default'] = <?php echo json_encode($this->options, JSON_UNESCAPED_UNICODE); ?>;
<?php } ?>
</script>
<?php cmsTemplate::getInstance()->addBottom(ob_get_clean());
}
private function loadRedactor() {
if(self::$redactor_loaded){ return false; }
$template = cmsTemplate::getInstance();
$template->addJSFromContext('wysiwyg/tinymce/files/tinymce.min.js');
$template->addTplJSNameFromContext('files');
$template_css = $template->getTemplateStylesFileName('theme');
if($template_css){
$template_css = $template->getHeadFilePath($template_css);
}
ob_start(); ?>
<script>
var tiny_global_options = {};
function init_tinymce (dom_id, callback){
var tinymce_options = {};
if(tiny_global_options.hasOwnProperty('field_'+dom_id)){
tinymce_options = tiny_global_options['field_'+dom_id];
} else if(tiny_global_options.hasOwnProperty('default')) {
tinymce_options = tiny_global_options.default;
}
icms.files.url_delete = '<?php echo href_to('files', 'delete'); ?>';
tinymce_options.selector = '#'+dom_id;
tinymce_options.init_instance_callback = function (editor) {
editor.on('KeyDown', function (e) {
if ((e.keyCode === 8 || e.keyCode === 46) && editor.selection) {
var selectedNode = editor.selection.getNode();
if (selectedNode && selectedNode.nodeName === 'IMG' && !$(selectedNode).hasClass('smile_image') && confirm('<?php echo LANG_PARSER_IMAGE_DELETE; ?>')) {
icms.files.deleteByPath($(selectedNode).data('mce-src'));
}
}
});
if (typeof(callback) === 'function') {
callback(editor);
}
};
tinymce_options.setup = function (editor) {
editor.addShortcut(
'ctrl+13', 'ctr + enter submit', function () {
$('#'+dom_id).trigger('keydown', [{keyCode: 13, ctrlKey: true}]);
});
};
<?php if($template_css){ ?>
tinymce_options.content_css = '<?php echo $template_css; ?>';
<?php } ?>
tinymce.init(tinymce_options);
icms.forms.addWysiwygsInsertPool(dom_id, function(field_element, text){
tinymce.activeEditor.setContent(text);
tinymce.activeEditor.focus();
});
icms.forms.addWysiwygsAddPool(dom_id, function(field_element, text){
tinymce.activeEditor.insertContent(text);
});
icms.forms.addWysiwygsInitPool(dom_id, function(field_element, callback){
tinymce.remove('#'+field_element);
init_tinymce(field_element, callback);
});
icms.forms.addWysiwygsSavePool(dom_id, function(field_element){
tinymce.activeEditor.save();
});
}
</script>
<?php $template->addBottom(ob_get_clean());
self::$redactor_loaded = true;
}
public function getParams() {
$plugins = cmsCore::getDirsList('wysiwyg/tinymce/files/plugins', true);
$hidden_plugins = ['code'];
$buttons = $this->buttons;
$buttons_mapping = $this->buttons_mapping;
// убираем плагины, которые подключатся автоматически при назначении кнопок
foreach ($buttons_mapping as $plugin_name => $pbtns) {
if(is_numeric($plugin_name)){
$plugin_name = $pbtns;
$pbtns = [$plugin_name];
}
$key = array_search($plugin_name, $plugins);
if($key !== false){
unset($plugins[$key]);
}
foreach ($pbtns as $pbtn) {
$buttons[] = $pbtn;
}
}
// убираем скрытые плагины, которые включаются в самом классе редактора
foreach ($hidden_plugins as $hidden_plugin) {
$key = array_search($hidden_plugin, $plugins);
if($key !== false){
unset($plugins[$key]);
}
}
return cmsEventsManager::hook('wysiwyg_tinymce_form_options', [$plugins, $buttons, $this->quickbars_insert_buttons, $this->quickbars_selection_buttons, $this->block_formats]);
}
}