-
Notifications
You must be signed in to change notification settings - Fork 0
/
user_service.php
212 lines (186 loc) · 6.27 KB
/
user_service.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<?php
namespace SmartHistoryTourManager;
require_once(dirname(__FILE__) . '/db.php');
require_once(dirname(__FILE__) . '/models/areas.php');
/**
* This is a wrapper around wordpress' current user (a WP_User object). It
* determines access and update rights based on wordpress roles and cpabilities.
*/
class UserService {
// the key used to set the current users chosen area in the wordpress user
// settings
const CURRENT_AREA_KEY = "shtm_current_area";
// a WP_User object or 0 if no user is logged in, cf. wp_get_current_user()
private $user;
// the wp-roles that are interesting for us
private static $admin_role = 'administrator';
private static $contributor_role = 'contributor-with-upload';
private function __construct() {
$this->user = wp_get_current_user();
}
public static function instance() {
static $instance = null;
if ($instance === null) {
$instance = new self();
}
return $instance;
}
/**
* Returns access conditions for the current user. This answers the question
* "Which values must an object have to be readable by the current user?"
* The result is a set of key => value pairs that can be used in a database
* query.
*
* On a user without relevant roles the result array will contain the
* key/value pair true => false which can be inserted in a where clause to
* prevent the return of any results (WHERE true = false).
*
* @return array
*/
public function access_conditions() {
$conditions = array();
if($this->is_admin()) {
// do nothing
} else if ($this->is_contributor()) {
$conditions['user_id'] = $this->user_id();
} else {
$conditions['true'] = 'false';
}
return $conditions;
}
public function is_contributor($id = null) {
return in_array(self::$contributor_role, $this->get_roles($id));
}
public function is_admin($id = null) {
return in_array(self::$admin_role, $this->get_roles($id));
}
public function user_may_edit_place($place) {
return ($this->is_admin() || ($this->user_id() == $place->user_id));
}
public function user_may_edit_tour($tour) {
return ($this->is_admin() || ($this->user_id() == $tour->user_id));
}
public function user_may_publish_tours() {
return $this->is_admin();
}
public function is_logged_in() {
return !empty($this->user);
}
/**
* Sets the area for the current user. (Uses the wordpress user settings.)
*
* @return bool To indicate success/failure
*/
public function set_current_area_id($id) {
if(!is_int($id)) {
throw new UserServiceException(
"Area id must be present and int value, is: $id.");
return false;
}
$result = false;
if(!empty($this->user)) {
$result = set_user_setting(self::CURRENT_AREA_KEY, strval($id));
if(empty($result)) {
throw new UserServiceException(
"Failed to set current area for user.");
$result = false;
}
}
return $result;
}
/**
* Gets the current area id for the current user.
* (Uses the wordpress user settings)
*
* @return int The area id if successful, else DB::BAD_ID
*/
public function get_current_area_id() {
$id = get_user_setting(self::CURRENT_AREA_KEY, DB::BAD_ID);
if(!is_numeric($id)) {
throw new UserServiceException(
"Bad value in setting: current_area_id.");
}
if($id == DB::BAD_ID || !Areas::instance()->valid_id($id)) {
$id = Areas::instance()->first_id();
if($id == DB::BAD_ID) {
throw new UserServiceException("Cannot set default area id.");
} else {
$this->set_current_area_id($id);
}
}
return intval($id);
}
/**
* Returns the id of the currently logged in user or DB::BAD_ID if no user
* is logged in.
*/
public function user_id() {
if(empty($this->user)) {
return DB::BAD_ID;
}
return intval($this->user->ID);
}
/**
* Wrapper for the worpress function get_userdata
*
* @return WP_User|false The WP_User object on success else fals.
*/
public function get_user($id) {
return get_userdata($id);
}
/**
* Get all posts the current user may link to a mapstop. Avalilable posts
* for contributors are those that belong to them and are not connected, for
* admins they are all posts, that are not connected to mapstops.
*
* Only posts with a 'draft' status are returned as these are the only ones
* used by us.
*
* @param int $user_id The user to get posts for. If null, the current
* user's posts will be fetched.
*
* @return array An array of WP_Posts or an empty array if an o
*/
public function get_available_posts() {
$args = array(
'numberposts' => -1,
'post_status' => 'draft',
'exclude' => Mapstops::instance()->get_linked_post_ids(),
);
if(!$this->is_admin()) {
$args['author'] = $this->user_id();
}
$result = get_posts($args);
return $result;
}
// TODO: This belongs somewhere else
public function get_posts($post_ids) {
// retrieve posts one by one to preserve the order of the input ids
$result = array();
foreach ($post_ids as $id) {
$posts = get_posts(array(
'p' => $id,
'post_status' => 'draft',
'numberposts' => 1,
));
if(!empty($posts)) {
$result[] = $posts[0];
}
}
return $result;
}
private function get_roles($id = null) {
$roles = array();
if (isset($id)) {
$user = get_userdata($id);
if ($user) {
$roles = $user->roles;
}
} else {
$roles = $this->user->roles;
}
return $roles;
}
}
class UserServiceException extends \Exception {}
?>