ckeditor.module 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <?php
  2. /**
  3. * CKEditor - The text editor for the Internet - http://ckeditor.com
  4. * Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
  5. *
  6. * == BEGIN LICENSE ==
  7. *
  8. * Licensed under the terms of any of the following licenses of your
  9. * choice:
  10. *
  11. * - GNU General Public License Version 2 or later (the "GPL")
  12. * http://www.gnu.org/licenses/gpl.html
  13. *
  14. * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
  15. * http://www.gnu.org/licenses/lgpl.html
  16. *
  17. * - Mozilla Public License Version 1.1 or later (the "MPL")
  18. * http://www.mozilla.org/MPL/MPL-1.1.html
  19. *
  20. * == END LICENSE ==
  21. *
  22. * @file
  23. * CKEditor Module for Drupal 7.x
  24. *
  25. * This module allows Drupal to replace textarea fields with CKEditor.
  26. *
  27. * CKEditor is an online rich text editor that can be embedded inside web pages.
  28. * It is a WYSIWYG (What You See Is What You Get) editor which means that the
  29. * text edited in it looks as similar as possible to the results end users will
  30. * see after the document gets published. It brings to the Web popular editing
  31. * features found in desktop word processors such as Microsoft Word and
  32. * OpenOffice.org Writer. CKEditor is truly lightweight and does not require any
  33. * kind of installation on the client computer.
  34. */
  35. /**
  36. * The name of the simplified toolbar that should be forced.
  37. * Make sure that this toolbar is defined in ckeditor.config.js or fckconfig.js.
  38. */
  39. define('CKEDITOR_FORCE_SIMPLE_TOOLBAR_NAME', 'DrupalBasic');
  40. define('CKEDITOR_ENTERMODE_P', 1);
  41. define('CKEDITOR_ENTERMODE_BR', 2);
  42. define('CKEDITOR_ENTERMODE_DIV', 3);
  43. global $_ckeditor_configuration;
  44. global $_ckeditor_ids;
  45. require_once('includes/ckeditor.user.inc');
  46. $_ckeditor_configuration = array();
  47. $_ckeditor_ids = array();
  48. /**
  49. * Implementation of hook_menu().
  50. */
  51. function ckeditor_menu() {
  52. $items = array();
  53. $items['ckeditor/xss'] = array(
  54. 'title' => 'XSS Filter',
  55. 'description' => 'XSS Filter.',
  56. 'page callback' => 'ckeditor_filter_xss',
  57. 'file' => 'includes/ckeditor.page.inc',
  58. 'access callback' => TRUE,
  59. 'type' => MENU_CALLBACK,
  60. );
  61. $items['ckeditor/disable/wysiwyg/%'] = array(
  62. 'title' => 'Disable the WYSIWYG module',
  63. 'description' => 'Disable WYSIWYG module.',
  64. 'page callback' => 'ckeditor_disable_wysiwyg',
  65. 'page arguments' => array(3),
  66. 'file' => 'includes/ckeditor.admin.inc',
  67. 'access arguments' => array('administer ckeditor'),
  68. 'access callback' => TRUE,
  69. 'type' => MENU_CALLBACK,
  70. );
  71. $items['admin/config/content/ckeditor'] = array(
  72. 'title' => 'CKEditor',
  73. 'description' => 'Configure the rich text editor.',
  74. 'page callback' => 'ckeditor_admin_main',
  75. 'file' => 'includes/ckeditor.admin.inc',
  76. 'access arguments' => array('administer ckeditor'),
  77. 'type' => MENU_NORMAL_ITEM,
  78. );
  79. $items['admin/config/content/ckeditor/skinframe'] = array(
  80. 'title' => 'Change skin of CKEditor',
  81. 'description' => 'Configure skin for CKEditor.',
  82. 'page callback' => 'ckeditor_skinframe',
  83. 'file' => 'includes/ckeditor.admin.inc',
  84. 'access arguments' => array('administer ckeditor'),
  85. 'type' => MENU_CALLBACK,
  86. );
  87. $items['admin/config/content/ckeditor/add'] = array(
  88. 'title' => 'Add a new CKEditor profile',
  89. 'description' => 'Configure the rich text editor.',
  90. 'page callback' => 'drupal_get_form',
  91. 'page arguments' => array('ckeditor_admin_profile_form'),
  92. 'file' => 'includes/ckeditor.admin.inc',
  93. 'access arguments' => array('administer ckeditor'),
  94. 'type' => MENU_CALLBACK,
  95. );
  96. $items['admin/config/content/ckeditor/clone/%ckeditor_profile'] = array(
  97. 'title' => 'Clone the CKEditor profile',
  98. 'description' => 'Configure the rich text editor.',
  99. 'page callback' => 'drupal_get_form',
  100. 'page arguments' => array('ckeditor_admin_profile_clone_form', 5),
  101. 'file' => 'includes/ckeditor.admin.inc',
  102. 'access arguments' => array('administer ckeditor'),
  103. 'type' => MENU_CALLBACK,
  104. );
  105. $items['admin/config/content/ckeditor/edit/%ckeditor_profile'] = array(
  106. 'title' => 'Edit the CKEditor profile',
  107. 'description' => 'Configure the rich text editor.',
  108. 'page callback' => 'drupal_get_form',
  109. 'page arguments' => array('ckeditor_admin_profile_form', 5),
  110. 'file' => 'includes/ckeditor.admin.inc',
  111. 'access arguments' => array('administer ckeditor'),
  112. 'type' => MENU_CALLBACK,
  113. );
  114. $items['admin/config/content/ckeditor/delete/%ckeditor_profile'] = array(
  115. 'title' => 'Delete the CKEditor profile',
  116. 'description' => 'Configure the rich text editor.',
  117. 'page callback' => 'drupal_get_form',
  118. 'page arguments' => array('ckeditor_admin_profile_delete_form', 5),
  119. 'file' => 'includes/ckeditor.admin.inc',
  120. 'access arguments' => array('administer ckeditor'),
  121. 'type' => MENU_CALLBACK,
  122. );
  123. $items['admin/config/content/ckeditor/addg'] = array(
  124. 'title' => 'Add the CKEditor Global profile',
  125. 'description' => 'Configure the rich text editor.',
  126. 'page callback' => 'drupal_get_form',
  127. 'page arguments' => array('ckeditor_admin_global_profile_form', 'add'),
  128. 'file' => 'includes/ckeditor.admin.inc',
  129. 'access arguments' => array('administer ckeditor'),
  130. 'type' => MENU_CALLBACK,
  131. );
  132. $items['admin/config/content/ckeditor/editg'] = array(
  133. 'title' => 'Edit the CKEditor Global profile',
  134. 'description' => 'Configure the rich text editor.',
  135. 'page callback' => 'drupal_get_form',
  136. 'page arguments' => array('ckeditor_admin_global_profile_form', 'edit'),
  137. 'file' => 'includes/ckeditor.admin.inc',
  138. 'access arguments' => array('administer ckeditor'),
  139. 'type' => MENU_CALLBACK,
  140. );
  141. return $items;
  142. }
  143. /**
  144. * Implementation of hook_permission().
  145. *
  146. * People -> Permissions
  147. */
  148. function ckeditor_permission() {
  149. $arr = array();
  150. $arr['administer ckeditor'] = array(
  151. 'title' => t('Administer CKEditor access'),
  152. 'description' => t('Allow users to change CKEditor settings.')
  153. );
  154. $arr['customize ckeditor'] = array(
  155. 'title' => t('Customize CKEditor appearance'),
  156. 'description' => t('Allow users to customize CKEditor appearance.')
  157. );
  158. if (file_exists(ckfinder_path('local'))) {
  159. $arr['allow CKFinder file uploads'] = array(
  160. 'title' => t('CKFinder access'),
  161. 'description' => t('Allow users to use CKFinder.')
  162. );
  163. }
  164. return $arr;
  165. }
  166. /**
  167. * Implementation of hook_help().
  168. *
  169. * This function delegates the execution to ckeditor_help_delegate() in includes/ckeditor.page.inc to
  170. * lower the amount of code in ckeditor.module.
  171. */
  172. function ckeditor_help($path, $arg) {
  173. module_load_include('inc', 'ckeditor', 'includes/ckeditor.page');
  174. return module_invoke('ckeditor', 'help_delegate', $path, $arg);
  175. }
  176. /**
  177. * Check CKEditor version
  178. */
  179. function ckeditor_get_version($main_version = FALSE) {
  180. static $ckeditor_version = FALSE;
  181. if ($ckeditor_version !== FALSE) {
  182. if (!$main_version) {
  183. return $ckeditor_version;
  184. }
  185. $version = explode('.', $ckeditor_version);
  186. return trim($version[0]);
  187. }
  188. $editor_path = ckeditor_path('local', TRUE);
  189. $jspath = $editor_path . '/ckeditor.js';
  190. $configcontents = @file_get_contents($jspath);
  191. if (!$configcontents) {
  192. return $ckeditor_version = NULL;
  193. }
  194. $matches = array();
  195. if (preg_match('#,version:[\'\"]{1}(.*?)[\'\"]{1},#', $configcontents, $matches)) {
  196. $ckeditor_version = $matches[1];
  197. if ($ckeditor_version == '%VERSION%') {
  198. $ckeditor_version = '4.0.0';
  199. }
  200. if (!$main_version) {
  201. return $ckeditor_version;
  202. }
  203. $version = explode('.', $ckeditor_version);
  204. return trim($version[0]);
  205. }
  206. return $ckeditor_version = NULL;
  207. }
  208. /**
  209. * Implementation of hook_init().
  210. */
  211. function ckeditor_init() {
  212. drupal_add_css(drupal_get_path('module', 'ckeditor') . '/ckeditor.css');
  213. }
  214. /**
  215. * Implements hook_form_FORM_ID_alter() for user_profile_form().
  216. */
  217. function ckeditor_form_user_profile_form_alter(&$form, &$form_state) {
  218. if ($form['#user_category'] == 'account') {
  219. module_load_include('inc', 'ckeditor', 'includes/ckeditor.user');
  220. ckeditor_user_customize($form, $form_state, 'user_profile_form');
  221. }
  222. }
  223. /**
  224. * Implementation of hook_element_info_alter().
  225. *
  226. * Replace the textarea with CKEditor using a callback function (ckeditor_pre_render_text_format).
  227. */
  228. function ckeditor_element_info_alter(&$types) {
  229. $types['text_format']['#pre_render'][] = 'ckeditor_pre_render_text_format';
  230. }
  231. /**
  232. * This function creates the HTML objects required for CKEditor.
  233. *
  234. * @param $element
  235. * A fully populated form element to add the editor to.
  236. * @return
  237. * The same $element with extra CKEditor markup and initialization.
  238. */
  239. function ckeditor_pre_render_text_format($element) {
  240. static $init = FALSE;
  241. if (!isset($element['#format'])) {
  242. return $element;
  243. }
  244. module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
  245. if ($init === FALSE) {
  246. $input_formats = ckeditor_profiles_compile();
  247. drupal_add_js(array('ckeditor' => array('input_formats' => $input_formats, 'plugins' => array())), 'setting');
  248. $init = TRUE;
  249. }
  250. if (isset($element['value'])) {
  251. if (!isset($element['format'])) {
  252. return $element;
  253. }
  254. if (isset($element['summary'])) {
  255. $element['value'] = ckeditor_load_by_field($element['value'], $element['format']['format'], TRUE, $element['summary']['#id']);
  256. $element['summary'] = ckeditor_load_by_field($element['summary'], $element['format']['format'], FALSE);
  257. }
  258. else {
  259. $element['value'] = ckeditor_load_by_field($element['value'], $element['format']['format']);
  260. }
  261. }
  262. else {
  263. $element = ckeditor_load_by_field($element, $element['#format']);
  264. }
  265. return $element;
  266. }
  267. /**
  268. * Load all profiles. Just load one profile if $name is passed in.
  269. */
  270. function ckeditor_profile_load($name = '', $clear = FALSE) {
  271. static $profiles = array();
  272. global $user;
  273. if (empty($profiles) || $clear === TRUE) {
  274. $result = db_select('ckeditor_settings', 's')->fields('s')->execute();
  275. foreach ($result as $data) {
  276. $data->settings = unserialize($data->settings);
  277. $data->input_formats = array();
  278. $profiles[$data->name] = $data;
  279. }
  280. $input_formats = filter_formats($user);
  281. $result = db_select('ckeditor_input_format', 'f')->fields('f')->execute();
  282. foreach ($result as $data) {
  283. if (isset($input_formats[$data->format])) {
  284. $profiles[$data->name]->input_formats[$data->format] = $input_formats[$data->format]->name;
  285. }
  286. }
  287. }
  288. return ($name ? (isset($profiles[urldecode($name)]) ? $profiles[urldecode($name)] : FALSE) : $profiles);
  289. }
  290. /**
  291. * Generate base path of the Drupal installation.
  292. *
  293. * @return
  294. * Path of the Drupal installation.
  295. */
  296. function ckeditor_base_path($mode = 'relative') {
  297. if ($mode == 'local') {
  298. return $cke_base_local_path = '.';
  299. }
  300. return rtrim(base_path(), '/');
  301. }
  302. /**
  303. * Generate module path of the CKEditor module.
  304. *
  305. * @return
  306. * Path of CKEditor module.
  307. */
  308. function ckeditor_module_path($mode = 'relative') {
  309. switch ($mode) {
  310. default:
  311. case 'relative':
  312. return ckeditor_base_path('relative') . '/' . drupal_get_path('module', 'ckeditor');
  313. case 'local':
  314. return ckeditor_base_path('local') . '/' . drupal_get_path('module', 'ckeditor');
  315. case 'url':
  316. return drupal_get_path('module', 'ckeditor');
  317. }
  318. }
  319. /**
  320. * Generate library path of the Drupal installation.
  321. *
  322. * @return
  323. * Path of library in the Drupal installation.
  324. */
  325. function ckeditor_library_path($mode = 'relative') {
  326. switch ($mode) {
  327. default:
  328. case 'relative':
  329. return ckeditor_base_path('relative') . '/sites/all/libraries';
  330. case 'local':
  331. return ckeditor_base_path('local') . '/sites/all/libraries';
  332. case 'url':
  333. return 'sites/all/libraries';
  334. }
  335. }
  336. /**
  337. * Read the CKEditor path from the Global profile.
  338. *
  339. * @return
  340. * Path to CKEditor folder.
  341. */
  342. function ckeditor_path($mode = 'relative', $refresh = FALSE) {
  343. static $cke_static;
  344. if (!isset($cke_static)) {
  345. $cke_static = array();
  346. }
  347. if ($refresh || !isset($cke_static[$mode])) {
  348. $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
  349. switch ($mode) {
  350. default:
  351. case 'relative':
  352. if ($global_profile && isset($global_profile->settings['ckeditor_path'])) {
  353. $cke_path = $global_profile->settings['ckeditor_path'];
  354. $cke_path = strtr($cke_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
  355. $cke_path = str_replace('\\', '/', $cke_path);
  356. $cke_path = str_replace('//', '/', $cke_path);
  357. return $cke_static[$mode] = $cke_path;
  358. }
  359. return $cke_static[$mode] = ckeditor_module_path('relative') . '/ckeditor';
  360. case 'local':
  361. if ($global_profile) {
  362. if (!empty($global_profile->settings['ckeditor_local_path'])) {
  363. return $cke_static[$mode] = $global_profile->settings['ckeditor_local_path'];
  364. }
  365. if (isset($global_profile->settings['ckeditor_path'])) {
  366. $cke_local_path = $global_profile->settings['ckeditor_path'];
  367. $cke_local_path = strtr($cke_local_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
  368. return $cke_static[$mode] = $cke_local_path;
  369. }
  370. }
  371. return $cke_static[$mode] = ckeditor_module_path('local') . '/ckeditor';
  372. case 'url':
  373. if ($global_profile && isset($global_profile->settings['ckeditor_path'])) {
  374. $cke_path = $global_profile->settings['ckeditor_path'];
  375. $cke_path = strtr($cke_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
  376. $cke_path = str_replace('\\', '/', $cke_path);
  377. $cke_path = str_replace('//', '/', $cke_path);
  378. //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
  379. $cke_path = str_replace(array("%b/", "%b"), '', $cke_path);
  380. return $cke_static[$mode] = $cke_path;
  381. }
  382. return $cke_static[$mode] = ckeditor_module_path('url') . '/ckeditor';
  383. }
  384. }
  385. return $cke_static[$mode];
  386. }
  387. /**
  388. * Read the CKEditor plugins path from the Global profile.
  389. *
  390. * @return
  391. * Path to CKEditor plugins folder.
  392. */
  393. function ckeditor_plugins_path($mode = 'relative', $refresh = FALSE) {
  394. static $cke_static;
  395. if (!isset($cke_static)) {
  396. $cke_static = array();
  397. }
  398. if ($refresh || !isset($cke_static[$mode])) {
  399. $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
  400. switch ($mode) {
  401. default:
  402. case 'relative':
  403. if ($global_profile && isset($global_profile->settings['ckeditor_plugins_path'])) {
  404. $cke_plugins_path = $global_profile->settings['ckeditor_plugins_path'];
  405. $cke_plugins_path = strtr($cke_plugins_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
  406. $cke_plugins_path = str_replace('\\', '/', $cke_plugins_path);
  407. $cke_plugins_path = str_replace('//', '/', $cke_plugins_path);
  408. $cke_plugins_path = rtrim($cke_plugins_path, ' \/');
  409. return $cke_static[$mode] = $cke_plugins_path;
  410. }
  411. return $cke_static[$mode] = ckeditor_module_path('relative') . '/plugins';
  412. case 'local':
  413. if ($global_profile) {
  414. if (!empty($global_profile->settings['ckeditor_plugins_local_path'])) {
  415. return $cke_static[$mode] = $global_profile->settings['ckeditor_plugins_local_path'];
  416. }
  417. if (isset($global_profile->settings['ckeditor_plugins_path'])) {
  418. $cke_plugins_local_path = $global_profile->settings['ckeditor_plugins_path'];
  419. $cke_plugins_local_path = strtr($cke_plugins_local_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
  420. return $cke_static[$mode] = $cke_plugins_local_path;
  421. }
  422. }
  423. return $cke_static[$mode] = ckeditor_module_path('local') . '/plugins';
  424. case 'url':
  425. if ($global_profile && isset($global_profile->settings['ckeditor_plugins_path'])) {
  426. $cke_plugins_path = $global_profile->settings['ckeditor_plugins_path'];
  427. $cke_plugins_path = strtr($cke_plugins_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
  428. $cke_plugins_path = str_replace('\\', '/', $cke_plugins_path);
  429. $cke_plugins_path = str_replace('//', '/', $cke_plugins_path);
  430. $cke_plugins_path = rtrim($cke_plugins_path, ' \/');
  431. //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
  432. $cke_plugins_path = str_replace(array("%b/", "%b"), '', $cke_plugins_path);
  433. return $cke_static[$mode] = $cke_plugins_path;
  434. }
  435. return $cke_static[$mode] = ckeditor_module_path('url') . '/plugins';
  436. }
  437. }
  438. return $cke_static[$mode];
  439. }
  440. /**
  441. * Read the CKFinder path from the Global profile.
  442. *
  443. * @return
  444. * Path to CKFinder folder.
  445. */
  446. function ckfinder_path($mode = 'relative', $refresh = FALSE) {
  447. static $cke_static;
  448. if (!isset($cke_static)) {
  449. $cke_static = array();
  450. }
  451. if ($refresh || !isset($cke_static[$mode])) {
  452. $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
  453. switch ($mode) {
  454. default:
  455. case 'relative':
  456. if ($global_profile && isset($global_profile->settings['ckfinder_path'])) {
  457. $ckfinder_path = $global_profile->settings['ckfinder_path'];
  458. $ckfinder_path = strtr($ckfinder_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
  459. $ckfinder_path = str_replace('\\', '/', $ckfinder_path);
  460. $ckfinder_path = str_replace('//', '/', $ckfinder_path);
  461. return $cke_static[$mode] = $ckfinder_path;
  462. }
  463. return $cke_static[$mode] = ckeditor_module_path('relative') . '/ckfinder';
  464. case 'local':
  465. if ($global_profile) {
  466. if (!empty($global_profile->settings['ckfinder_local_path'])) {
  467. return $cke_static[$mode] = $global_profile->settings['ckfinder_local_path'];
  468. }
  469. if (isset($global_profile->settings['ckfinder_path'])) {
  470. $ckfinder_path = $global_profile->settings['ckfinder_path'];
  471. $ckfinder_path = strtr($ckfinder_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
  472. return $cke_static[$mode] = $ckfinder_path;
  473. }
  474. }
  475. return $cke_static[$mode] = ckeditor_module_path('local') . '/ckfinder';
  476. case 'url':
  477. if ($global_profile && isset($global_profile->settings['ckfinder_path'])) {
  478. $ckfinder_path = $global_profile->settings['ckfinder_path'];
  479. $ckfinder_path = strtr($ckfinder_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
  480. $ckfinder_path = str_replace('\\', '/', $cke_plugins_path);
  481. $ckfinder_path = str_replace('//', '/', $cke_plugins_path);
  482. //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
  483. $ckfinder_path = str_replace(array("%b/", "%b"), '', $ckfinder_path);
  484. return $cke_static[$mode] = $ckfinder_path;
  485. }
  486. return $cke_static[$mode] = ckeditor_module_path('url') . '/ckfinder';
  487. }
  488. }
  489. return $cke_static[$mode];
  490. }
  491. /**
  492. * Implementation of hook_features_api().
  493. *
  494. * Allow exporting of CKEditor profiles by the Features module.
  495. */
  496. function ckeditor_features_api() {
  497. return array(
  498. 'ckeditor_profile' => array(
  499. 'name' => t('CKEditor profiles'),
  500. 'default_hook' => 'ckeditor_profile_defaults',
  501. 'default_file' => FEATURES_DEFAULTS_INCLUDED,
  502. 'file' => drupal_get_path('module', 'ckeditor') . '/includes/ckeditor.features.inc',
  503. )
  504. );
  505. }
  506. /**
  507. * Implementation of hook_file_download().
  508. * Support for private downloads.
  509. * CKEditor does not implement any kind of potection on private files.
  510. */
  511. function ckeditor_file_download($uri) {
  512. if ($path = file_create_url($uri)) {
  513. $result = db_query("SELECT f.* FROM {file_managed} f WHERE uri = :uri", array(':uri' => $uri));
  514. foreach ($result as $record) {
  515. return NULL;
  516. }
  517. //No info in DB? Probably a file uploaded with FCKeditor / CKFinder
  518. $global_profile = ckeditor_profile_load("CKEditor Global Profile");
  519. //Assume that files inside of ckeditor directory belong to the CKEditor. If private directory is set, let the decision about protection to the user.
  520. $private_dir_db = $private_dir = isset($global_profile->settings['private_dir']) ? trim($global_profile->settings['private_dir'], '\/') : '';
  521. $private_dir_db = str_replace(array('\\%u', '\\%n'), array('', ''), $private_dir_db);
  522. $private_dir = preg_quote($private_dir, '#');
  523. $private_dir = strtr($private_dir, array('%u' => '(\d+)', '%n' => '([\x80-\xF7 \w@.-]+)')); // regex for %n taken from user_validate_name() in user.module
  524. $private_dir = trim($private_dir, '\/');
  525. $regex = '#^' . preg_quote('private://', '#') . $private_dir . '#';
  526. if (!strstr($uri, 'private://') && !strstr($uri, 'public://')) {
  527. $path = 'private://' . $uri;
  528. }
  529. else {
  530. $path = $uri;
  531. }
  532. //check if CKEditor's "Enable access to files located in the private folder" option is disabled or enabled
  533. $allow_download_private_files = FALSE;
  534. if (isset($global_profile->settings['ckeditor_allow_download_private_files']) && $global_profile->settings['ckeditor_allow_download_private_files'] === 't') {
  535. $allow_download_private_files = TRUE;
  536. }
  537. //denied access to file if private upload is set and CKEditor's "Enable access to files located in the private folder" option is disabled
  538. if ($allow_download_private_files == FALSE)
  539. return NULL;
  540. //check if file can be served by comparing regex and path to file
  541. if (preg_match($regex, $path)) {
  542. $info = image_get_info($uri);
  543. return array('Content-Type' => $info['mime_type']);
  544. }
  545. }
  546. }
  547. /**
  548. * Implementation of hook_modules_enabled().
  549. *
  550. * Enable disabled plugins by hook_modules_disabled().
  551. */
  552. function ckeditor_modules_enabled($modules) {
  553. module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
  554. $profiles_list = ckeditor_profile_input_formats();
  555. $plugins_list = ckeditor_load_plugins();
  556. foreach ($profiles_list AS $_profile => $_inputs) {
  557. $changed = FALSE;
  558. $profile = ckeditor_profile_load($_profile);
  559. if (!isset($profile->settings['loadPlugins'])) continue;
  560. foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
  561. if (isset($profile->settings['loadPlugins'][$plugin_name]['active']) && $profile->settings['loadPlugins'][$plugin_name]['active'] == 0 && array_key_exists($plugin_name, $plugins_list)) {
  562. $profile->settings['loadPlugins'][$plugin_name]['active'] = 1;
  563. $changed = TRUE;
  564. }
  565. }
  566. if ($changed === TRUE) {
  567. db_update('ckeditor_settings')
  568. ->fields(array(
  569. 'settings' => serialize($profile->settings)
  570. ))
  571. ->condition('name', $profile->name, '=')
  572. ->execute();
  573. }
  574. }
  575. }
  576. /**
  577. * Implementation of hook_modules_disabled().
  578. *
  579. * Disable enabled plugins in CKEditor profiles added by disabled modules.
  580. */
  581. function ckeditor_modules_disabled($modules) {
  582. module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
  583. $profiles_list = ckeditor_profile_input_formats();
  584. $plugins_list = ckeditor_load_plugins();
  585. foreach ($profiles_list AS $_profile => $_inputs) {
  586. $changed = FALSE;
  587. $profile = ckeditor_profile_load($_profile);
  588. foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
  589. if (!array_key_exists($plugin_name, $plugins_list)) {
  590. $profile->settings['loadPlugins'][$plugin_name]['active'] = 0;
  591. $changed = TRUE;
  592. }
  593. }
  594. if ($changed === TRUE) {
  595. db_update('ckeditor_settings')
  596. ->fields(array(
  597. 'settings' => serialize($profile->settings)
  598. ))
  599. ->condition('name', $profile->name, '=')
  600. ->execute();
  601. }
  602. }
  603. }
  604. /**
  605. * Implementation of hook_modules_uninstalled().
  606. *
  607. * Remove enabled plugins in CKEditor profiles added by uninstalled modules.
  608. */
  609. function ckeditor_modules_uninstalled($modules) {
  610. module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
  611. $profiles_list = ckeditor_profile_input_formats();
  612. $plugins_list = ckeditor_load_plugins();
  613. foreach ($profiles_list AS $_profile => $_inputs) {
  614. $changed = FALSE;
  615. $profile = ckeditor_profile_load($_profile);
  616. foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
  617. if (!array_key_exists($plugin_name, $plugins_list)) {
  618. unset($profile->settings['loadPlugins'][$plugin_name]);
  619. $changed = TRUE;
  620. }
  621. }
  622. if ($changed === TRUE) {
  623. db_update('ckeditor_settings')
  624. ->fields(array(
  625. 'settings' => serialize($profile->settings)
  626. ))
  627. ->condition('name', $profile->name, '=')
  628. ->execute();
  629. }
  630. }
  631. }