policy = $policy; } /** * Discover currently stored Contact Form 7 forms. * * @return FormModel[] */ public function discover() { if ( ! class_exists( 'WPCF7_ContactForm' ) || ! is_callable( array( 'WPCF7_ContactForm', 'find' ) ) ) { return array(); } $forms = \WPCF7_ContactForm::find(); if ( ! is_array( $forms ) ) { return array(); } $models = array(); foreach ( $forms as $form ) { if ( is_object( $form ) ) { $models[] = $this->normalize( $form ); } } return $models; } /** * Normalize one WPCF7_ContactForm object. * * @param object $contact_form Contact Form 7 form. * @return FormModel */ public function normalize( $contact_form ) { $id = is_callable( array( $contact_form, 'id' ) ) ? absint( $contact_form->id() ) : 0; $title = is_callable( array( $contact_form, 'title' ) ) ? (string) $contact_form->title() : ''; $tags = is_callable( array( $contact_form, 'scan_form_tags' ) ) ? $contact_form->scan_form_tags() : false; if ( ! is_array( $tags ) ) { return new FormModel( $id, $title, 'cf7', array(), array(), 'Contact Form 7 did not provide a readable tag list.' ); } $fields = array(); $blocked_fields = array(); $seen_names = array(); foreach ( $tags as $tag ) { if ( ! is_object( $tag ) ) { $blocked_fields[] = $this->blocked_record( '', 'unknown', 'Malformed provider control.' ); continue; } $type = isset( $tag->basetype ) && is_string( $tag->basetype ) && '' !== $tag->basetype ? $tag->basetype : ( isset( $tag->type ) ? (string) $tag->type : '' ); $type = strtolower( preg_replace( '/\*$/', '', $type ) ); $name = isset( $tag->name ) ? (string) $tag->name : ''; if ( $this->is_submit_control( $type ) ) { continue; } $normalized = array( 'name' => $name, 'type' => $type, 'label' => $this->tag_label( $tag, $name ), 'required' => $this->is_required( $tag ), 'options' => $this->tag_options( $tag ), 'provider_type' => isset( $tag->type ) ? (string) $tag->type : $type, ); if ( 'select' === $type && $this->has_option( $tag, 'multiple' ) ) { $blocked_fields[] = $this->blocked_record( $name, $type, 'Multiple select controls are not supported.' ); continue; } $decision = $this->policy->evaluate( $normalized ); if ( ! empty( $decision['allowed'] ) && isset( $decision['field'] ) && $decision['field'] instanceof Field ) { $field = $decision['field']; if ( isset( $seen_names[ $field->name() ] ) ) { $blocked_fields[] = $this->blocked_record( $field->name(), $type, 'Duplicate field names are not supported.' ); continue; } $seen_names[ $field->name() ] = true; $fields[] = $field; } elseif ( isset( $decision['blocked'] ) && is_array( $decision['blocked'] ) ) { $blocked_fields[] = $decision['blocked']; } else { $blocked_fields[] = $this->blocked_record( $name, $type, 'Policy evaluation failed closed.' ); } } usort( $fields, static function ( Field $left, Field $right ) { return strcmp( $left->name(), $right->name() ); } ); $reason = ''; if ( ! empty( $blocked_fields ) ) { $reason = 'One or more Contact Form 7 controls are unsupported or policy-blocked.'; } elseif ( empty( $fields ) ) { $reason = 'No supported human-visible user fields were found.'; } return new FormModel( $id, $title, 'cf7', $fields, $blocked_fields, $reason ); } /** * Perform the documented operation. * * @param object $tag CF7 form tag. * @param string $fallback Fallback label. * @return string */ private function tag_label( $tag, $fallback ) { foreach ( array( 'label', 'labels' ) as $property ) { if ( isset( $tag->{$property} ) && is_string( $tag->{$property} ) && '' !== trim( $tag->{$property} ) ) { return trim( $tag->{$property} ); } } return '' !== $fallback ? $fallback : 'Form field'; } /** * Perform the documented operation. * * @param object $tag CF7 form tag. * @return bool */ private function is_required( $tag ) { $type = isset( $tag->type ) ? (string) $tag->type : ''; return 0 < strlen( $type ) && '*' === substr( $type, -1 ); } /** * Perform the documented operation. * * @param object $tag CF7 form tag. * @return string[] */ private function tag_options( $tag ) { $values = isset( $tag->values ) && is_array( $tag->values ) ? $tag->values : array(); $options = array(); foreach ( $values as $value ) { if ( is_scalar( $value ) && '' !== (string) $value ) { $options[] = (string) $value; } } return array_values( array_unique( $options ) ); } /** * Perform the documented operation. * * @param object $tag CF7 form tag. * @param string $option Option name. * @return bool */ private function has_option( $tag, $option ) { return isset( $tag->options ) && is_array( $tag->options ) && in_array( $option, $tag->options, true ); } /** * Perform the documented operation. * * @param string $type CF7 base type. * @return bool */ private function is_submit_control( $type ) { return in_array( $type, array( 'submit', 'button', 'image' ), true ); } /** * Perform the documented operation. * * @param string $name Field name. * @param string $type Provider type. * @param string $reason Block reason. * @return array */ private function blocked_record( $name, $type, $reason ) { return array( 'name' => (string) $name, 'provider_type' => (string) $type, 'reason' => (string) $reason, ); } }