fckeditor.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <?php
  2. /**
  3. * @file
  4. * Editor integration functions for FCKeditor.
  5. */
  6. /**
  7. * Plugin implementation of hook_editor().
  8. */
  9. function wysiwyg_fckeditor_editor() {
  10. $editor['fckeditor'] = array(
  11. 'title' => 'FCKeditor',
  12. 'vendor url' => 'http://www.fckeditor.net',
  13. 'download url' => 'http://www.fckeditor.net/download',
  14. 'libraries' => array(
  15. '' => array(
  16. 'title' => 'Default',
  17. 'files' => array('fckeditor.js'),
  18. ),
  19. ),
  20. 'version callback' => 'wysiwyg_fckeditor_version',
  21. 'themes callback' => 'wysiwyg_fckeditor_themes',
  22. 'settings callback' => 'wysiwyg_fckeditor_settings',
  23. 'plugin callback' => 'wysiwyg_fckeditor_plugins',
  24. 'plugin settings callback' => 'wysiwyg_fckeditor_plugin_settings',
  25. 'proxy plugin' => array(
  26. 'drupal' => array(
  27. 'load' => TRUE,
  28. 'proxy' => TRUE,
  29. ),
  30. ),
  31. 'proxy plugin settings callback' => 'wysiwyg_fckeditor_proxy_plugin_settings',
  32. 'versions' => array(
  33. '2.6' => array(
  34. 'js files' => array('fckeditor-2.6.js'),
  35. ),
  36. ),
  37. );
  38. return $editor;
  39. }
  40. /**
  41. * Detect editor version.
  42. *
  43. * @param $editor
  44. * An array containing editor properties as returned from hook_editor().
  45. *
  46. * @return
  47. * The installed editor version.
  48. */
  49. function wysiwyg_fckeditor_version($editor) {
  50. $library = $editor['library path'] . '/fckeditor.js';
  51. if (!file_exists($library)) {
  52. return;
  53. }
  54. $library = fopen($library, 'r');
  55. $max_lines = 100;
  56. while ($max_lines && $line = fgets($library, 60)) {
  57. if (preg_match('@^FCKeditor.prototype.Version\s*= \'([\d\.]+)@', $line, $version)) {
  58. fclose($library);
  59. return $version[1];
  60. }
  61. $max_lines--;
  62. }
  63. fclose($library);
  64. }
  65. /**
  66. * Determine available editor themes or check/reset a given one.
  67. *
  68. * @param $editor
  69. * A processed hook_editor() array of editor properties.
  70. * @param $profile
  71. * A wysiwyg editor profile.
  72. *
  73. * @return
  74. * An array of theme names. The first returned name should be the default
  75. * theme name.
  76. */
  77. function wysiwyg_fckeditor_themes($editor, $profile) {
  78. return array('default', 'office2003', 'silver');
  79. }
  80. /**
  81. * Return runtime editor settings for a given wysiwyg profile.
  82. *
  83. * @param $editor
  84. * A processed hook_editor() array of editor properties.
  85. * @param $config
  86. * An array containing wysiwyg editor profile settings.
  87. * @param $theme
  88. * The name of a theme/GUI/skin to use.
  89. *
  90. * @return
  91. * A settings array to be populated in
  92. * Drupal.settings.wysiwyg.configs.{editor}
  93. */
  94. function wysiwyg_fckeditor_settings($editor, $config, $theme) {
  95. $settings = array(
  96. 'EditorPath' => base_path() . $editor['library path'] . '/',
  97. 'SkinPath' => base_path() . $editor['library path'] . '/editor/skins/' . $theme . '/',
  98. 'CustomConfigurationsPath' => base_path() . drupal_get_path('module', 'wysiwyg') . '/editors/js/fckeditor.config.js',
  99. 'Width' => '100%',
  100. 'Height' => 420,
  101. 'LinkBrowser' => FALSE,
  102. 'LinkUpload' => FALSE,
  103. 'ImageBrowser' => FALSE,
  104. 'ImageUpload' => FALSE,
  105. 'FlashBrowser' => FALSE,
  106. 'FlashUpload' => FALSE,
  107. // By default, FCKeditor converts most characters into HTML entities. Since
  108. // it does not support a custom definition, but Drupal supports Unicode, we
  109. // disable at least the additional character sets. FCKeditor always converts
  110. // XML default characters '&', '<', '>'.
  111. // @todo Check whether completely disabling ProcessHTMLEntities is an option.
  112. 'IncludeLatinEntities' => FALSE,
  113. 'IncludeGreekEntities' => FALSE,
  114. );
  115. if (isset($config['block_formats'])) {
  116. $settings['FontFormats'] = strtr($config['block_formats'], array(',' => ';'));
  117. }
  118. if (isset($config['apply_source_formatting'])) {
  119. $settings['FormatOutput'] = $settings['FormatSource'] = $config['apply_source_formatting'];
  120. }
  121. if (isset($config['paste_auto_cleanup_on_paste'])) {
  122. $settings['AutoDetectPasteFromWord'] = $config['paste_auto_cleanup_on_paste'];
  123. }
  124. if (isset($config['css_setting'])) {
  125. if ($config['css_setting'] == 'theme') {
  126. $settings['EditorAreaCSS'] = implode(',', wysiwyg_get_css());
  127. }
  128. elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
  129. $settings['EditorAreaCSS'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => drupal_get_path('theme', variable_get('theme_default', NULL))));
  130. }
  131. }
  132. // Use our custom toolbar set.
  133. $settings['ToolbarSet'] = 'Wysiwyg';
  134. // Populate our custom toolbar set for fckeditor.config.js.
  135. $settings['buttons'] = array();
  136. if (!empty($config['buttons'])) {
  137. $plugins = wysiwyg_get_plugins($editor['name']);
  138. foreach ($config['buttons'] as $plugin => $buttons) {
  139. foreach ($buttons as $button => $enabled) {
  140. // Iterate separately over buttons and extensions properties.
  141. foreach (array('buttons', 'extensions') as $type) {
  142. // Skip unavailable plugins.
  143. if (!isset($plugins[$plugin][$type][$button])) {
  144. continue;
  145. }
  146. // Add buttons.
  147. if ($type == 'buttons') {
  148. $settings['buttons'][] = $button;
  149. }
  150. // Allow plugins to add or override global configuration settings.
  151. if (!empty($plugins[$plugin]['options'])) {
  152. $settings = array_merge($settings, $plugins[$plugin]['options']);
  153. }
  154. }
  155. }
  156. }
  157. }
  158. // For now, all buttons are placed into one row.
  159. $settings['buttons'] = array($settings['buttons']);
  160. return $settings;
  161. }
  162. /**
  163. * Build a JS settings array of native external plugins that need to be loaded separately.
  164. */
  165. function wysiwyg_fckeditor_plugin_settings($editor, $profile, $plugins) {
  166. $settings = array();
  167. foreach ($plugins as $name => $plugin) {
  168. // Register all plugins that need to be loaded.
  169. if (!empty($plugin['load'])) {
  170. $settings[$name] = array();
  171. // Add path for native external plugins; internal ones do not need a path.
  172. if (empty($plugin['internal']) && isset($plugin['path'])) {
  173. // All native FCKeditor plugins use the filename fckplugin.js.
  174. $settings[$name]['path'] = base_path() . $plugin['path'] . '/';
  175. }
  176. if (!empty($plugin['languages'])) {
  177. $settings[$name]['languages'] = $plugin['languages'];
  178. }
  179. }
  180. }
  181. return $settings;
  182. }
  183. /**
  184. * Build a JS settings array for Drupal plugins loaded via the proxy plugin.
  185. */
  186. function wysiwyg_fckeditor_proxy_plugin_settings($editor, $profile, $plugins) {
  187. $settings = array();
  188. foreach ($plugins as $name => $plugin) {
  189. // Populate required plugin settings.
  190. $settings[$name] = $plugin['dialog settings'] + array(
  191. 'title' => $plugin['title'],
  192. 'icon' => base_path() . $plugin['icon path'] . '/' . $plugin['icon file'],
  193. 'iconTitle' => $plugin['icon title'],
  194. // @todo These should only be set if the plugin defined them.
  195. 'css' => base_path() . $plugin['css path'] . '/' . $plugin['css file'],
  196. );
  197. }
  198. return $settings;
  199. }
  200. /**
  201. * Return internal plugins for this editor; semi-implementation of hook_wysiwyg_plugin().
  202. */
  203. function wysiwyg_fckeditor_plugins($editor) {
  204. $plugins = array(
  205. 'default' => array(
  206. 'buttons' => array(
  207. 'Bold' => t('Bold'), 'Italic' => t('Italic'), 'Underline' => t('Underline'),
  208. 'StrikeThrough' => t('Strike-through'),
  209. 'JustifyLeft' => t('Align left'), 'JustifyCenter' => t('Align center'), 'JustifyRight' => t('Align right'), 'JustifyFull' => t('Justify'),
  210. 'UnorderedList' => t('Bullet list'), 'OrderedList' => t('Numbered list'),
  211. 'Outdent' => t('Outdent'), 'Indent' => t('Indent'),
  212. 'Undo' => t('Undo'), 'Redo' => t('Redo'),
  213. 'Link' => t('Link'), 'Unlink' => t('Unlink'), 'Anchor' => t('Anchor'),
  214. 'Image' => t('Image'),
  215. 'TextColor' => t('Forecolor'), 'BGColor' => t('Backcolor'),
  216. 'Superscript' => t('Superscript'), 'Subscript' => t('Subscript'),
  217. 'Blockquote' => t('Blockquote'), 'Source' => t('Source code'),
  218. 'Rule' => t('Horizontal rule'),
  219. 'Cut' => t('Cut'), 'Copy' => t('Copy'), 'Paste' => t('Paste'),
  220. 'PasteText' => t('Paste Text'), 'PasteWord' => t('Paste from Word'),
  221. 'ShowBlocks' => t('Show blocks'),
  222. 'RemoveFormat' => t('Remove format'),
  223. 'SpecialChar' => t('Character map'),
  224. 'About' => t('About'),
  225. 'FontFormat' => t('HTML block format'), 'FontName' => t('Font'), 'FontSize' => t('Font size'), 'Style' => t('Font style'),
  226. 'Table' => t('Table'),
  227. 'Find' => t('Search'), 'Replace' => t('Replace'), 'SelectAll' => t('Select all'),
  228. 'CreateDiv' => t('Create DIV container'),
  229. 'Flash' => t('Flash'), 'Smiley' => t('Smiley'),
  230. 'FitWindow' => t('FitWindow'),
  231. 'SpellCheck' => t('Check spelling'),
  232. ),
  233. 'internal' => TRUE,
  234. ),
  235. 'autogrow' => array(
  236. 'path' => $editor['library path'] . '/editor/plugins',
  237. 'extensions' => array(
  238. 'autogrow' => t('Autogrow'),
  239. ),
  240. 'options' => array(
  241. 'AutoGrowMax' => 800,
  242. ),
  243. 'internal' => TRUE,
  244. 'load' => TRUE,
  245. ),
  246. 'bbcode' => array(
  247. 'path' => $editor['library path'] . '/editor/plugins',
  248. 'extensions' => array(
  249. 'bbcode' => t('BBCode'),
  250. ),
  251. 'internal' => TRUE,
  252. 'load' => TRUE,
  253. ),
  254. 'dragresizetable' => array(
  255. 'path' => $editor['library path'] . '/editor/plugins',
  256. 'extensions' => array(
  257. 'dragresizetable' => t('Table drag/resize'),
  258. ),
  259. 'internal' => TRUE,
  260. 'load' => TRUE,
  261. ),
  262. 'tablecommands' => array(
  263. 'path' => $editor['library path'] . '/editor/plugins',
  264. 'buttons' => array(
  265. 'TableCellProp' => t('Table: Cell properties'),
  266. 'TableInsertRowAfter' => t('Table: Insert row after'),
  267. 'TableInsertColumnAfter' => t('Table: Insert column after'),
  268. 'TableInsertCellAfter' => t('Table: Insert cell after'),
  269. 'TableDeleteRows' => t('Table: Delete rows'),
  270. 'TableDeleteColumns' => t('Table: Delete columns'),
  271. 'TableDeleteCells' => t('Table: Delete cells'),
  272. 'TableMergeCells' => t('Table: Merge cells'),
  273. 'TableHorizontalSplitCell' => t('Table: Horizontal split cell'),
  274. ),
  275. 'internal' => TRUE,
  276. 'load' => TRUE,
  277. ),
  278. );
  279. return $plugins;
  280. }