Completed
Pull Request — development (#194)
by
unknown
04:27
created

User_Meta_Container::attach()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Carbon_Fields\Container;
4
5
use Carbon_Fields\Datastore\Meta_Datastore;
6
use Carbon_Fields\Datastore\User_Meta_Datastore;
7
8
class User_Meta_Container extends Container {
9
	protected $user_id;
10
11
	public $settings = array(
12
		'show_on' => array(
13
			'role' => array(),
14
		),
15
		'show_for' => array(
16
			'capabilities' => array( 'edit_users' ),
17
		),
18
	);
19
20
	/**
21
	 * Create a new user meta container
22
	 *
23
	 * @param string $title Unique title of the container
24
	 **/
25
	public function __construct( $title ) {
26
		parent::__construct( $title );
27
28
		if ( ! $this->get_datastore() ) {
29
			$this->set_datastore( new User_Meta_Datastore() );
30
		}
31
	}
32
33
	/**
34
	 * Bind attach() and save() to the appropriate WordPress actions.
35
	 **/
36
	public function init() {
37
		add_action( 'admin_init', array( $this, '_attach' ) );
38
		add_action( 'profile_update', array( $this, '_save' ), 10, 1 );
39
		add_action( 'user_register', array( $this, '_save' ), 10, 1 );
40
	}
41
42
	/**
43
	 * Perform save operation after successful is_valid_save() check.
44
	 * The call is propagated to all fields in the container.
45
	 *
46
	 * @param int $user_id ID of the user against which save() is ran
47
	 **/
48
	public function save( $user_id ) {
49
		// Unhook action to garantee single save
50
		remove_action( 'profile_update', array( $this, '_save' ) );
51
52
		$this->set_user_id( $user_id );
53
54
		foreach ( $this->fields as $field ) {
55
			$field->set_value_from_input();
56
			$field->save();
57
		}
58
59
		do_action( 'carbon_after_save_user_meta', $user_id );
60
	}
61
62
	/**
63
	 * Checks whether the current request is valid
64
	 *
65
	 * @return bool
66
	 **/
67
	public function is_valid_save( $user_id = 0 ) {
68 View Code Duplication
		if ( ! isset( $_REQUEST[ $this->get_nonce_name() ] ) || ! wp_verify_nonce( $_REQUEST[ $this->get_nonce_name() ], $this->get_nonce_name() ) ) { // Input var okay.
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
69
			return false;
70
		} else if ( ! $this->is_valid_attach() ) {
71
			return false;
72
		}
73
74
		return $this->is_valid_save_conditions( $user_id );
75
	}
76
77
	/**
78
	 * Perform checks whether the current save() request is valid
79
	 *
80
	 * @param int $user_id ID of the user against which save() is ran
81
	 * @return bool
82
	 **/
83
	public function is_valid_save_conditions( $user_id ) {
84
		$valid = true;
85
		$user = get_userdata( $user_id );
86
87
		if ( empty( $user->roles ) ) {
88
			return;
89
		}
90
91
		// Check user role
92
		if ( ! empty( $this->settings['show_on']['role'] ) ) {
93
			$allowed_roles = (array) $this->settings['show_on']['role'];
94
95
			// array_shift removed the returned role from the $user_profile->roles
96
			// $roles_to_shift prevents changing of the $user_profile->roles variable
97
			$roles_to_shift = $user->roles;
98
			$profile_role = array_shift( $roles_to_shift );
99
			if ( ! in_array( $profile_role, $allowed_roles ) ) {
100
				$valid = false;
101
			}
102
		}
103
104
		return $valid;
105
	}
106
107
	/**
108
	 * Show the container only on users who have the $role role.
109
	 *
110
	 * @param string $role
111
	 * @return object $this
112
	 **/
113
	public function show_on_user_role( $role ) {
114
		$this->settings['show_on']['role'] = (array) $role;
115
116
		return $this;
117
	}
118
119
	/**
120
	 * Show the container only for users who have either capabilities or roles setup
121
	 *
122
	 * @param array $show_for
123
	 * @return object $this
124
	 **/
125
	public function show_for( $show_for ) {
126
		// Filter empty values and unexpected attributes
127
		$show_for = shortcode_atts( $show_for , array(
128
			'capabilities' => array(),
129
			'roles' => array(),
130
		) );
131
132
		if ( empty( $show_for ) ) {
133
			return $this;
134
		}
135
136
		$this->settings['show_for'] = $show_for;
137
138
		return $this;
139
	}
140
141
	/**
142
	 * Add the container to the user
143
	 **/
144
	public function attach() {
145
		add_action( 'show_user_profile', array( $this, 'render' ), 10, 1 );
146
		add_action( 'edit_user_profile', array( $this, 'render' ), 10, 1 );
147
		add_action( 'user_new_form', array( $this, 'render' ), 10, 1 );
148
	}
149
150
	/**
151
	 * Whether we're on the user profile page
152
	 **/
153
	public function is_profile_page() {
154
		global $pagenow;
155
156
		return $pagenow === 'profile.php' || $pagenow === 'user-new.php' || $pagenow === 'user-edit.php';
157
	}
158
159
	/**
160
	 * Perform checks whether the container should be attached during the current request
161
	 *
162
	 * @return bool True if the container is allowed to be attached
163
	 **/
164
	public function is_valid_attach() {
165
		$user = wp_get_current_user();
166
167
		$is_valid_capability = true;
168 View Code Duplication
		if ( !empty( $this->settings['show_for']['capabilities'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
169
			$is_valid_capability = array_intersect( (array) $this->settings['show_for']['capabilities'], $user->allcaps );
170
		}
171
172
		$is_valid_role = true;
173 View Code Duplication
		if ( !empty( $this->settings['show_for']['roles'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
174
			$is_valid_role = array_intersect( (array) $this->settings['show_for']['roles'], $user->roles );
175
		}
176
177
		if ( ! $this->is_profile_page() || ! $is_valid_capability || ! $is_valid_role ) {
178
			return false;
179
		}
180
181
		return true;
182
	}
183
184
	/**
185
	 * Output the container markup
186
	 **/
187
	public function render( $user_profile = null ) {
188
		$profile_role = '';
189
190
		if ( is_object( $user_profile ) ) {
191
			$this->set_user_id( $user_profile->ID );
192
193
			// array_shift removed the returned role from the $user_profile->roles
194
			// $roles_to_shift prevents changing of the $user_profile->roles variable
195
			$roles_to_shift = $user_profile->roles;
196
			$profile_role = array_shift( $roles_to_shift );
197
		}
198
199
		include \Carbon_Fields\DIR . '/templates/Container/user_meta.php';
200
	}
201
202
	/**
203
	 * Set the user ID the container will operate with.
204
	 *
205
	 * @param int $user_id
206
	 **/
207
	public function set_user_id( $user_id ) {
208
		$this->user_id = $user_id;
209
		$this->store->set_id( $user_id );
210
	}
211
}
212