| 1 |
<?php |
| 2 |
namespace LWS\WOOREWARDS\Ui\Editlists; |
| 3 |
|
| 4 |
// don't call the file directly |
| 5 |
if( !defined( 'ABSPATH' ) ) exit(); |
| 6 |
|
| 7 |
/** Display users and their point at backend. */ |
| 8 |
class UsersPoints extends \LWS\Adminpanel\EditList\Source |
| 9 |
{ |
| 10 |
const L_PREFIX = 'lws_wre_pool_'; |
| 11 |
const S_PREFIX = 'lws_wre_points_'; |
| 12 |
|
| 13 |
protected $sortSource = false; |
| 14 |
protected $stackIds = false; |
| 15 |
|
| 16 |
public function getEditCapability(): string |
| 17 |
{ |
| 18 |
return 'manage_rewards'; |
| 19 |
} |
| 20 |
|
| 21 |
function labels() |
| 22 |
{ |
| 23 |
$default = \LWS_WooRewards::getInstalledPool(); |
| 24 |
if (!$default) { |
| 25 |
$prefabs = \LWS_WooRewards::getPrefabPools(false); |
| 26 |
if ($prefabs) |
| 27 |
$default = $prefabs->first(); |
| 28 |
} |
| 29 |
$column = self::L_PREFIX . ($default ? $default->getId() : 'default'); |
| 30 |
$labels = array( |
| 31 |
'user' => array(__("Users", 'woorewards-lite'), '1fr'), |
| 32 |
$column => array(\LWS_WooRewards::getPointSymbol(2, $default), 'max-content'), // usermeta 'lws_wre_points_default' |
| 33 |
'rewards' => array(__("Rewards", 'woorewards-lite'), 'auto'), // filled by filter |
| 34 |
); |
| 35 |
return \apply_filters('lws_woorewards_ui_userspoints_labels', $labels); |
| 36 |
} |
| 37 |
|
| 38 |
function read($limit) |
| 39 |
{ |
| 40 |
global $wpdb; |
| 41 |
$request = \LWS\Adminpanel\Tools\Request::from($wpdb->users, 'u'); |
| 42 |
$request->select('u.ID as user_id, u.*'); |
| 43 |
$request->group('u.ID'); |
| 44 |
$request->rowLimit($limit); |
| 45 |
$this->addSorting($request); |
| 46 |
|
| 47 |
$request = \apply_filters('lws_woorewards_admin_userspoints_request', $this->search($request), true); |
| 48 |
$users = $request->getResults(ARRAY_A); |
| 49 |
if (!$users) |
| 50 |
return array(); |
| 51 |
else |
| 52 |
return \array_map(array($this, 'shapeRow'), $users); |
| 53 |
} |
| 54 |
|
| 55 |
function shapeRow($user) |
| 56 |
{ |
| 57 |
global $wpdb; |
| 58 |
// get all points for that user |
| 59 |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching |
| 60 |
$points = $wpdb->get_results($wpdb->prepare( |
| 61 |
"SELECT meta_key, meta_value FROM {$wpdb->usermeta} WHERE user_id = %d AND meta_key LIKE %s", |
| 62 |
(int)$user['user_id'], |
| 63 |
self::S_PREFIX . '%' |
| 64 |
), OBJECT_K); |
| 65 |
// format them |
| 66 |
foreach ($this->getStackIds() as $info) { |
| 67 |
$column = (self::L_PREFIX . $info->post_id); |
| 68 |
$key = (self::S_PREFIX . $info->stack_id); |
| 69 |
$amount = (isset($points[$key]) ? $points[$key]->meta_value : 0); |
| 70 |
$user[$key] = \LWS_WooRewards::formatPoints($amount, $info->post_id); |
| 71 |
$user[$column] = sprintf( |
| 72 |
"<a class='lws_wre_point_history maxwidth right lws-icon-time-machine' data-stack='%s' data-user='%d'>%s</a>", |
| 73 |
\esc_attr($info->stack_id), |
| 74 |
(int)$user['user_id'], |
| 75 |
\apply_filters('lws_wre_editlist_point_amount_display', $user[$key], $user, $info->post_id, $info) |
| 76 |
); |
| 77 |
} |
| 78 |
// user name |
| 79 |
$edit = esc_attr(\get_edit_user_link($user['user_id'])); |
| 80 |
$mailto = esc_attr('mailto:' . $user['user_email']); |
| 81 |
$display = \apply_filters('lws_woorewards_customer_display_name', $user['display_name'], $user); |
| 82 |
$user['user'] = implode(' - ', array( |
| 83 |
"<a href='{$edit}' target='_blank'>{$user['user_login']}</a>", |
| 84 |
"<a href='{$mailto}'>{$user['user_email']}</a>", |
| 85 |
"<span class='lws_wre_history_dispname'>{$display}</span>" |
| 86 |
)); |
| 87 |
// rewards |
| 88 |
$user['rewards'] = "<div class='lws-editlist-btns-line'>"; |
| 89 |
$user['rewards'] .= implode('', \apply_filters('lws_woorewards_ui_userspoints_rewards_cell', array(), $user)); |
| 90 |
$user['rewards'] .= "</div>"; |
| 91 |
// return modified value |
| 92 |
return $user; |
| 93 |
} |
| 94 |
|
| 95 |
/** @return array as [string:pool_name] => object{post_name, stack_id} */ |
| 96 |
protected function getStackIds() |
| 97 |
{ |
| 98 |
if (false === $this->stackIds) |
| 99 |
{ |
| 100 |
global $wpdb; |
| 101 |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching |
| 102 |
$this->stackIds = $wpdb->get_results("SELECT post_id, post_name, meta_value as stack_id FROM {$wpdb->postmeta} INNER JOIN {$wpdb->posts} ON ID=post_id WHERE meta_key='wre_pool_point_stack'", OBJECT_K); |
| 103 |
} |
| 104 |
return $this->stackIds; |
| 105 |
} |
| 106 |
|
| 107 |
function total() |
| 108 |
{ |
| 109 |
global $wpdb; |
| 110 |
$request = \LWS\Adminpanel\Tools\Request::from($wpdb->users, 'u'); |
| 111 |
$request->select('COUNT(u.ID)'); |
| 112 |
$request = \apply_filters('lws_woorewards_admin_userspoints_request', $this->search($request), false); |
| 113 |
$c = $request->getVar(); |
| 114 |
return (\is_null($c) ? -1 : $c); |
| 115 |
} |
| 116 |
|
| 117 |
/** @return object the given $sql array with WHERE clause if required. */ |
| 118 |
protected function search($request) |
| 119 |
{ |
| 120 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- admin editlist search |
| 121 |
$needle = isset($_REQUEST['usersearch']) ? \sanitize_text_field(\wp_unslash($_REQUEST['usersearch'])) : ''; |
| 122 |
if ($needle) { |
| 123 |
global $wpdb; |
| 124 |
$mask = ("'%" . \esc_sql($needle) . "%'"); |
| 125 |
$where = array( |
| 126 |
'condition' => 'OR', |
| 127 |
"u.user_login LIKE {$mask}", |
| 128 |
"u.user_email LIKE {$mask}", |
| 129 |
"u.display_name LIKE {$mask}", |
| 130 |
"u.user_nicename LIKE {$mask}", |
| 131 |
); |
| 132 |
if (($id = \intval($needle)) > 0) |
| 133 |
$where[] = "u.ID = {$id}"; |
| 134 |
if (\get_option('lws_woorewards_admin_userspoints_deep_search', 'on')) |
| 135 |
$where[] = "u.ID IN (SELECT m.user_id FROM {$wpdb->usermeta} as m WHERE m.meta_value LIKE {$mask} AND (m.meta_key LIKE '%name' OR m.meta_key LIKE 'billing_%'))"; |
| 136 |
$request->where($where); |
| 137 |
} |
| 138 |
return $request; |
| 139 |
} |
| 140 |
|
| 141 |
protected function addSorting(&$request) |
| 142 |
{ |
| 143 |
$asc = !$this->isSortDescsending('userspoints'); |
| 144 |
$value = $this->getSortValue('userspoints'); |
| 145 |
if ($value) { |
| 146 |
$value = explode('-', $value, 2); |
| 147 |
if (count($value) > 1) { |
| 148 |
global $wpdb; |
| 149 |
// need usermeta points |
| 150 |
$request->leftJoin($wpdb->usermeta, 'csort', $wpdb->prepare( |
| 151 |
'csort.user_id=u.ID AND csort.meta_key=%s', |
| 152 |
'lws_wre_points_' . $value[1] |
| 153 |
)); |
| 154 |
// numerical order on casted or inexistant value |
| 155 |
return $request->order( |
| 156 |
'CASE WHEN csort.meta_value IS NOT NULL THEN CAST(csort.meta_value AS SIGNED) ELSE 0 END', |
| 157 |
$asc |
| 158 |
); |
| 159 |
} elseif ('email' == $value[0]) { |
| 160 |
return $request->order('u.user_email', $asc); |
| 161 |
} elseif ('name' == $value[0]) { |
| 162 |
return $request->order('u.display_name', $asc); |
| 163 |
} |
| 164 |
} |
| 165 |
return $request->order('u.user_login', $asc); |
| 166 |
} |
| 167 |
|
| 168 |
public function getSortColumns() |
| 169 |
{ |
| 170 |
if (false === $this->sortSource) { |
| 171 |
global $wpdb; |
| 172 |
$sql = "SELECT pool.ID, stack.meta_value as stack_id, pool.post_title" |
| 173 |
. " FROM {$wpdb->posts} as `pool`" |
| 174 |
. " LEFT JOIN {$wpdb->postmeta} AS stack ON stack.post_id=pool.ID AND stack.meta_key='wre_pool_point_stack'" |
| 175 |
. " WHERE post_type=%s AND post_status NOT IN ('trash')" |
| 176 |
. " ORDER BY post_title ASC"; |
| 177 |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter |
| 178 |
$stacks = $wpdb->get_results($wpdb->prepare($sql, \LWS\WOOREWARDS\Core\Pool::POST_TYPE)); |
| 179 |
|
| 180 |
$this->sortSource = array( |
| 181 |
array('value' => '', 'label' => __("User Login", 'woorewards-lite')), // user_login |
| 182 |
array('value' => 'email', 'label' => __("Email", 'woorewards-lite')), // user_email |
| 183 |
array('value' => 'name', 'label' => __("Display Name", 'woorewards-lite')), // display_name |
| 184 |
); |
| 185 |
/* translators: %s: loyalty system name */ |
| 186 |
$label = __("Points : %s", 'woorewards-lite'); |
| 187 |
foreach($stacks as $stack) { |
| 188 |
$this->sortSource[] = array( |
| 189 |
'value' => ($stack->ID . '-' . $stack->stack_id), |
| 190 |
'label' => sprintf($label, $stack->post_title), |
| 191 |
); |
| 192 |
} |
| 193 |
} |
| 194 |
return $this->sortSource; |
| 195 |
} |
| 196 |
|
| 197 |
/** no edition, use bulk action */ |
| 198 |
function input() |
| 199 |
{ |
| 200 |
return ''; |
| 201 |
} |
| 202 |
|
| 203 |
/** no edition, use bulk action */ |
| 204 |
function write($row) |
| 205 |
{ |
| 206 |
return false; |
| 207 |
} |
| 208 |
|
| 209 |
/** Cannot erase a user here. */ |
| 210 |
function erase($row) |
| 211 |
{ |
| 212 |
return false; |
| 213 |
} |
| 214 |
} |