SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/TinyMCE4RichText.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Helpers;
  15.  
  16. use Exception;
  17.  
  18. use Kohana;
  19.  
  20.  
  21. /**
  22. * Interface the display of a richtext field
  23. **/
  24. class TinyMCE4RichText extends RichText
  25. {
  26. /**
  27.   * Loads the required TinyMCE JS library
  28.   * @return void
  29.   */
  30. public static function needs()
  31. {
  32. // Use non-minified, local TinyMCE in dev environment if possible
  33. if (!IN_PRODUCTION and file_exists(DOCROOT . '/media/tinymce4/tinymce.js')) {
  34. Needs::addJavascriptInclude('ROOT/media/tinymce4/tinymce.js');
  35. } else {
  36. Needs::addJavascriptInclude('//cdnjs.cloudflare.com/ajax/libs/tinymce/4.6.3/tinymce.min.js');
  37. }
  38. Needs::fileGroup('tinymce4');
  39. }
  40.  
  41. /**
  42.   * Shows a richtext field. Should output content directly
  43.   *
  44.   * @param string $field_name The field name
  45.   * @param string $content The content of the richtext field, in HTML
  46.   * @param int $width The width of the field, in pixels
  47.   * @param int $height The height of the field, in pixels
  48.   * @param string $config_group Specific configuration to use instead of the default
  49.   **/
  50. protected function drawInternal($field_name, $content, $width = 600, $height = 300, $config_group = null)
  51. {
  52. self::needs();
  53.  
  54. $subsite = SubsiteSelector::$subsite_id;
  55.  
  56. $field_name_html = Enc::html($field_name);
  57. $field_name_class = 'mce4-' . Enc::id($field_name);
  58.  
  59. // Set up options
  60. $options = array();
  61. $options['selector'] = '.' . $field_name_class;
  62. $options['height'] = $height - 110; // Toolbars and status aren't included in 'height' for some reason
  63. $options['resize'] = true;
  64. $options['plugins'] = 'anchor code fullscreen image link paste searchreplace table lists visualblocks fullscreen contextmenu stylebuttons media';
  65. $options['menubar'] = false;
  66. $options['relative_urls'] = true;
  67. $options['branding'] = false;
  68. $options['external_plugins'] = [
  69. 'sprout_gallery' => Sprout::absRoot() . 'media/js/sprout_gallery.js',
  70. ];
  71.  
  72. if (Router::$controller == 'admin') {
  73. $subsite = @$_SESSION['admin']['active_subsite'];
  74. $options['document_base_url'] = rtrim(Subsites::getAbsRootAdmin(), '/') . '/';
  75. } else {
  76. $options['document_base_url'] = rtrim(Subsites::getAbsRoot($subsite), '/') . '/';
  77. }
  78.  
  79. //$options['paste_word_valid_elements'] = 'b,strong,i,em,h1,h2,h3,h4';
  80. $options['paste_webkit_styles'] = 'none';
  81. $options['paste_retain_style_properties'] = 'none';
  82. $options['object_resizing'] = 'img';
  83. $options['element_format'] = 'html';
  84. $options['object_resizing'] = 'img';
  85. $options['media_live_embeds'] = true;
  86.  
  87. // Image float fun
  88. $options['formats'] = array(
  89. 'alignleft' => array(array('selector' => 'img', 'collapsed' => false, 'classes' => 'left')),
  90. 'alignright' => array(array('selector' => 'img', 'collapsed' => false, 'classes' => 'right')),
  91. );
  92.  
  93. // If a config group isn't specified, use one from the config
  94. if ($config_group === null) {
  95. $config_group = Kohana::config('tinymce4.default_group', false, false);
  96. }
  97.  
  98. // If still no config found (e.g. no config file), fall-back to a default
  99. if ($config_group === null) {
  100. $options['toolbar'] = array(
  101. 'bold italic strikethrough subscript superscript link unlink anchor | removeformat | code fullscreen',
  102. 'styleselect | style-h2 style-h3 style-h4 style-p | bullist numlist indent outdent | alignleft alignright | image media table'
  103. );
  104. } else {
  105. $config_options = Kohana::config('tinymce4.' . $config_group, false, false);
  106. if ($config_options === null) {
  107. throw new Exception('Invalid config group "' . $config_group . '"');
  108. } else {
  109. $options += $config_options;
  110. }
  111. }
  112.  
  113. // Require "class" for SPAN elements, there isn't any point of a span otherwise
  114. // This also fixes a webkit bug in lists
  115. if (empty($options['extended_valid_elements'])) {
  116. $options['extended_valid_elements'] = 'span[!class]';
  117. } else {
  118. $options['extended_valid_elements'] .= ',span[!class]';
  119. }
  120.  
  121. // Formats dropdown menu
  122. if (empty($options['style_formats'])) {
  123. $options['style_formats'] = array(
  124. array('title' => 'Headings', 'items' => array(
  125. array('title' => 'Heading 2', 'format' => 'h2'),
  126. array('title' => 'Heading 3', 'format' => 'h3'),
  127. array('title' => 'Heading 4', 'format' => 'h4'),
  128. )),
  129. array('title' => 'Block', 'items' => array(
  130. array('title' => 'Paragraph', 'format' => 'p'),
  131. array('title' => 'Blockquote', 'format' => 'blockquote'),
  132. )),
  133. array('title' => 'Inline', 'items' => array(
  134. array('title' => 'Bold', 'format' => 'bold'),
  135. array('title' => 'Italic', 'format' => 'italic'),
  136. )),
  137. array('title' => 'Wrappers', 'items' => array(
  138. array('title' => 'Expando', 'block' => 'div', 'classes' => 'expando', 'wrapper' => true),
  139. array('title' => 'Highlight', 'block' => 'div', 'classes' => 'highlight', 'wrapper' => true),
  140. array('title' => 'Highlight to the right', 'block' => 'div', 'classes' => 'highlight--right', 'wrapper' => true),
  141. array('title' => 'Highlight to the left', 'block' => 'div', 'classes' => 'highlight--left', 'wrapper' => true),
  142. )),
  143. );
  144. }
  145.  
  146. // CSS file: richtext.css, content.css
  147. $options['content_css'] = array();
  148. $options['content_css'][] = Sprout::absRoot() . 'media/css/richtext.css?ts=' . time();
  149. if (file_exists(DOCROOT . 'skin/' . Subsites::getCode($subsite) . '/css/richtext.css')) {
  150. $options['content_css'][] = Sprout::absRoot() . 'skin/' . Subsites::getCode($subsite) . '/css/richtext.css?ts=' . time();
  151. } else {
  152. $options['content_css'][] = Sprout::absRoot() . 'skin/' . Subsites::getCode($subsite) . '/css/content.css?ts=' . time();
  153. }
  154.  
  155. // Javascript which makes the field work
  156. $out = '<script type="text/javascript">TinyMCE4.init(' . json_encode($options) . ');</script>';
  157.  
  158. // Include the field itself
  159. $out .= "<div>";
  160. $out .= "<textarea name=\"{$field_name_html}\" style=\"height: {$height}px;\"";
  161. $out .= " class=\"richtext-editor tinymce4-editor {$field_name_class}\" data-field-name=\"{$field_name_html}\">";
  162. $out .= Enc::html($content);
  163. $out .= "</textarea>\n";
  164. $out .= "</div>\n";
  165.  
  166. return $out;
  167. }
  168.  
  169. }
  170.  
  171.  
  172.