1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @package content |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* The Preferences page allows Developers to change settings for |
9
|
|
|
* this Symphony install. Extensions can extend the form on this |
10
|
|
|
* page so they can have their own settings. This page is typically |
11
|
|
|
* a UI for a subset of the `CONFIG` file. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
class contentSystemPreferences extends AdministrationPage |
|
|
|
|
15
|
|
|
{ |
16
|
|
|
public $_errors = array(); |
17
|
|
|
|
18
|
|
|
// Overload the parent 'view' function since we dont need the switchboard logic |
19
|
|
|
public function view() |
20
|
|
|
{ |
21
|
|
|
$this->setPageType('form'); |
22
|
|
|
$this->setTitle(__('%1$s – %2$s', array(__('Preferences'), __('Symphony')))); |
23
|
|
|
$this->addElementToHead(new XMLElement('link', null, array( |
24
|
|
|
'rel' => 'canonical', |
25
|
|
|
'href' => SYMPHONY_URL . '/system/preferences/', |
|
|
|
|
26
|
|
|
))); |
27
|
|
|
$this->appendSubheading(__('Preferences')); |
28
|
|
|
|
29
|
|
|
$bIsWritable = true; |
30
|
|
|
$formHasErrors = (is_array($this->_errors) && !empty($this->_errors)); |
31
|
|
|
|
32
|
|
|
if (General::checkFileWritable(CONFIG) === false) { |
|
|
|
|
33
|
|
|
$this->pageAlert(__('The Symphony configuration file, %s, or folder is not writable. You will not be able to save changes to preferences.', array('<code>/manifest/config.php</code>')), Alert::ERROR); |
34
|
|
|
$bIsWritable = false; |
35
|
|
|
} elseif ($formHasErrors) { |
36
|
|
|
$this->pageAlert( |
37
|
|
|
__('An error occurred while processing this form. See below for details.'), Alert::ERROR |
38
|
|
|
); |
39
|
|
|
} elseif (isset($this->_context[0]) && $this->_context[0] == 'success') { |
40
|
|
|
$this->pageAlert(__('Preferences saved.'), Alert::SUCCESS); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
// Get available languages |
44
|
|
|
$languages = Lang::getAvailableLanguages(); |
45
|
|
|
|
46
|
|
|
if (count($languages) > 1) { |
47
|
|
|
// Create language selection |
48
|
|
|
$group = new XMLElement('fieldset'); |
49
|
|
|
$group->setAttribute('class', 'settings'); |
50
|
|
|
$group->appendChild(new XMLElement('legend', __('System Language'))); |
51
|
|
|
$label = Widget::Label(); |
52
|
|
|
|
53
|
|
|
// Get language names |
54
|
|
|
asort($languages); |
55
|
|
|
|
56
|
|
|
$options = array(); |
57
|
|
|
foreach ($languages as $code => $name) { |
58
|
|
|
$options[] = array($code, $code == Symphony::Configuration()->get('lang', 'symphony'), $name); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$select = Widget::Select('settings[symphony][lang]', $options); |
62
|
|
|
$label->appendChild($select); |
63
|
|
|
$group->appendChild($label); |
64
|
|
|
$group->appendChild(new XMLElement('p', __('Authors can set up a differing language in their profiles.'), array('class' => 'help'))); |
65
|
|
|
// Append language selection |
66
|
|
|
$this->Form->appendChild($group); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
// Get available EmailGateways |
70
|
|
|
$email_gateways = EmailGatewayManager::listAll(); |
71
|
|
|
|
72
|
|
|
if (count($email_gateways) >= 1) { |
73
|
|
|
$group = new XMLElement('fieldset', null, array('class' => 'settings condensed')); |
74
|
|
|
$group->appendChild(new XMLElement('legend', __('Default Email Settings'))); |
75
|
|
|
$label = Widget::Label(__('Gateway')); |
76
|
|
|
|
77
|
|
|
// Get gateway names |
78
|
|
|
ksort($email_gateways); |
79
|
|
|
|
80
|
|
|
$default_gateway = EmailGatewayManager::getDefaultGateway(); |
81
|
|
|
$selected_is_installed = EmailGatewayManager::__getClassPath($default_gateway); |
82
|
|
|
|
83
|
|
|
$options = array(); |
84
|
|
|
|
85
|
|
|
foreach ($email_gateways as $handle => $details) { |
86
|
|
|
$options[] = array($handle, (($handle == $default_gateway) || (($selected_is_installed == false) && $handle == 'sendmail')), $details['name']); |
|
|
|
|
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
$select = Widget::Select('settings[Email][default_gateway]', $options, array('class' => 'picker', 'data-interactive' => 'data-interactive')); |
90
|
|
|
$label->appendChild($select); |
91
|
|
|
$group->appendChild($label); |
92
|
|
|
// Append email gateway selection |
93
|
|
|
$this->Form->appendChild($group); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
foreach ($email_gateways as $gateway) { |
97
|
|
|
$gateway_settings = EmailGatewayManager::create($gateway['handle'])->getPreferencesPane(); |
98
|
|
|
|
99
|
|
|
if (is_a($gateway_settings, 'XMLElement')) { |
100
|
|
|
$this->Form->appendChild($gateway_settings); |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
// Get available cache drivers |
105
|
|
|
$caches = Symphony::ExtensionManager()->getProvidersOf('cache'); |
106
|
|
|
// Add default Symphony cache driver.. |
107
|
|
|
$caches['database'] = 'Database'; |
108
|
|
|
|
109
|
|
|
if (count($caches) > 1) { |
110
|
|
|
$group = new XMLElement('fieldset', null, array('class' => 'settings condensed')); |
111
|
|
|
$group->appendChild(new XMLElement('legend', __('Default Cache Settings'))); |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Add custom Caching groups. For example a Datasource extension might want to add in the ability |
115
|
|
|
* for set a cache driver for it's functionality. This should usually be a dropdown, which allows |
116
|
|
|
* a developer to select what driver they want to use for caching. This choice is stored in the |
117
|
|
|
* Configuration in a Caching node. |
118
|
|
|
* eg. |
119
|
|
|
* 'caching' => array ( |
120
|
|
|
* 'remote_datasource' => 'database', |
121
|
|
|
* 'dynamic_ds' => 'YourCachingExtensionClassName' |
122
|
|
|
* ) |
123
|
|
|
* |
124
|
|
|
* @since Symphony 2.4 |
125
|
|
|
* @delegate AddCachingOpportunity |
126
|
|
|
* @param string $context |
127
|
|
|
* '/system/preferences/' |
128
|
|
|
* @param XMLElement $wrapper |
129
|
|
|
* An XMLElement of the current Caching fieldset |
130
|
|
|
* @param string $config_path |
131
|
|
|
* The node in the Configuration where this information will be stored. Read only. |
132
|
|
|
* @param array $available_caches |
133
|
|
|
* An array of the available cache providers |
134
|
|
|
* @param array $errors |
135
|
|
|
* An array of errors |
136
|
|
|
*/ |
137
|
|
|
Symphony::ExtensionManager()->notifyMembers('AddCachingOpportunity', '/system/preferences/', array( |
138
|
|
|
'wrapper' => &$group, |
139
|
|
|
'config_path' => 'caching', |
140
|
|
|
'available_caches' => $caches, |
141
|
|
|
'errors' => $this->_errors |
142
|
|
|
)); |
143
|
|
|
|
144
|
|
|
$this->Form->appendChild($group); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Add Extension custom preferences. Use the $wrapper reference to append objects. |
149
|
|
|
* |
150
|
|
|
* @delegate AddCustomPreferenceFieldsets |
151
|
|
|
* @param string $context |
152
|
|
|
* '/system/preferences/' |
153
|
|
|
* @param XMLElement $wrapper |
154
|
|
|
* An XMLElement of the current page |
155
|
|
|
* @param array $errors |
156
|
|
|
* An array of errors |
157
|
|
|
*/ |
158
|
|
|
Symphony::ExtensionManager()->notifyMembers('AddCustomPreferenceFieldsets', '/system/preferences/', array( |
159
|
|
|
'wrapper' => &$this->Form, |
160
|
|
|
'errors' => $this->_errors |
161
|
|
|
)); |
162
|
|
|
|
163
|
|
|
$div = new XMLElement('div'); |
164
|
|
|
$div->setAttribute('class', 'actions'); |
165
|
|
|
|
166
|
|
|
$version = new XMLElement('p', 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), array( |
167
|
|
|
'id' => 'version' |
168
|
|
|
)); |
169
|
|
|
$div->appendChild($version); |
170
|
|
|
|
171
|
|
|
$attr = array('accesskey' => 's'); |
172
|
|
|
|
173
|
|
|
if (!$bIsWritable) { |
174
|
|
|
$attr['disabled'] = 'disabled'; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
$div->appendChild(Widget::Input('action[save]', __('Save Changes'), 'submit', $attr)); |
178
|
|
|
|
179
|
|
|
$this->Form->appendChild($div); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
public function action() |
183
|
|
|
{ |
184
|
|
|
// Do not proceed if the config file cannot be changed |
185
|
|
|
if (General::checkFileWritable(CONFIG) === false) { |
|
|
|
|
186
|
|
|
redirect(SYMPHONY_URL . '/system/preferences/'); |
|
|
|
|
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Extensions can listen for any custom actions that were added |
191
|
|
|
* through `AddCustomPreferenceFieldsets` or `AddCustomActions` |
192
|
|
|
* delegates. |
193
|
|
|
* |
194
|
|
|
* @delegate CustomActions |
195
|
|
|
* @param string $context |
196
|
|
|
* '/system/preferences/' |
197
|
|
|
*/ |
198
|
|
|
Symphony::ExtensionManager()->notifyMembers('CustomActions', '/system/preferences/'); |
199
|
|
|
|
200
|
|
|
if (isset($_POST['action']['save'])) { |
201
|
|
|
$settings = filter_var_array($_POST['settings'], FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); |
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Just prior to saving the preferences and writing them to the `CONFIG` |
204
|
|
|
* Allows extensions to preform custom validation logic on the settings. |
205
|
|
|
* |
206
|
|
|
* @delegate Save |
207
|
|
|
* @param string $context |
208
|
|
|
* '/system/preferences/' |
209
|
|
|
* @param array $settings |
210
|
|
|
* An array of the preferences to be saved, passed by reference |
211
|
|
|
* @param array $errors |
212
|
|
|
* An array of errors passed by reference |
213
|
|
|
*/ |
214
|
|
|
Symphony::ExtensionManager()->notifyMembers('Save', '/system/preferences/', array( |
215
|
|
|
'settings' => &$settings, |
216
|
|
|
'errors' => &$this->_errors |
217
|
|
|
)); |
218
|
|
|
|
219
|
|
|
if (!is_array($this->_errors) || empty($this->_errors)) { |
|
|
|
|
220
|
|
|
if (is_array($settings) && !empty($settings)) { |
221
|
|
|
Symphony::Configuration()->setArray($settings, false); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
if (Symphony::Configuration()->write()) { |
225
|
|
|
if (function_exists('opcache_invalidate')) { |
226
|
|
|
@opcache_invalidate(CONFIG, true); |
|
|
|
|
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
redirect(SYMPHONY_URL . '/system/preferences/success/'); |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
} |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
|
Classes in PHP are usually named in CamelCase.
In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.
Thus the name database provider becomes
DatabaseProvider
.