Completed
Push — milestone/2_0/react-ui ( 1c376a...57d10c )
by
unknown
02:51
created

Theme_Options_Container   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 278
ccs 0
cts 112
cp 0
rs 8.8
c 1
b 0
f 0
wmc 36
lcom 4
cbo 3

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A clear_string() 0 3 1
B init() 0 16 5
A is_valid_save() 0 7 2
A save() 0 13 3
A get_environment_for_request() 0 3 1
A is_valid_attach_for_request() 0 3 1
A get_environment_for_object() 0 3 1
A is_valid_attach_for_object() 0 3 1
B attach() 0 29 2
A should_activate() 0 9 4
A render() 0 9 3
B register_page() 0 28 5
A set_page_parent() 0 8 2
A set_icon() 0 4 1
A set_page_file() 0 4 1
A set_page_position() 0 4 1
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
		'position' => null,
30
	);
31
32
	/**
33
	 * Create a new container
34
	 *
35
	 * @param string $unique_id Unique id of the container
36
	 * @param string $title title of the container
37
	 * @param string $type Type of the container
38
	 */
39
	public function __construct( $unique_id, $title, $type ) {
40
		parent::__construct( $unique_id, $title, $type );
41
42
		if ( ! $this->get_datastore() ) {
43
			$this->set_datastore( Datastore::make( 'theme_options' ), $this->has_default_datastore() );
1 ignored issue
show
Bug introduced by
It seems like \Carbon_Fields\Datastore...::make('theme_options') can be null; however, set_datastore() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
44
		}
45
	}
46
47
	/**
48
	 * Sanitize the container title for use in
49
	 * the theme options file name.
50
	 *
51
	 * @param string $string
52
	 * @return string
53
	 */
54
	protected function clear_string( $string ) {
55
		return preg_replace( array( '~ +~', '~[^\w\d-]+~u', '~-+~' ), array( '-', '-', '-' ), strtolower( remove_accents( $string ) ) );
56
	}
57
58
	/**
59
	 * Attach container as a theme options page/subpage.
60
	 */
61
	public function init() {
62
		if ( $this->settings['parent'] !== '' && strpos( $this->settings['parent'], '.php' ) === false ) {
63
			$clear_title = $this->clear_string( $this->settings['parent'] );
64
			$this->settings['parent'] = 'crbn-' . $clear_title . '.php';
65
		}
66
67
		if ( ! $this->settings['file'] ) {
68
			$clear_title = $this->clear_string( $this->title );
69
			$this->settings['file'] .= 'crbn-' . $clear_title . '.php';
70
		}
71
72
		$registered = $this->register_page();
73
		if ( $registered ) {
74
			add_action( 'admin_menu', array( $this, '_attach' ) );
75
		}
76
	}
77
78
	/**
79
	 * Checks whether the current save request is valid
80
	 *
81
	 * @return bool
82
	 */
83
	public function is_valid_save() {
84
		if ( ! $this->verified_nonce_in_request() ) {
85
			return false;
86
		}
87
88
		return $this->is_valid_attach_for_object( null );
89
	}
90
91
	/**
92
	 * Perform save operation after successful is_valid_save() check.
93
	 * The call is propagated to all fields in the container.
94
	 *
95
	 * @param mixed $user_data
96
	 */
97
	public function save( $user_data = null ) {
98
		try {
99
			parent::save( $user_data );
100
		} catch ( Incorrect_Syntax_Exception $e ) {
101
			$this->errors[] = $e->getMessage();
102
		}
103
104
		do_action( 'carbon_after_save_theme_options', $user_data );
105
106
		if ( ! headers_sent() ) {
107
			wp_redirect( add_query_arg( array( 'settings-updated' => 'true' ) ) );
108
		}
109
	}
110
111
	/**
112
	 * Get environment array for page request (in admin)
113
	 *
114
	 * @return array
115
	 */
116
	protected function get_environment_for_request() {
117
		return array();
118
	}
119
120
	/**
121
	 * Perform checks whether the container should be attached during the current request
122
	 *
123
	 * @return bool True if the container is allowed to be attached
124
	 */
125
	public function is_valid_attach_for_request() {
126
		return $this->static_conditions_pass();
127
	}
128
129
	/**
130
	 * Get environment array for object id
131
	 *
132
	 * @return array
133
	 */
134
	protected function get_environment_for_object( $object_id ) {
135
		return array();
136
	}
