Completed
Push — master ( afe740...a74724 )
by
unknown
03:38
created

Theme_Options_Container::is_valid_save()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
ccs 0
cts 4
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
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
	/**
14
	 * Array of registered page slugs to verify uniqueness with
15
	 *
16
	 * @var array
17
	 */
18
	protected static $registered_pages = array();
19
20
	/**
21
	 * Array of container settings
22
	 *
23
	 * @var array
24
	 */
25
	public $settings = array(
26
		'parent' => '',
27
		'file' => '',
28
		'icon' => '',
29
		'menu_position' => null,
30
		'menu_title' => null,
31
	);
32
33
	/**
34
	 * {@inheritDoc}
35
	 */
36 View Code Duplication
	public function __construct( $id, $title, $type, $condition_collection, $condition_translator ) {
37
		parent::__construct( $id, $title, $type, $condition_collection, $condition_translator );
38
39
		if ( ! $this->get_datastore() ) {
40
			$this->set_datastore( Datastore::make( 'theme_options' ), $this->has_default_datastore() );
41
		}
42
43
		if ( apply_filters( 'carbon_fields_' . $type . '_container_admin_only_access', true, $title ) ) {
44
			$this->where( 'current_user_capability', '=', 'manage_options' );
45
		}
46
	}
47
48
	/**
49
	 * Sanitize a title to a filename
50
	 *
51
	 * @param  string $title
52
	 * @param  string $extension
53
	 * @return string
54
	 */
55
	protected function title_to_filename( $title, $extension ) {
56
		$title = sanitize_file_name( $title );
57
		$title = strtolower( $title );
58
		$title = remove_accents( $title );
59
		$title = preg_replace( array(
60
			'~\s+~',
61
			'~[^\w\d-]+~u',
62
			'~-+~',
63
		), array(
64
			'-',
65
			'-',
66
			'-',
67
		), $title );
68
		return $title . $extension;
69
	}
70
71
	/**
72
	 * Attach container as a theme options page/subpage.
73
	 */
74
	public function init() {
75
		if ( ! $this->settings['file'] ) {
76
			$this->settings['file'] = $this->title_to_filename( 'crb_' . $this->get_id(), '.php' );
77
		}
78
79
		$registered = $this->register_page();
80
		if ( $registered ) {
81
			add_action( 'admin_menu', array( $this, '_attach' ) );
82
		}
83
	}
84
85
	/**
86
	 * Checks whether the current save request is valid
87
	 *
88
	 * @return bool
89
	 */
90
	public function is_valid_save() {
91
		if ( ! $this->verified_nonce_in_request() ) {
92
			return false;
93
		}
94
95
		return $this->is_valid_attach_for_object( null );
96
	}
97
98
	/**
99
	 * Perform save operation after successful is_valid_save() check.
100
	 * The call is propagated to all fields in the container.
101
	 *
102
	 * @param mixed $user_data
103
	 */
104
	public function save( $user_data = null ) {
105
		try {
106
			parent::save( $user_data );
107
		} catch ( Incorrect_Syntax_Exception $e ) {
108
			$this->errors[] = $e->getMessage();
109
		}
110
111
		do_action( 'carbon_fields_theme_options_container_saved', $user_data, $this );
112
113
		if ( ! headers_sent() ) {
114
			wp_redirect( add_query_arg( array( 'settings-updated' => 'true' ) ) );
115
		}
116
	}
117
118
	/**
119
	 * Get environment array for page request (in admin)
120
	 *
121
	 * @return array
122
	 */
123
	protected function get_environment_for_request() {
124
		return array();
125
	}
126
127
	/**
128
	 * Perform checks whether the container should be attached during the current request
129
	 *
130
	 * @return bool True if the container is allowed to be attached
131
	 */
132
	public function is_valid_attach_for_request() {
133
		return $this->static_conditions_pass();
134
	}
135
136
	/**
137
	 * Get environment array for object id
138
	 *
139
	 * @return array
140
	 */
141
	protected function get_environment_for_object( $object_id ) {
142
		return array();
143
	}
144
145
	/**
146
	 * Check container attachment rules against object id
147
	 *
148
	 * @param int $object_id
149
	 * @return bool
150
	 */
151
	public function is_valid_attach_for_object( $object_id = null ) {
152
		return $this->all_conditions_pass( intval( $object_id ) );
153
	}
154
155
	/**
156
	 * Add theme options container pages.
157
	 * Hook the container saving action.
158
	 */
