['required', 'string', 'sanitize:text', 'max:200'], // Optional here, as it already is on edit. The form decides when a // topic needs words: an empty editor posts markup of its own, so // requiring the field never kept a wordless topic out anyway. 'post_content' => ['nullable', 'string', 'max:' . PostingLimits::TOPIC_HTML_CEILING], // `sanitize:title` is WordPress' own `sanitize_title()`, so whatever // reaches the service is already a valid slug. Left blank, the // service derives one from the title the way core does. 'post_name' => ['nullable', 'string', 'sanitize:title', new LengthAtMostRule(200)], // Publish is the only status this endpoint creates: the allowlist // is a statement of what this plugin does rather than a gate on it. // Hiding a reported topic is moderation's, and goes through // ContentVisibilityService rather than this request. 'post_status' => ['nullable', 'string', new InRule(['publish'])], 'attachments' => ['nullable', 'array'], // Required when the admin made it so (Settings → Topic form), and // enforced here rather than only in the portal's form, which is // just one of the ways a topic gets created. 'topic-types' => [self::presence('topicType'), 'integer', 'min:1'], 'tags' => ['nullable', 'array', 'max:' . PostingLimits::TOPIC_TAGS_CEILING], // An id from the list, or a name the member typed — see TagResolverService. 'tags.*' => ['nullable', new TagRefRule()], ]; // One term each from a taxonomy another plugin files topics under, // required when that plugin says so — see TopicTaxonomies. foreach (TopicTaxonomies::all() as $param => $entry) { $rules[$param] = [$entry['required'] ? 'required' : 'nullable', 'integer', 'min:1', new AssignableTermRule($param)]; } return $rules; } public function messages() { $messages = [ 'post_title.required' => 'The post title is required.', 'post_title.max' => 'The post title cannot exceed 200 characters.', 'post_name.string' => 'The post slug must be a string.', 'post_name.max' => 'The post slug cannot exceed 200 characters.', 'post_content.max' => 'The post description is too long.', 'topic-type' => 'Each topic must be a valid ID.', 'topic-types.required' => 'Choose a topic.', 'tags.max' => \sprintf('A post may carry at most %d tags.', PostingLimits::TOPIC_TAGS_CEILING), 'tags.*.integer' => \sprintf('Each tag must be a tag from the list or a name of up to %d characters.', TagResolverService::MAX_NAME_LENGTH), ]; foreach (TopicTaxonomies::all() as $param => $entry) { $messages[$param . '.required'] = \sprintf('Choose a %s.', $entry['singular']); } return $messages; } /** * `required` or `nullable` for one of the form's optional fields, by the * mode the admin set for it. A hidden field is never asked, so it is as * free to leave out as an optional one. * * @param string $field `topicType` */ private static function presence(string $field): string { return TopicFormFields::isRequired($field) ? 'required' : 'nullable'; } }