| @@ -18,13 +18,8 @@ | ||
| 18 | 18 | */ |
| 19 | 19 | class CustomerController extends Controller |
| 20 | 20 | { |
| 21 | 21 | /** |
| 22 | - * Maximum number of customers accepted by a single bulk-delete request. | |
| 23 | - */ | |
| 24 | - const BULK_DELETE_LIMIT = 100; | |
| 25 | - | |
| 26 | - /** | |
| 27 | 22 | * index method will return the list of customers |
| 28 | 23 | * @param Request $request |
| 29 | 24 | * @param Customer $customer |
| 30 | 25 | * @return array |
| @@ -227,14 +222,10 @@ | ||
| 227 | 222 | $customerIds = array_filter($customerIds, function ($id) { |
| 228 | 223 | return $id > 0; |
| 229 | 224 | }); |
| 230 | 225 | |
| 231 | - $customerIds = array_values(array_unique($customerIds)); | |
| 232 | - | |
| 233 | - // Each id fans out into a full cascade delete (tickets, conversations, | |
| 234 | - // attachments), so an unbounded batch means an unbounded request. | |
| 235 | 226 | $this->validate(['customer_ids' => $customerIds], [ |
| 236 | - 'customer_ids' => 'required|array|min:1|max:' . self::BULK_DELETE_LIMIT, | |
| 227 | + 'customer_ids' => 'required|array|min:1', | |
| 237 | 228 | 'customer_ids.*' => 'required|integer|exists:fs_persons,id' |
| 238 | 229 | ]); |
| 239 | 230 | |
| 240 | 231 | return $customer->bulkDeleteCustomers($customerIds); |
| @@ -261,19 +252,15 @@ | ||
| 261 | 252 | |
| 262 | 253 | /** |
| 263 | 254 | * resetAvatar method will restore a customer avatar |
| 264 | 255 | * For a successful upload it's required to send file object, customer id and the user type(customer) |
| 265 | - * | |
| 266 | - * No Customer type-hint here: route-model binding resolves inside the | |
| 267 | - * permission callback, before any policy runs, which lets unauthenticated | |
| 268 | - * callers probe customer ID existence (FS-PERM-001). Resolve after auth. | |
| 269 | - * @param int|string $customer | |
| 256 | + * @param Request $request | |
| 257 | + * @param $id | |
| 270 | 258 | * @return array |
| 271 | 259 | */ |
| 272 | - public function resetAvatar($customer) | |
| 260 | + public function resetAvatar(Customer $customer) | |
| 273 | 261 | { |
| 274 | 262 | try { |
| 275 | - $customer = Customer::findOrFail((int) $customer); | |
| 276 | 263 | $customer->restoreAvatar(); |
| 277 | 264 | |
| 278 | 265 | return [ |
| 279 | 266 | 'message' => __('Customer avatar reset to gravatar default', 'fluent-support'), |
| @@ -286,15 +273,9 @@ | ||
| 286 | 273 | } |
| 287 | 274 | |
| 288 | 275 | public function searchContact(Request $request) |
| 289 | 276 | { |
| 290 | - $search = trim($request->getSafe('search', 'sanitize_text_field')); | |
| 291 | - | |
| 292 | - // '*' is a WP_User_Query wildcard and survives sanitize_text_field, so a | |
| 293 | - // lone '*' would list every user on the site. Stripping it leaves | |
| 294 | - // WP_User_Query doing an exact match. | |
| 295 | - $search = trim(str_replace('*', '', $search)); | |
| 296 | - | |
| 277 | + $search = $request->getSafe('search', 'sanitize_text_field'); | |
| 297 | 278 | if (!$search) { |
| 298 | 279 | return $this->sendError([ |
| 299 | 280 | 'message' => __('Please provide search string', 'fluent-support') |
| 300 | 281 | ]); |
| @@ -301,27 +282,8 @@ | ||
| 301 | 282 | } |
| 302 | 283 | |
| 303 | 284 | $isEmail = is_email($search); |
| 304 | 285 | |
| 305 | - // Require a meaningful prefix so the endpoint can't be walked one letter | |
| 306 | - // at a time. Emails are matched exactly, so they need no minimum. | |
| 307 | - if (!$isEmail && mb_strlen($search) < 3) { | |
| 308 | - return $this->sendError([ | |
| 309 | - 'message' => __('Please provide at least 3 characters to search', 'fluent-support') | |
| 310 | - ]); | |
| 311 | - } | |
| 312 | - | |
| 313 | - if (Helper::hitRateLimit('fs_contact_search_' . get_current_user_id(), 60, 5 * MINUTE_IN_SECONDS)) { | |
| 314 | - return $this->sendError([ | |
| 315 | - 'message' => __('Too many contact searches. Please try again in a few minutes.', 'fluent-support') | |
| 316 | - ], 429); | |
| 317 | - } | |
| 318 | - | |
| 319 | - // '%' and '_' are LIKE wildcards for the customer and CRM scopes below. | |
| 320 | - // Escape rather than strip: underscores are legitimate in emails. | |
| 321 | - global $wpdb; | |
| 322 | - $likeSearch = $wpdb->esc_like($search); | |
| 323 | - | |
| 324 | 286 | // search the existing customers first |
| 325 | 287 | if ($isEmail) { |
| 326 | 288 | $customers = Customer::select(['first_name', 'last_name', 'email', 'id', 'user_id']) |
| 327 | 289 | ->where('email', $search) |
| @@ -327,9 +289,9 @@ | ||
| 327 | 289 | ->where('email', $search) |
| 328 | 290 | ->get(); |
| 329 | 291 | } else { |
| 330 | 292 | $customers = Customer::select(['first_name', 'last_name', 'email', 'id', 'user_id']) |
| 331 | - ->searchBy($likeSearch) | |
| 293 | + ->searchBy($search) | |
| 332 | 294 | ->limit(10) |
| 333 | 295 | ->get(); |
| 334 | 296 | } |
| 335 | 297 | |
| @@ -351,9 +313,9 @@ | ||
| 351 | 313 | ->select(['first_name', 'last_name', 'email', 'id', 'user_id']) |
| 352 | 314 | ->get(); |
| 353 | 315 | } else { |
| 354 | 316 | |
| 355 | - $contacts = \FluentCrm\App\Models\Subscriber::searchBy($likeSearch) | |
| 317 | + $contacts = \FluentCrm\App\Models\Subscriber::searchBy($search) | |
| 356 | 318 | ->select(['first_name', 'last_name', 'email', 'id', 'user_id']) |
| 357 | 319 | ->limit(10) |
| 358 | 320 | ->get(); |
| 359 | 321 | } |