159
	public function attach() {
160
		// use the "read" capability because conditions will handle actual access and save capability checking
161
		// before the attach() method is called
162
163
		// Add menu page
164
		if ( ! $this->settings['parent'] ) {
165
			add_menu_page(
166
				$this->title,
167
				$this->settings['menu_title'] ? $this->settings['menu_title'] : $this->title,
168
				'read',
169
				$this->settings['file'],
170
				array( $this, 'render' ),
171
				$this->settings['icon'],
172
				$this->settings['menu_position']
173
			);
174
		}
175
176
		add_submenu_page(
177
			$this->settings['parent'],
178
			$this->title,
179
			$this->settings['menu_title'] ? $this->settings['menu_title'] : $this->title,
180
			'read',
181
			$this->settings['file'],
182
			array( $this, 'render' )
183
		);
184
185
		$page_hook = get_plugin_page_hookname( $this->settings['file'], '' );
186
		add_action( 'load-' . $page_hook, array( $this, '_save' ) );
187
	}
188
189
	/**
190
	 * Whether this container is currently viewed.
191
	 *
192
	 * @return boolean
193
	 */
194
	public function should_activate() {
195
		$input = stripslashes_deep( $_GET );
196
		$request_page = isset( $input['page'] ) ? $input['page'] : '';
197
		if ( ! empty( $request_page ) && $request_page === $this->settings['file'] ) {
198
			return true;
199
		}
200
201
		return false;
202
	}
203
204
	/**
205
	 * Output the container markup
206
	 */
207
	public function render() {
208
		$input = stripslashes_deep( $_GET );
209
		$request_settings_updated = isset( $input['settings-updated'] ) ? $input['settings-updated'] : '';
210
		if ( $request_settings_updated === 'true' ) {
211
			$this->notifications[] = __( 'Settings saved.', 'carbon-fields' );
212
		}
213
214
		include \Carbon_Fields\DIR . '/templates/Container/theme_options.php';
215
	}
216
217
	/**
218
	 * Register the page while making sure it is unique.
219
	 *
220
	 * @return boolean
221
	 */
222
	protected function register_page() {
223
		$file = $this->settings['file'];
224
		$parent = $this->settings['parent'];
225
226
		if ( ! $parent ) {
227
			// Register top level page
228
			if ( isset( static::$registered_pages[ $file ] ) ) {
229
				Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" already registered' );
230
				return false;
231
			}
232
233
			static::$registered_pages[ $file ] = array();
234
			return true;
235
		}
236
237
		// Register sub-page
238
		if ( ! isset( static::$registered_pages[ $parent ] ) ) {
239
			static::$registered_pages[ $parent ] = array();
240
		}
241
242
		if ( in_array( $file, static::$registered_pages[ $parent ] ) ) {
243
			Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" with parent "' . $parent . '" is already registered. Please set a name for the container.' );
244
			return false;
245
		}
246
247
		static::$registered_pages[ $parent ][] = $file;
248
		return true;
249
	}
250
251
	/**
252
	 * Change the parent theme options page of this container
253
	 *
254
	 * @param  string|Theme_Options_Container $parent
255
	 * @return Container                      $this
256
	 */
257
	public function set_page_parent( $parent ) {
258
		if ( is_a( $parent, get_class() ) ) {
259
			$this->settings['parent'] = $this->title_to_filename( 'crb_' . $parent->get_id(), '.php' );
0 ignored issues
show
Bug introduced by
It seems like $parent is not always an object, but can also be of type string. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
260
			return $this;
261
		}
262
263
		$this->settings['parent'] = $parent;
264
		return $this;
265
	}
266
267
	/**
268
	 * Set the theme options file name of this container.
269
	 *
270
	 * @param  string    $file
271
	 * @return Container $this
272
	 */
273
	public function set_page_file( $file ) {
274
		$this->settings['file'] = $file;
275
		return $this;
276
	}
277
278
	/**
279
	 * Set the title of this container in the administration menu.
280
	 *
281
	 * @param  string    $title
282
	 * @return Container $this
283
	 */
284
	public function set_page_menu_title( $title ) {
285
		$this->settings['menu_title'] = $title;
286
		return $this;
287
	}
288
289
	/**
290
	 * Alias of the set_page_menu_position() method for backwards compatibility
291
	 *
292
	 * @param  integer   $position
293
	 * @return Container $this
294
	 */
295
	public function set_page_position( $position ) {
296
		return $this->set_page_menu_position( $position );
297
	}
298
299
	/**
300
	 * Set the page position of this container in the administration menu.
301
	 *
302
	 * @param  integer   $position
303
	 * @return Container $this
304
	 */
305
	public function set_page_menu_position( $position ) {
306
		$this->settings['menu_position'] = $position;
307
		return $this;
308
	}
309
310
	/**
311
	 * Set the icon of this theme options page.
312
	 * Applicable only for parent theme option pages.
313
	 *
314
	 * @param  string    $icon
315
	 * @return Container $this
316
	 */
317
	public function set_icon( $icon ) {
318
		$this->settings['icon'] = $icon;
319
		return $this;
320
	}
321
}
322