3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2015
35 * Page for configuring CKEditor options.
37 * Note that while this is implemented as a CRM_Core_Page, it is actually a form.
38 * Because the form needs to be submitted and refreshed via javascrit, it seemed like
39 * Quickform and CRM_Core_Form/Controller might get in the way.
41 class CRM_Admin_Page_CKEditorConfig
extends CRM_Core_Page
{
43 const CONFIG_FILENAME
= 'crm-ckeditor-config.js';
46 * Default settings if config file has not been initialized
50 public $defaultSettings = array(
60 public function run() {
61 // If the form was submitted, take appropriate action.
62 if (!empty($_POST['revert'])) {
63 self
::deleteConfigFile();
65 elseif (!empty($_POST['config'])) {
69 CRM_Core_Resources
::singleton()
70 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js', 1)
71 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js', 2)
72 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js', 3)
73 ->addScriptFile('civicrm', 'js/wysiwyg/admin.ckeditor-configurator.js', 10)
74 ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/css/fontello.css')
75 ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/css/samples.css')
76 ->addVars('ckConfig', array(
77 'plugins' => array_values($this->getCKPlugins()),
80 $this->assign('skins', $this->getCKSkins());
81 $this->assign('skin', $this->getConfigSetting('skin'));
82 $this->assign('extraPlugins', $this->getConfigSetting('extraPlugins'));
83 $this->assign('configUrl', self
::getConfigUrl());
84 $this->assign('revertConfirm', htmlspecialchars(ts('Are you sure you want to revert all changes?', array('escape' => 'js'))));
86 CRM_Utils_System
::appendBreadCrumb(array(array(
87 'url' => CRM_Utils_System
::url('civicrm/admin/setting/preferences/display', 'reset=1'),
88 'title' => ts('Display Preferences'),
95 * Generate the config js file based on posted data.
97 * @param array $params
99 public function save($params) {
101 . " * CKEditor config file auto-generated by CiviCRM.\n"
103 . " * Note: This file will be overwritten if settings are modified at:\n"
104 . " * @link " . CRM_Utils_System
::url(CRM_Utils_System
::currentPath(), NULL, TRUE, NULL, FALSE) . "\n"
106 // Standardize line-endings
107 . preg_replace('~\R~u', "\n", $params['config']);
109 // Use defaultSettings as a whitelist so we don't just insert any old junk into the file
110 foreach ($this->defaultSettings
as $key => $default) {
111 if (isset($params[$key]) && strlen($params[$key])) {
112 $pos = strrpos($config, '};');
113 $setting = "\n\tconfig.$key = '{$params[$key]}';\n";
114 $config = substr_replace($config, $setting, $pos, 0);
117 self
::saveConfigFile($config);
118 if (!empty($params['save'])) {
119 CRM_Core_Session
::setStatus(ts("You may need to clear your browser's cache to see the changes in CiviCRM."), ts('CKEditor Saved'), 'success');
124 * Get CKEditor plugins.
128 private function getCKPlugins() {
130 global $civicrm_root;
131 $pluginDir = CRM_Utils_file
::addTrailingSlash($civicrm_root, '/') . 'bower_components/ckeditor/plugins';
133 foreach (glob($pluginDir . '/*', GLOB_ONLYDIR
) as $dir) {
134 $dir = rtrim(str_replace('\\', '/', $dir), '/');
135 $name = substr($dir, strrpos($dir, '/') +
1);
136 $dir = CRM_Utils_file
::addTrailingSlash($dir, '/');
137 if (is_file($dir . 'plugin.js')) {
138 $plugins[$name] = array(
140 'text' => ucfirst($name),
143 if (is_dir($dir . "icons")) {
144 if (is_file($dir . "icons/$name.png")) {
145 $plugins[$name]['icon'] = "bower_components/ckeditor/plugins/$name/icons/$name.png";
147 elseif (glob($dir . "icons/*.png")) {
148 $icon = CRM_Utils_Array
::first(glob($dir . "icons/*.png"));
149 $icon = rtrim(str_replace('\\', '/', $icon), '/');
150 $plugins[$name]['icon'] = "bower_components/ckeditor/plugins/$name/icons/" . substr($icon, strrpos($icon, '/') +
1);
160 * Get CK Editor skins.
164 private function getCKSkins() {
166 global $civicrm_root;
167 $skinDir = CRM_Utils_file
::addTrailingSlash($civicrm_root, '/') . 'bower_components/ckeditor/skins';
168 foreach (glob($skinDir . '/*', GLOB_ONLYDIR
) as $dir) {
169 $dir = rtrim(str_replace('\\', '/', $dir), '/');
170 $skins[] = substr($dir, strrpos($dir, '/') +
1);
179 private function getConfigSetting($setting) {
180 $value = CRM_Utils_Array
::value($setting, $this->defaultSettings
, '');
181 $file = self
::getConfigFile();
183 $contents = file_get_contents($file);
185 preg_match("/\sconfig\.$setting\s?=\s?'([^']*)'/", $contents, $matches);
187 $value = $matches[1];
194 * @return null|string
196 public static function getConfigUrl() {
197 if (self
::getConfigFile()) {
198 // FIXME: Basing file path off imageUploadURL sucks, but it's all we got
199 $url = CRM_Utils_file
::addTrailingSlash(CRM_Core_Config
::singleton()->imageUploadURL
, '/');
200 $url = str_replace('/persist/contribute/', '/persist/', $url);
201 return $url . self
::CONFIG_FILENAME
;
207 * @param bool $checkIfFileExists
208 * If false, this fn will return fileName even if it doesn't exist
210 * @return null|string
212 public static function getConfigFile($checkIfFileExists = TRUE) {
213 // FIXME: Basing file path off imageUploadDir sucks, but it's all we got
214 $dir = CRM_Core_Config
::singleton()->imageUploadDir
;
215 $dir = CRM_Utils_file
::addTrailingSlash(str_replace('\\', '/', $dir), '/');
216 $dir = str_replace('/persist/contribute/', '/persist/', $dir);
217 $fileName = $dir . self
::CONFIG_FILENAME
;
218 return !$checkIfFileExists ||
is_file($fileName) ?
$fileName : NULL;
222 * @param string $contents
224 public static function saveConfigFile($contents) {
225 $file = self
::getConfigFile(FALSE);
226 file_put_contents($file, $contents);
230 * Delete config file.
232 public static function deleteConfigFile() {
233 $file = self
::getConfigFile();