db = $db; $this->group_helper = $group_helper; $this->language = $language; $this->log = $log; $this->notification = $notification; $this->operator_cat = $operator_cat; $this->operator_item = $operator_item; $this->request = $request; $this->template = $template; $this->user = $user; $this->groups_table = $groups_table; $this->users_table = $users_table; $this->user_group_table = $user_group_table; $this->inventory_table = $inventory_table; $this->root_path = $root_path; $this->php_ext = $php_ext; } /** * Handle and display the "Inventory" ACP mode. * * @return void * @access public */ public function inventory() { $this->language->add_lang(['ass_acp_common', 'ass_common'], 'phpbbstudio/ass'); $type = $this->request->variable('type', '', true); $submit = $this->request->is_set_post('submit'); $errors = []; $form_key = 'ass_inventory'; add_form_key($form_key); switch ($type) { case 'global'; $action = $this->request->variable('action', 'add', true); $item_ids = $this->request->variable('items', [0]); $group_ids = $this->request->variable('groups', [0]); $usernames = $this->request->variable('usernames', '', true); $items = []; /** @var category $category */ foreach ($this->operator_cat->get_categories() as $category) { $this->template->assign_block_vars('categories', array_merge([ 'S_INACTIVE' => !$category->get_active(), ], $this->operator_cat->get_variables($category))); $items += $category_items = $this->operator_item->get_items($category->get_id()); /** @var item $item */ foreach ($category_items as $item) { $this->template->assign_block_vars('categories.items', array_merge([ 'S_INACTIVE' => !$item->get_active(), 'S_SELECTED' => in_array($item->get_id(), $item_ids), ], $this->operator_item->get_variables($item))); } } if ($submit) { if (!check_form_key($form_key)) { $errors[] = 'FORM_INVALID'; } if (!in_array($action, ['add', 'delete'])) { $errors[] = 'NO_ACTION'; } if (empty($item_ids)) { $errors[] = 'ACP_ASS_NO_ITEMS_SELECTED'; } $user_ids = []; $usernames_array = array_filter(explode("\n", $usernames)); if (empty($usernames_array) && empty($group_ids)) { $this->language->add_lang('acp/permissions'); $errors[] = 'NO_USER_GROUP_SELECTED'; } if (!empty($usernames_array)) { $this->get_ids_from_usernames($usernames_array, $user_ids, $errors); } if (!empty($group_ids)) { $this->get_ids_from_groups($group_ids, $user_ids); } if (empty($errors) && empty($user_ids)) { $errors[] = 'NO_GROUP_MEMBERS'; } if (empty($errors)) { $user_ids = array_unique($user_ids); $this->update_inventory($action, $user_ids, $item_ids); $count_items = count($item_ids); $count_users = count($user_ids); $item_names = []; foreach ($item_ids as $item_id) { $item_names[] = $items[$item_id]->get_title(); } $l_action = 'ACP_ASS_INVENTORY_' . utf8_strtoupper($action); $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, "LOG_{$l_action}", time(), [$count_items, implode(', ', $item_names), $count_users, implode(', ', $usernames_array)]); $message = $this->language->lang("{$l_action}_SUCCESS", $count_items); $message .= '
» ' . $this->language->lang('ACP_ASS_AMOUNT_ITEMS') . $this->language->lang('COLON') . ' ' . $count_items; $message .= '
» ' . $this->language->lang('ACP_ASS_AMOUNT_USERS') . $this->language->lang('COLON') . ' ' . $count_users; $message .= adm_back_link($this->u_action); trigger_error($message); } } $sql = 'SELECT group_id, group_name, group_type FROM ' . $this->groups_table . " WHERE group_name <> 'BOTS' AND group_name <> 'GUESTS' ORDER BY group_type DESC, group_name ASC"; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $this->template->assign_block_vars('groups', [ 'ID' => (int) $row['group_id'], 'NAME' => $this->group_helper->get_name($row['group_name']), 'S_SELECTED' => in_array((int) $row['group_id'], $group_ids), 'S_SPECIAL' => GROUP_SPECIAL === (int) $row['group_type'], ]); } $this->db->sql_freeresult($result); $this->template->assign_vars([ 'USERNAMES' => $usernames, 'S_ADD' => $action === 'add', 'U_FIND_USER' => append_sid("{$this->root_path}memberlist.{$this->php_ext}", [ 'mode' => 'searchuser', 'form' => 'ass_inventory', 'field' => 'usernames', ]), ]); break; case 'manage': $action = $this->request->variable('action', '', true); $username = $this->request->variable('username', '', true); $user_id = $this->request->variable('u', 0); $item_ids = $this->request->variable('items', [0]); if (empty($username) && empty($user_id)) { $this->template->assign_var('U_FIND_USER', append_sid("{$this->root_path}memberlist.{$this->php_ext}", [ 'mode' => 'searchuser', 'form' => 'ass_inventory', 'field' => 'username', 'select_single' => true, ])); } else { if (empty($user_id)) { $user_ids = []; $this->get_ids_from_usernames([$username], $user_ids, $errors); if (empty($user_ids)) { trigger_error($this->language->lang('NO_USER') . adm_back_link($this->u_action . "&type={$type}"), E_USER_WARNING); } $user_id = (int) reset($user_ids); } $rowset = []; $sql = 'SELECT i.*, u.username as gifter_name, u.user_colour as gifter_colour FROM ' . $this->inventory_table . ' i LEFT JOIN ' . $this->users_table . ' u ON i.gifter_id = u.user_id WHERE i.user_id = ' . (int) $user_id; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $rowset[(int) $row['item_id']] = $row; } $this->db->sql_freeresult($result); $inventory = [ 'categories' => array_column($rowset, 'category_id'), 'items' => array_keys($rowset), ]; $items = []; $categories = $this->operator_cat->get_categories(); /** @var category $category */ foreach ($categories as $category) { $this->template->assign_block_vars('categories', array_merge([ 'S_INACTIVE' => !$category->get_active(), 'S_INVENTORY' => in_array($category->get_id(), $inventory['categories']), ], $this->operator_cat->get_variables($category))); $items += $category_items = $this->operator_item->get_items($category->get_id()); /** @var item $item */ foreach ($category_items as $item) { $variables = array_merge([ 'S_INACTIVE' => !$item->get_active(), 'S_INVENTORY' => in_array($item->get_id(), $inventory['items']), 'S_SELECTED' => in_array($item->get_id(), $item_ids), ], $this->operator_item->get_variables($item)); if ($variables['S_INVENTORY']) { $row = $rowset[$item->get_id()]; $variables = array_merge($variables, [ 'GIFTER' => $row['gifter_id'] ? get_username_string('full', $row['gifter_id'], $row['gifter_name'], $row['gifter_colour']) : '', 'PURCHASE_TIME' => $this->user->format_date($row['purchase_time']), 'USE_TIME' => $row['use_time'] ? $this->user->format_date($row['use_time']) : $this->language->lang('NEVER'), 'USE_COUNT' => (int) $row['use_count'], ]); } $this->template->assign_block_vars('categories.items', $variables); } } $u_back = $this->u_action . "&type={$type}&u={$user_id}"; if ($action === 'delete') { $item_id = $this->request->variable('iid', 0); if (confirm_box(true)) { $this->update_inventory($action, [$user_id], [$item_id]); if (empty($username)) { $username = $this->get_username($user_id); } $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_ACP_ASS_INVENTORY_DELETE_USER', time(), [$items[$item_id]->get_title(), $username]); trigger_error($this->language->lang('ASS_DELETE_SUCCESS') . adm_back_link($u_back)); } else { confirm_box(false, 'ASS_DELETE', ''); redirect($u_back); } } if ($submit) { if (!check_form_key($form_key)) { $errors[] = 'FORM_INVALID'; } if (empty($item_ids)) { $errors[] = 'ACP_ASS_NO_ITEMS_SELECTED'; } if (empty($errors)) { $this->update_inventory('add', [$user_id], $item_ids); if (empty($username)) { $username = $this->get_username($user_id); } $count_items = count($item_ids); $item_names = []; foreach ($item_ids as $item_id) { $item_names[] = $items[$item_id]->get_title(); } $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_ACP_ASS_INVENTORY_ADD_USER', time(), [$count_items, implode(', ', $item_names), $username]); trigger_error($this->language->lang('ACP_ASS_INVENTORY_ADD_SUCCESS', $count_items) . adm_back_link($u_back)); } } $this->template->assign_vars([ 'ASS_USERNAME' => $username, 'U_DELETE' => $this->u_action . "&type={$type}&u={$user_id}&action=delete&iid=", ]); } break; default: $this->template->assign_vars([ 'U_GLOBAL' => $this->u_action . '&type=global', 'U_MANAGE' => $this->u_action . '&type=manage', ]); break; } $this->template->assign_vars([ 'ERRORS' => $errors, 'S_TYPE' => $type, 'U_ACTION' => $this->u_action . ($type ? "&type={$type}" : ''), 'U_BACK' => $this->u_action, ]); } /** * Update users' inventories. * * @param string $action The action to perform (add|delete) * @param array $user_ids The user identifiers * @param array $item_ids The item identifiers * @return void * @access protected */ protected function update_inventory($action, array $user_ids, array $item_ids) { switch ($action) { case 'add': $owned = []; $stack = []; $sql = 'SELECT item_id, user_id FROM ' . $this->inventory_table . ' WHERE ' . $this->db->sql_in_set('item_id', $item_ids) . ' AND ' . $this->db->sql_in_set('user_id', $user_ids); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $item_id = (int) $row['item_id']; $user_id = (int) $row['user_id']; $owned[$item_id][] = $user_id; $stack[$user_id][$item_id][] = $item_id; } $this->db->sql_freeresult($result); $items = $this->operator_item->get_items_by_id($item_ids); foreach ($item_ids as $item_id) { /** @var item $item */ $item = $items[$item_id]; $users = !empty($owned[$item_id]) && !$item->get_stack() ? array_diff($user_ids, $owned[$item_id]) : $user_ids; foreach ($users as $user_id) { $sql = 'INSERT INTO ' . $this->inventory_table . ' ' . $this->db->sql_build_array('INSERT', [ 'category_id' => $item->get_category(), 'item_id' => $item->get_id(), 'user_id' => $user_id, 'gifter_id' => (int) $this->user->data['user_id'], 'purchase_time' => time(), 'purchase_price' => 0.00, ]); $this->db->sql_query($sql); $index = !empty($stack[$user_id][$item_id]) ? count($stack[$user_id][$item_id]) : 0; $index = $index + 1; $this->notification->gift($item, $user_id, $this->db->sql_nextid(), $index); } } break; case 'delete': $sql = 'DELETE FROM ' . $this->inventory_table . ' WHERE ' . $this->db->sql_in_set('item_id', $item_ids) . ' AND ' . $this->db->sql_in_set('user_id', $user_ids); $this->db->sql_query($sql); break; } } /** * Get user identifiers from usernames. * * @param array $usernames The usernames * @param array $user_ids The user identifiers * @param array $errors The errors * @return void * @access protected */ protected function get_ids_from_usernames(array $usernames, array &$user_ids, array &$errors) { $usernames_clean = []; $usernames_found = []; foreach ($usernames as $username) { $usernames_clean[$username] = utf8_clean_string($username); } $sql = 'SELECT user_id, username_clean FROM ' . $this->users_table . ' WHERE ' . $this->db->sql_in_set('username_clean', $usernames_clean); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $usernames_found[] = $row['username_clean']; $user_ids[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); $usernames_not_found = array_diff($usernames_clean, $usernames_found); if (!empty($usernames_not_found)) { $errors[] = count($usernames_not_found) > 1 ? 'NO_USERS' : 'NO_USER'; $not_found = array_intersect($usernames_clean, $usernames_not_found); $not_found = array_flip($not_found); foreach ($not_found as $username) { $errors[] = '» ' . $username; } } } /** * Get user identifiers from group identifiers. * * @param array $group_ids The group identifiers * @param array $user_ids The user identifiers * @return void * @access protected */ protected function get_ids_from_groups(array $group_ids, array &$user_ids) { $sql = 'SELECT user_id FROM ' . $this->user_group_table . ' WHERE user_pending <> 1 AND ' . $this->db->sql_in_set('group_id', $group_ids); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { $user_ids[] = (int) $row['user_id']; } $this->db->sql_freeresult($result); } /** * Get a username from user identifier. * * @param int $user_id The user identifier * @return string The username * @access protected */ protected function get_username($user_id) { $sql = 'SELECT username FROM ' . $this->users_table . ' WHERE user_id = ' . (int) $user_id; $result = $this->db->sql_query_limit($sql, 1); $username = $this->db->sql_fetchfield('username'); $this->db->sql_freeresult($result); return (string) $username; } /** * Set custom form action. * * @param string $u_action Custom form action * @return self $this This controller for chaining calls * @access public */ public function set_page_url($u_action) { $this->u_action = $u_action; return $this; } }