1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Carbon_Fields\Container; |
4
|
|
|
|
5
|
|
|
use Carbon_Fields\Datastore\Datastore; |
6
|
|
|
use Carbon_Fields\Exception\Incorrect_Syntax_Exception; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Theme options container class. |
10
|
|
|
*/ |
11
|
|
|
class Theme_Options_Container extends Container { |
12
|
|
|
|
13
|
|
|
protected static $registered_pages = array(); |
14
|
|
|
|
15
|
|
|
public $settings = array( |
16
|
|
|
'parent' => '', |
17
|
|
|
'file' => '', |
18
|
|
|
); |
19
|
|
|
|
20
|
|
|
public $icon = ''; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Create a new container |
24
|
|
|
* |
25
|
|
|
* @param string $unique_id Unique id of the container |
26
|
|
|
* @param string $title title of the container |
27
|
|
|
* @param string $type Type of the container |
28
|
|
|
**/ |
29
|
|
View Code Duplication |
public function __construct( $unique_id, $title, $type ) { |
30
|
|
|
parent::__construct( $unique_id, $title, $type ); |
31
|
|
|
|
32
|
|
|
if ( ! $this->get_datastore() ) { |
33
|
|
|
$this->set_datastore( Datastore::make( 'theme_options' ), $this->has_default_datastore() ); |
34
|
|
|
} |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Attach container as a theme options page/subpage. |
39
|
|
|
**/ |
40
|
|
|
public function init() { |
41
|
|
|
if ( $this->settings['parent'] !== '' && strpos( $this->settings['parent'], '.php' ) === false ) { |
42
|
|
|
$clear_title = $this->clear_string( $this->settings['parent'] ); |
43
|
|
|
$this->settings['parent'] = 'crbn-' . $clear_title . '.php'; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
if ( ! $this->settings['file'] ) { |
47
|
|
|
$clear_title = $this->clear_string( $this->title ); |
48
|
|
|
$this->settings['file'] .= 'crbn-' . $clear_title . '.php'; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
$this->verify_unique_page(); |
52
|
|
|
|
53
|
|
|
add_action( 'admin_menu', array( $this, '_attach' ) ); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Perform checks whether the current save() request is valid. |
58
|
|
|
* |
59
|
|
|
* @return bool |
60
|
|
|
**/ |
61
|
|
|
public function is_valid_save() { |
62
|
|
|
if ( ! $this->verified_nonce_in_request() ) { |
63
|
|
|
return false; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
return $this->is_valid_attach_for_object(); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Perform save operation after successful is_valid_save() check. |
71
|
|
|
* The call is propagated to all fields in the container. |
72
|
|
|
* |
73
|
|
|
* @param mixed $user_data |
74
|
|
|
**/ |
75
|
|
|
public function save( $user_data = null ) { |
76
|
|
|
try { |
77
|
|
|
parent::save( $user_data ); |
78
|
|
|
} catch ( Incorrect_Syntax_Exception $e ) { |
79
|
|
|
$this->errors[] = $e->getMessage(); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
do_action( 'carbon_after_save_theme_options', $user_data ); |
83
|
|
|
|
84
|
|
|
if ( ! headers_sent() ) { |
85
|
|
|
wp_redirect( add_query_arg( array( 'settings-updated' => 'true' ) ) ); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Get environment array for page request (in admin) |
91
|
|
|
* |
92
|
|
|
* @return array |
93
|
|
|
**/ |
94
|
|
|
protected function get_environment_for_request() { |
95
|
|
|
return array(); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Perform checks whether the container should be attached during the current request |
100
|
|
|
* |
101
|
|
|
* @return bool True if the container is allowed to be attached |
102
|
|
|
**/ |
103
|
|
View Code Duplication |
public function is_valid_attach_for_request() { |
|
|
|
|
104
|
|
|
$environment = $this->get_environment_for_request(); |
105
|
|
|
$static_conditions_collection = $this->conditions_collection->evaluate( $this->get_dynamic_conditions(), true ); |
|
|
|
|
106
|
|
|
if ( ! $static_conditions_collection->is_fulfilled( $environment ) ) { |
107
|
|
|
return false; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
return true; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Get environment array for object id |
115
|
|
|
* |
116
|
|
|
* @return array |
117
|
|
|
*/ |
118
|
|
|
protected function get_environment_for_object( $object_id ) { |
119
|
|
|
return array(); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Check container attachment rules against object id |
124
|
|
|
* |
125
|
|
|
* @param int $object_id |
126
|
|
|
* @return bool |
127
|
|
|
**/ |
128
|
|
View Code Duplication |
public function is_valid_attach_for_object( $object_id = null ) { |
|
|
|
|
129
|
|
|
$environment = $this->get_environment_for_object( intval( $object_id ) ); |
130
|
|
|
if ( ! $this->conditions_collection->is_fulfilled( $environment ) ) { |
131
|
|
|
return false; |
132
|
|
|
} |
133
|
|
|
return true; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Add theme options container pages. |
138
|
|
|
* Hook the container saving action. |
139
|
|
|
**/ |
140
|
|
|
public function attach() { |
141
|
|
|
// use the "read" capability because conditions will handle actual access and save capability checking |
142
|
|
|
// before the attach() method is called |
143
|
|
|
|
144
|
|
|
// Add menu page |
145
|
|
|
if ( ! $this->settings['parent'] ) { |
146
|
|
|
add_menu_page( |
147
|
|
|
$this->title, |
148
|
|
|
$this->title, |
149
|
|
|
'read', |
150
|
|
|
$this->settings['file'], |
151
|
|
|
array( $this, 'render' ), |
152
|
|
|
$this->icon |
153
|
|
|
); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
add_submenu_page( |
157
|
|
|
$this->settings['parent'], |
158
|
|
|
$this->title, |
159
|
|
|
$this->title, |
160
|
|
|
'read', |
161
|
|
|
$this->settings['file'], |
162
|
|
|
array( $this, 'render' ), |
163
|
|
|
$this->icon |
164
|
|
|
); |
165
|
|
|
|
166
|
|
|
$page_hook = get_plugin_page_hookname( $this->settings['file'], '' ); |
167
|
|
|
add_action( 'load-' . $page_hook, array( $this, '_save' ) ); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Whether this container is currently viewed. |
172
|
|
|
**/ |
173
|
|
|
public function should_activate() { |
174
|
|
|
$request_page = isset( $_GET['page'] ) ? $_GET['page'] : ''; |
|
|
|
|
175
|
|
|
if ( ! empty( $request_page ) && $request_page === $this->settings['file'] ) { |
176
|
|
|
return true; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
return false; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Output the container markup |
184
|
|
|
**/ |
185
|
|
|
public function render() { |
186
|
|
|
$request_settings_updated = isset( $_GET['settings-updated'] ) ? $_GET['settings-updated'] : ''; |
|
|
|
|
187
|
|
|
if ( $request_settings_updated === 'true' ) { |
188
|
|
|
$this->notifications[] = __( 'Settings saved.', \Carbon_Fields\TEXT_DOMAIN ); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
include \Carbon_Fields\DIR . '/templates/Container/theme_options.php'; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Make sure that there are no duplicate containers with the same name. |
196
|
|
|
**/ |
197
|
|
|
public function verify_unique_page() { |
198
|
|
|
$file = $this->settings['file']; |
199
|
|
|
$parent = $this->settings['parent']; |
200
|
|
|
|
201
|
|
|
if ( ! $parent ) { |
202
|
|
|
// Register top level page |
203
|
|
|
if ( isset( static::$registered_pages[ $file ] ) ) { |
204
|
|
|
Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" already registered' ); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
static::$registered_pages[ $file ] = array(); |
208
|
|
|
return; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
// Register sub-page |
212
|
|
|
if ( ! isset( static::$registered_pages[ $parent ] ) ) { |
213
|
|
|
static::$registered_pages[ $parent ] = array(); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
if ( in_array( $file, static::$registered_pages[ $parent ] ) ) { |
217
|
|
|
Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" with parent "' . $parent . '" is already registered. Please set a name for the container.' ); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
static::$registered_pages[ $parent ][] = $file; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Sanitize the container title for use in |
225
|
|
|
* the theme options file name. |
226
|
|
|
**/ |
227
|
|
|
protected function clear_string( $string ) { |
228
|
|
|
return preg_replace( array( '~ +~', '~[^\w\d-]+~u', '~-+~' ), array( '-', '-', '-' ), strtolower( remove_accents( $string ) ) ); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* COMMON USAGE METHODS |
233
|
|
|
*/ |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* Change the parent theme options page of this container |
237
|
|
|
**/ |
238
|
|
|
public function set_page_parent( $parent ) { |
239
|
|
|
if ( is_a( $parent, 'Carbon_Container' ) ) { |
240
|
|
|
$parent = $parent->title; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
$this->settings['parent'] = $parent; |
244
|
|
|
return $this; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Set the icon of this theme options page. |
249
|
|
|
* Applicable only for parent theme option pages. |
250
|
|
|
**/ |
251
|
|
|
public function set_icon( $icon ) { |
252
|
|
|
$this->icon = $icon; |
253
|
|
|
return $this; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Set the theme options file name of this container. |
258
|
|
|
**/ |
259
|
|
|
public function set_page_file( $file ) { |
260
|
|
|
$this->settings['file'] = $file; |
261
|
|
|
return $this; |
262
|
|
|
} |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.