137
138
	/**
139
	 * Check container attachment rules against object id
140
	 *
141
	 * @param int $object_id
142
	 * @return bool
143
	 */
144
	public function is_valid_attach_for_object( $object_id = null ) {
145
		return $this->all_conditions_pass( intval( $object_id ) );
146
	}
147
148
	/**
149
	 * Add theme options container pages.
150
	 * Hook the container saving action.
151
	 */
152
	public function attach() {
153
		// use the "read" capability because conditions will handle actual access and save capability checking
154
		// before the attach() method is called
155
156
		// Add menu page
157
		if ( ! $this->settings['parent'] ) {
158
			add_menu_page(
159
				$this->title,
160
				$this->title,
161
				'read',
162
				$this->settings['file'],
163
				array( $this, 'render' ),
164
				$this->settings['icon'],
165
				$this->settings['position']
166
			);
167
		}
168
169
		add_submenu_page(
170
			$this->settings['parent'],
171
			$this->title,
172
			$this->title,
173
			'read',
174
			$this->settings['file'],
175
			array( $this, 'render' )
176
		);
177
178
		$page_hook = get_plugin_page_hookname( $this->settings['file'], '' );
179
		add_action( 'load-' . $page_hook, array( $this, '_save' ) );
180
	}
181
182
	/**
183
	 * Whether this container is currently viewed.
184
	 *
185
	 * @return boolean
186
	 */
187
	public function should_activate() {
188
		$input = stripslashes_deep( $_GET );
189
		$request_page = isset( $input['page'] ) ? $input['page'] : '';
190
		if ( ! empty( $request_page ) && $request_page === $this->settings['file'] ) {
191
			return true;
192
		}
193
194
		return false;
195
	}
196
197
	/**
198
	 * Output the container markup
199
	 */
200
	public function render() {
201
		$input = stripslashes_deep( $_GET );
202
		$request_settings_updated = isset( $input['settings-updated'] ) ? $input['settings-updated'] : '';
203
		if ( $request_settings_updated === 'true' ) {
204
			$this->notifications[] = __( 'Settings saved.', 'carbon-fields' );
205
		}
206
207
		include \Carbon_Fields\DIR . '/templates/Container/theme_options.php';
208
	}
209
210
	/**
211
	 * Register the page while making sure it is unique.
212
	 *
213
	 * @return boolean
214
	 */
215
	public function register_page() {
216
		$file = $this->settings['file'];
217
		$parent = $this->settings['parent'];
218
219
		if ( ! $parent ) {
220
			// Register top level page
221
			if ( isset( static::$registered_pages[ $file ] ) ) {
222
				Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" already registered' );
223
				return false;
224
			}
225
226
			static::$registered_pages[ $file ] = array();
227
			return true;
228
		}
229
230
		// Register sub-page
231
		if ( ! isset( static::$registered_pages[ $parent ] ) ) {
232
			static::$registered_pages[ $parent ] = array();
233
		}
234
235
		if ( in_array( $file, static::$registered_pages[ $parent ] ) ) {
236
			Incorrect_Syntax_Exception::raise( 'Page "' . $file . '" with parent "' . $parent . '" is already registered. Please set a name for the container.' );
237
			return false;
238
		}
239
240
		static::$registered_pages[ $parent ][] = $file;
241
		return true;
242
	}
243
244
	/**
245
	 * Change the parent theme options page of this container
246
	 * 
247
	 * @return Container $this
248
	 */
249
	public function set_page_parent( $parent ) {
250
		if ( is_a( $parent, 'Carbon_Container' ) ) {
251
			$parent = $parent->title;
252
		}
253
254
		$this->settings['parent'] = $parent;
255
		return $this;
256
	}
257
258
	/**
259
	 * Set the icon of this theme options page.
260
	 * Applicable only for parent theme option pages.
261
	 * 
262
	 * @return Container $this
263
	 */
264
	public function set_icon( $icon ) {
265
		$this->settings['icon'] = $icon;
266
		return $this;
267
	}
268
269
	/**
270
	 * Set the theme options file name of this container.
271
	 * 
272
	 * @return Container $this
273
	 */
274
	public function set_page_file( $file ) {
275
		$this->settings['file'] = $file;
276
		return $this;
277
	}
278
279
	/**
280
	 * Set the page position of this container in the administration menu.
281
	 * 
282
	 * @return Container $this
283
	 */
284
	public function set_page_position( $position ) {
285
		$this->settings['position'] = $position;
286
		return $this;
287
	}
288
}
289
290