, * comments_mode: 'open'|'logged_in'|'closed', * voting_access: 'anyone'|'logged_in', * landing_mode: string * } */ public function all(): array { $raw = get_option( self::OPTION_NAME, [] ); $settings = is_array( $raw ) ? $raw : []; return [ 'modules' => $this->parse_modules( $settings['modules'] ?? [] ), 'submission_access' => $this->parse_access( $settings['submission_access'] ?? self::ACCESS_ANYONE ), 'submission_moderation' => ! empty( $settings['submission_moderation'] ), 'allowed_types' => $this->parse_allowed_types( $settings['allowed_types'] ?? null ), 'comments_mode' => $this->parse_comments_mode( $settings['comments_mode'] ?? self::COMMENTS_OPEN ), 'voting_access' => $this->parse_access( $settings['voting_access'] ?? self::ACCESS_ANYONE ), 'landing_mode' => $this->parse_landing_mode( $settings['landing_mode'] ?? PortalPages::PORTAL ), ]; } public function is_module_active( string $module ): bool { $modules = $this->all()['modules']; return $modules[ $module ] ?? true; } /** * @return array{feedback: bool, roadmap: bool, changelog: bool} */ public function active_modules(): array { return $this->all()['modules']; } public function can_submit(): bool { if ( ! $this->is_module_active( self::MODULE_FEEDBACK ) ) { return false; } if ( $this->all()['submission_access'] === self::ACCESS_LOGGED_IN ) { return is_user_logged_in(); } return true; } public function can_vote(): bool { if ( ! $this->is_module_active( self::MODULE_FEEDBACK ) ) { return false; } if ( $this->all()['voting_access'] === self::ACCESS_LOGGED_IN ) { return is_user_logged_in(); } return true; } public function can_comment(): bool { if ( ! $this->is_module_active( self::MODULE_FEEDBACK ) ) { return false; } $mode = $this->all()['comments_mode']; if ( $mode === self::COMMENTS_CLOSED ) { return false; } if ( $mode === self::COMMENTS_LOGGED_IN ) { return is_user_logged_in(); } return true; } public function are_comments_closed(): bool { return ! $this->is_module_active( self::MODULE_FEEDBACK ) || $this->all()['comments_mode'] === self::COMMENTS_CLOSED; } public function requires_moderation(): bool { return $this->all()['submission_moderation']; } /** * @return list */ public function allowed_types(): array { return $this->all()['allowed_types']; } public function is_type_allowed( string $type ): bool { return in_array( $type, $this->allowed_types(), true ); } public function landing_mode(): string { return $this->all()['landing_mode']; } /** * @param mixed $raw * @return array{feedback: bool, roadmap: bool, changelog: bool} */ private function parse_modules( mixed $raw ): array { $modules = is_array( $raw ) ? $raw : []; $feedback = ! isset( $modules[ self::MODULE_FEEDBACK ] ) || ! empty( $modules[ self::MODULE_FEEDBACK ] ); $roadmap = ! isset( $modules[ self::MODULE_ROADMAP ] ) || ! empty( $modules[ self::MODULE_ROADMAP ] ); $changelog = ! isset( $modules[ self::MODULE_CHANGELOG ] ) || ! empty( $modules[ self::MODULE_CHANGELOG ] ); // Fallback: at least one module must always remain active. if ( ! $feedback && ! $roadmap && ! $changelog ) { $feedback = true; } return [ self::MODULE_FEEDBACK => $feedback, self::MODULE_ROADMAP => $roadmap, self::MODULE_CHANGELOG => $changelog, ]; } /** * @param mixed $raw * @return 'anyone'|'logged_in' */ private function parse_access( mixed $raw ): string { return $raw === self::ACCESS_LOGGED_IN ? self::ACCESS_LOGGED_IN : self::ACCESS_ANYONE; } /** * @param mixed $raw * @return 'open'|'logged_in'|'closed' */ private function parse_comments_mode( mixed $raw ): string { return match ( $raw ) { self::COMMENTS_LOGGED_IN => self::COMMENTS_LOGGED_IN, self::COMMENTS_CLOSED => self::COMMENTS_CLOSED, default => self::COMMENTS_OPEN, }; } /** * @param mixed $raw * @return list */ private function parse_allowed_types( mixed $raw ): array { if ( is_array( $raw ) && $raw !== [] ) { $sanitized = []; foreach ( $raw as $type ) { if ( is_string( $type ) && $type !== '' ) { $sanitized[] = sanitize_title( $type ); } } if ( $sanitized !== [] ) { return array_values( array_unique( $sanitized ) ); } } // Default to all existing request types or the standard enum values. if ( taxonomy_exists( Identifiers::TAXONOMY_REQUEST_TYPE ) ) { $terms = get_terms( [ 'taxonomy' => Identifiers::TAXONOMY_REQUEST_TYPE, 'hide_empty' => false, 'fields' => 'slugs', ] ); if ( ! is_wp_error( $terms ) && is_array( $terms ) && $terms !== [] ) { /** @var list $terms */ return array_values( array_map( 'strval', $terms ) ); } } return RequestType::values(); } private function parse_landing_mode( mixed $raw ): string { $mode = is_string( $raw ) ? sanitize_key( $raw ) : PortalPages::PORTAL; $allowed = [ PortalPages::PORTAL, PortalPages::FEEDBACK, PortalPages::ROADMAP, PortalPages::CHANGELOG ]; return in_array( $mode, $allowed, true ) ? $mode : PortalPages::PORTAL; } }