3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2016 |
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-2016
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 javascript, 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_FILEPATH
= '[civicrm.files]/persist/crm-ckeditor-';
46 * Settings that cannot be configured in "advanced options"
50 public $blackList = array(
56 'filebrowserBrowseUrl',
57 'filebrowserImageBrowseUrl',
58 'filebrowserFlashBrowseUrl',
59 'filebrowserUploadUrl',
60 'filebrowserImageUploadUrl',
61 'filebrowserFlashUploadUrl',
71 public function run() {
72 $this->preset
= CRM_Utils_Array
::value('preset', $_REQUEST, 'default');
74 // If the form was submitted, take appropriate action.
75 if (!empty($_POST['revert'])) {
76 self
::deleteConfigFile($this->preset
);
78 elseif (!empty($_POST['config'])) {
82 $settings = $this->getConfigSettings();
84 CRM_Core_Resources
::singleton()
85 ->addScriptFile('civicrm', 'bower_components/ckeditor/ckeditor.js', 0, 'page-header')
86 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js', 1)
87 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js', 2)
88 ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js', 3)
89 ->addScriptFile('civicrm', 'js/wysiwyg/admin.ckeditor-configurator.js', 10)
90 ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/css/fontello.css')
91 ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/css/samples.css')
92 ->addVars('ckConfig', array(
93 'plugins' => array_values($this->getCKPlugins()),
94 'blacklist' => $this->blackList
,
95 'settings' => $settings,
98 $configUrl = self
::getConfigUrl($this->preset
);
100 $configUrl = self
::getConfigUrl('default');
103 $this->assign('preset', $this->preset
);
104 $this->assign('presets', CRM_Core_OptionGroup
::values('wysiwyg_presets', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name'));
105 $this->assign('skins', $this->getCKSkins());
106 $this->assign('skin', CRM_Utils_Array
::value('skin', $settings));
107 $this->assign('extraPlugins', CRM_Utils_Array
::value('extraPlugins', $settings));
108 $this->assign('configUrl', $configUrl);
109 $this->assign('revertConfirm', htmlspecialchars(ts('Are you sure you want to revert all changes?', array('escape' => 'js'))));
111 CRM_Utils_System
::appendBreadCrumb(array(array(
112 'url' => CRM_Utils_System
::url('civicrm/admin/setting/preferences/display', 'reset=1'),
113 'title' => ts('Display Preferences'),
116 return parent
::run();
120 * Generate the config js file based on posted data.
122 * @param array $params
124 public function save($params) {
126 . " * CKEditor config file auto-generated by CiviCRM.\n"
128 . " * Note: This file will be overwritten if settings are modified at:\n"
129 . " * @link " . CRM_Utils_System
::url(CRM_Utils_System
::currentPath(), NULL, TRUE, NULL, FALSE) . "\n"
131 // Standardize line-endings
132 . preg_replace('~\R~u', "\n", $params['config']);
134 // Use all params starting with config_
135 foreach ($params as $key => $val) {
137 if (strpos($key, 'config_') === 0 && strlen($val)) {
138 if ($val != 'true' && $val != 'false' && $val != 'null' && $val[0] != '{' && $val[0] != '[' && !is_numeric($val)) {
139 $val = json_encode($val);
141 $pos = strrpos($config, '};');
142 $key = preg_replace('/^config_/', 'config.', $key);
143 $setting = "\n\t{$key} = {$val};\n";
144 $config = substr_replace($config, $setting, $pos, 0);
147 self
::saveConfigFile($this->preset
, $config);
148 if (!empty($params['save'])) {
149 CRM_Core_Session
::setStatus(ts("You may need to clear your browser's cache to see the changes in CiviCRM."), ts('CKEditor Saved'), 'success');
154 * Get available CKEditor plugin list.
158 private function getCKPlugins() {
160 $pluginDir = Civi
::paths()->getPath('[civicrm.root]/bower_components/ckeditor/plugins');
162 foreach (glob($pluginDir . '/*', GLOB_ONLYDIR
) as $dir) {
163 $dir = rtrim(str_replace('\\', '/', $dir), '/');
164 $name = substr($dir, strrpos($dir, '/') +
1);
165 $dir = CRM_Utils_file
::addTrailingSlash($dir, '/');
166 if (is_file($dir . 'plugin.js')) {
167 $plugins[$name] = array(
169 'text' => ucfirst($name),
172 if (is_dir($dir . "icons")) {
173 if (is_file($dir . "icons/$name.png")) {
174 $plugins[$name]['icon'] = "bower_components/ckeditor/plugins/$name/icons/$name.png";
176 elseif (glob($dir . "icons/*.png")) {
177 $icon = CRM_Utils_Array
::first(glob($dir . "icons/*.png"));
178 $icon = rtrim(str_replace('\\', '/', $icon), '/');
179 $plugins[$name]['icon'] = "bower_components/ckeditor/plugins/$name/icons/" . substr($icon, strrpos($icon, '/') +
1);
189 * Get available CKEditor skins.
193 private function getCKSkins() {
195 $skinDir = Civi
::paths()->getPath('[civicrm.root]/bower_components/ckeditor/skins');
196 foreach (glob($skinDir . '/*', GLOB_ONLYDIR
) as $dir) {
197 $dir = rtrim(str_replace('\\', '/', $dir), '/');
198 $skins[] = substr($dir, strrpos($dir, '/') +
1);
206 private function getConfigSettings() {
207 $matches = $result = array();
208 $file = self
::getConfigFile($this->preset
);
210 $file = self
::getConfigFile('default');
212 $result['skin'] = 'moono';
214 $contents = file_get_contents($file);
215 preg_match_all("/\sconfig\.(\w+)\s?=\s?([^;]*);/", $contents, $matches);
216 foreach ($matches[1] as $i => $match) {
217 $result[$match] = trim($matches[2][$i], ' "\'');
224 * @param string $preset
225 * Omit to get an array of all presets
226 * @return array|null|string
228 public static function getConfigUrl($preset = NULL) {
230 $presets = CRM_Core_OptionGroup
::values('wysiwyg_presets', FALSE, FALSE, FALSE, NULL, 'name');
231 foreach ($presets as $key => $name) {
232 if (self
::getConfigFile($name)) {
233 $items[$name] = Civi
::paths()->getUrl(self
::CONFIG_FILEPATH
. $name . '.js', 'absolute');
236 return $preset ? CRM_Utils_Array
::value($preset, $items) : $items;
240 * @param string $preset
242 * @return null|string
244 public static function getConfigFile($preset = 'default') {
245 $fileName = Civi
::paths()->getPath(self
::CONFIG_FILEPATH
. $preset . '.js');
246 return is_file($fileName) ?
$fileName : NULL;
250 * @param string $contents
252 public static function saveConfigFile($preset, $contents) {
253 $file = Civi
::paths()->getPath(self
::CONFIG_FILEPATH
. $preset . '.js');
254 file_put_contents($file, $contents);
258 * Delete config file.
260 public static function deleteConfigFile($preset) {
261 $file = self
::getConfigFile($preset);