Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
UpdateCompanyProjectRequest
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 authorize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prepareForValidation
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 rules
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3namespace App\Http\Requests\CompanyRolePlay;
4
5use App\Http\Models\RolePlayProjects;
6use App\Http\Services\RolePlay\ObjectionNormalizer;
7use Illuminate\Foundation\Http\FormRequest;
8use Illuminate\Validation\Rule;
9
10/**
11 * Request validation for updating an existing company roleplay project.
12 *
13 * All fields are optional for partial updates.
14 *
15 * @property string|null $name The project name (max 255 chars)
16 * @property string|null $type The call type ('cold-call' or 'discovery-call')
17 * @property string|null $description Optional project description
18 * @property string|null $industry The target industry
19 * @property array<string>|null $target_job_titles Array of targeted job titles
20 * @property array<string>|null $key_features Array of key product/service features
21 * @property string|null $product_description Optional product description
22 * @property int|null $difficulty_level Difficulty level (1-5)
23 * @property array|null $customer_profiles Array of customer profile objects
24 * @property array|null $scorecard_config Array of scorecard config objects
25 * @property array|null $objections Array of objection objects
26 * @property bool|null $allow_user_customization Whether users can customize when cloning
27 * @property array<string>|null $assigned_groups Array of group IDs (empty means all users)
28 * @property string|null $status Project status ('active', 'inactive', 'archived')
29 */
30class UpdateCompanyProjectRequest extends FormRequest
31{
32    /**
33     * Determine if the user is authorized to make this request.
34     *
35     * Authorization is handled in the controller by checking company_id.
36     */
37    public function authorize(): bool
38    {
39        return true;
40    }
41
42    /**
43     * Normalize legacy-shape `objections` payloads into the canonical
44     * {text, company_sizes} shape BEFORE validation rules fire.
45     */
46    protected function prepareForValidation(): void
47    {
48        if ($this->has('objections')) {
49            $this->merge([
50                'objections' => ObjectionNormalizer::normalize($this->input('objections')),
51            ]);
52        }
53    }
54
55    /**
56     * Get the validation rules that apply to the request.
57     *
58     * Makes all base rules optional by prepending 'sometimes' to required rules.
59     *
60     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
61     */
62    public function rules(): array
63    {
64        $baseRules = RolePlayProjects::getRules();
65
66        // Make all rules optional for partial updates
67        $rules = [];
68        foreach ($baseRules as $key => $rule) {
69            if (is_string($rule)) {
70                $rule = str_replace('required|', 'sometimes|', $rule);
71                $rule = str_replace('required', 'sometimes', $rule);
72            } elseif (is_array($rule)) {
73                $rule = array_map(function ($r) {
74                    return $r === 'required' ? 'sometimes' : $r;
75                }, $rule);
76            }
77            $rules[$key] = $rule;
78        }
79
80        return array_merge($rules, [
81            'product_description' => 'nullable|string',
82            'allow_user_customization' => 'sometimes|boolean',
83            'allow_clone' => 'sometimes|boolean',
84            'allow_direct_calls' => 'sometimes|boolean',
85            'assigned_groups' => 'sometimes|array',
86            'assigned_groups.*' => 'string',
87            'assigned_users' => 'sometimes|array',
88            'assigned_users.*' => 'string',
89            'status' => ['sometimes', 'string', Rule::in(['active', 'inactive', 'archived'])],
90        ]);
91    }
92}