Commit | Line | Data |
---|---|---|
7266e09b CW |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
7e9e8871 | 4 | | CiviCRM version 4.7 | |
7266e09b | 5 | +--------------------------------------------------------------------+ |
fa938177 | 6 | | Copyright CiviCRM LLC (c) 2004-2016 | |
7266e09b CW |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
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. | | |
13 | | | | |
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. | | |
18 | | | | |
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 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | ||
28 | /** | |
29 | * | |
30 | * @package CRM | |
fa938177 | 31 | * @copyright CiviCRM LLC (c) 2004-2016 |
7266e09b CW |
32 | */ |
33 | ||
34 | /** | |
ce064e4f | 35 | * Page for configuring CKEditor options. |
7266e09b CW |
36 | * |
37 | * Note that while this is implemented as a CRM_Core_Page, it is actually a form. | |
47b59d65 | 38 | * Because the form needs to be submitted and refreshed via javascript, it seemed like |
7266e09b CW |
39 | * Quickform and CRM_Core_Form/Controller might get in the way. |
40 | */ | |
41 | class CRM_Admin_Page_CKEditorConfig extends CRM_Core_Page { | |
42 | ||
47b59d65 | 43 | const CONFIG_FILENAME = '[civicrm.files]/persist/crm-ckeditor-config.js'; |
7266e09b CW |
44 | |
45 | /** | |
46 | * Default settings if config file has not been initialized | |
47 | * | |
48 | * @var array | |
49 | */ | |
50 | public $defaultSettings = array( | |
51 | 'skin' => 'moono', | |
52 | 'extraPlugins' => '', | |
53 | ); | |
54 | ||
55 | /** | |
ce064e4f | 56 | * Run page. |
57 | * | |
7266e09b CW |
58 | * @return string |
59 | */ | |
60 | public function run() { | |
61 | // If the form was submitted, take appropriate action. | |
62 | if (!empty($_POST['revert'])) { | |
63 | self::deleteConfigFile(); | |
64 | } | |
65 | elseif (!empty($_POST['config'])) { | |
66 | $this->save($_POST); | |
67 | } | |
68 | ||
69 | CRM_Core_Resources::singleton() | |
68e7ff1c | 70 | ->addScriptFile('civicrm', 'bower_components/ckeditor/ckeditor.js', 0, 'page-header') |
7266e09b CW |
71 | ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js', 1) |
72 | ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/abstracttoolbarmodifier.js', 2) | |
73 | ->addScriptFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/js/toolbarmodifier.js', 3) | |
74 | ->addScriptFile('civicrm', 'js/wysiwyg/admin.ckeditor-configurator.js', 10) | |
75 | ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/toolbarconfigurator/css/fontello.css') | |
76 | ->addStyleFile('civicrm', 'bower_components/ckeditor/samples/css/samples.css') | |
77 | ->addVars('ckConfig', array( | |
78 | 'plugins' => array_values($this->getCKPlugins()), | |
79 | )); | |
80 | ||
81 | $this->assign('skins', $this->getCKSkins()); | |
82 | $this->assign('skin', $this->getConfigSetting('skin')); | |
83 | $this->assign('extraPlugins', $this->getConfigSetting('extraPlugins')); | |
84 | $this->assign('configUrl', self::getConfigUrl()); | |
85 | $this->assign('revertConfirm', htmlspecialchars(ts('Are you sure you want to revert all changes?', array('escape' => 'js')))); | |
86 | ||
87 | CRM_Utils_System::appendBreadCrumb(array(array( | |
88 | 'url' => CRM_Utils_System::url('civicrm/admin/setting/preferences/display', 'reset=1'), | |
89 | 'title' => ts('Display Preferences'), | |
90 | ))); | |
91 | ||
92 | return parent::run(); | |
93 | } | |
94 | ||
95 | /** | |
96 | * Generate the config js file based on posted data. | |
97 | * | |
98 | * @param array $params | |
99 | */ | |
100 | public function save($params) { | |
101 | $config = "/**\n" | |
102 | . " * CKEditor config file auto-generated by CiviCRM.\n" | |
103 | . " *\n" | |
104 | . " * Note: This file will be overwritten if settings are modified at:\n" | |
105 | . " * @link " . CRM_Utils_System::url(CRM_Utils_System::currentPath(), NULL, TRUE, NULL, FALSE) . "\n" | |
106 | . " */\n\n" | |
107 | // Standardize line-endings | |
108 | . preg_replace('~\R~u', "\n", $params['config']); | |
109 | ||
110 | // Use defaultSettings as a whitelist so we don't just insert any old junk into the file | |
111 | foreach ($this->defaultSettings as $key => $default) { | |
112 | if (isset($params[$key]) && strlen($params[$key])) { | |
113 | $pos = strrpos($config, '};'); | |
114 | $setting = "\n\tconfig.$key = '{$params[$key]}';\n"; | |
115 | $config = substr_replace($config, $setting, $pos, 0); | |
116 | } | |
117 | } | |
118 | self::saveConfigFile($config); | |
119 | if (!empty($params['save'])) { | |
120 | CRM_Core_Session::setStatus(ts("You may need to clear your browser's cache to see the changes in CiviCRM."), ts('CKEditor Saved'), 'success'); | |
121 | } | |
122 | } | |
123 | ||
124 | /** | |
47b59d65 | 125 | * Get available CKEditor plugin list. |
ce064e4f | 126 | * |
7266e09b CW |
127 | * @return array |
128 | */ | |
129 | private function getCKPlugins() { | |
130 | $plugins = array(); | |
47b59d65 | 131 | $pluginDir = Civi::paths()->getPath('[civicrm.root]/bower_components/ckeditor/plugins'); |
7266e09b CW |
132 | |
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( | |
139 | 'id' => $name, | |
140 | 'text' => ucfirst($name), | |
141 | 'icon' => NULL, | |
142 | ); | |
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"; | |
146 | } | |
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); | |
151 | } | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | return $plugins; | |
157 | } | |
158 | ||
159 | /** | |
47b59d65 | 160 | * Get available CKEditor skins. |
ce064e4f | 161 | * |
7266e09b CW |
162 | * @return array |
163 | */ | |
164 | private function getCKSkins() { | |
165 | $skins = array(); | |
47b59d65 | 166 | $skinDir = Civi::paths()->getPath('[civicrm.root]/bower_components/ckeditor/skins'); |
7266e09b CW |
167 | foreach (glob($skinDir . '/*', GLOB_ONLYDIR) as $dir) { |
168 | $dir = rtrim(str_replace('\\', '/', $dir), '/'); | |
169 | $skins[] = substr($dir, strrpos($dir, '/') + 1); | |
170 | } | |
171 | return $skins; | |
172 | } | |
173 | ||
174 | /** | |
175 | * @param $setting | |
176 | * @return string | |
177 | */ | |
178 | private function getConfigSetting($setting) { | |
179 | $value = CRM_Utils_Array::value($setting, $this->defaultSettings, ''); | |
180 | $file = self::getConfigFile(); | |
181 | if ($file) { | |
182 | $contents = file_get_contents($file); | |
183 | $matches = array(); | |
184 | preg_match("/\sconfig\.$setting\s?=\s?'([^']*)'/", $contents, $matches); | |
185 | if ($matches) { | |
186 | $value = $matches[1]; | |
187 | } | |
188 | } | |
189 | return $value; | |
190 | } | |
191 | ||
192 | /** | |
193 | * @return null|string | |
194 | */ | |
195 | public static function getConfigUrl() { | |
196 | if (self::getConfigFile()) { | |
80ab9d76 | 197 | return Civi::paths()->getUrl(self::CONFIG_FILENAME, 'absolute'); |
7266e09b CW |
198 | } |
199 | return NULL; | |
200 | } | |
201 | ||
202 | /** | |
203 | * @param bool $checkIfFileExists | |
204 | * If false, this fn will return fileName even if it doesn't exist | |
205 | * | |
206 | * @return null|string | |
207 | */ | |
208 | public static function getConfigFile($checkIfFileExists = TRUE) { | |
47b59d65 | 209 | $fileName = Civi::paths()->getPath(self::CONFIG_FILENAME); |
7266e09b CW |
210 | return !$checkIfFileExists || is_file($fileName) ? $fileName : NULL; |
211 | } | |
212 | ||
213 | /** | |
214 | * @param string $contents | |
215 | */ | |
216 | public static function saveConfigFile($contents) { | |
217 | $file = self::getConfigFile(FALSE); | |
218 | file_put_contents($file, $contents); | |
219 | } | |
220 | ||
221 | /** | |
ce064e4f | 222 | * Delete config file. |
7266e09b CW |
223 | */ |
224 | public static function deleteConfigFile() { | |
225 | $file = self::getConfigFile(); | |
226 | if ($file) { | |
227 | unlink($file); | |
228 | } | |
229 | } | |
230 | ||
231 | } |