has('type') && ! $this->has('views')) { $this->merge(['views' => [$this->only(['type', 'slug', 'locale', 'count'])]]); } } /** * @return array */ public function rules(): array { return [ 'views' => ['required', 'array', 'min:1', 'max:'.$this->maxBatch()], 'views.*.type' => ['required', 'string', Rule::in(ContentTypes::keys())], 'views.*.slug' => ['required', 'string', 'max:200'], 'views.*.locale' => [ 'sometimes', 'nullable', 'string', Rule::in(array_keys((array) config('locales.supported'))), ], /* * Optional, because the obvious client sends one report per page * view. Capped because the frontend is trusted to count its own * renders and not to invent an audience: a number nobody can * check is a number worth bounding. */ 'views.*.count' => ['sometimes', 'integer', 'min:1', 'max:1000'], ]; } /** * @return array> */ public function views(): array { return array_values((array) $this->validated('views')); } public function maxBatch(): int { return max(1, (int) config('site.telemetry.max_batch', 50)); } }