json->steps, function ( $acc, $step ) use ( $multi_value_fields ) { return array_merge( $acc, array_reduce( $step->fields, function ( $acc, $field ) use ( $multi_value_fields ) { if ( in_array( $field->component, $multi_value_fields, true ) ) { $acc[ $field->id ] = [ 'label' => $field->label ?? $field->placeholder, 'options' => array_fill_keys( array_map( function ( $o ) { return $o['label'] ?? $o; }, (array) ( $field->options ?? [] ) ), 0 ), ]; } return $acc; }, [] ) ); }, [] ); /* If statistics record doesn't exist for this form - create it */ if ( empty( $this->json ) ) { $this->json = [ 'submissions' => array_fill( 0, 24, 0 ), 'fields' => $multi, ]; } else { /* * If there are any new multi choice fields in the form or * fields got new options - we add those into aggregated * statistics records */ foreach ( $multi as $key => $data ) { if ( ! isset( $this->json['fields'][ $key ] ) ) { $this->json['fields'][ $key ] = $data; } foreach ( $data['options'] as $option => $value ) { if ( ! isset( $this->json['fields'][ $key ]['options'][ $option ] ) ) { $this->json['fields'][ $key ]['options'][ $option ] = 0; } } } } $submission_fields = array_keys( $submission->json ); $submission->json = array_reduce( $submission_fields, function ( $acc, $key ) use ( $submission, $multi ) { // We are only interested in multi value fields. if ( isset( $multi[ $key ] ) ) { if ( is_array( $submission->json[ $key ] ) ) { $val = array_map( function ( $value ) { return $value['label'] ?? $value; }, $submission->json[ $key ] ); } else { $val = [ $submission->json[ $key ] ]; } $acc[ $key ] = $val; } return $acc; }, [] ); $hour = ( new DateTimeImmutable( 'now', new DateTimeZone( 'UTC' ) ) )->format( 'H' ); $this->json['submissions'][ intval( $hour ) ] += 1; foreach ( $submission->json as $field => $value ) { // Defence in depth: guard against the reserved upload-locator // sidecar (Epicformbuilder_Services_Submission_Merge::META_KEY). // Currently unreachable because the loop above filters // submission->json down to declared multi-choice fields before // this iteration, so the sidecar never appears here. if ( Epicformbuilder_Services_Submission_Merge::META_KEY === $field ) { continue; } /* * An array is either a list of chosen options or, for some * add-on components, a single item object carrying a label. */ if ( is_array( $value ) ) { if ( isset( $value['label'] ) ) { $this->increment( $multi, $field, $value['label'] ); } else { foreach ( $value as $v ) { $this->increment( $multi, $field, $v ); } } } else { $this->increment( $multi, $field, $value ); } } return $this; } /** * Increment statistics on multi fields values. * * @param array $multi Multi fields. * @param string $field Field ID. * @param string $value Field value. */ public function increment( $multi, $field, $value ) { if ( ! isset( $multi[ $field ]['options'][ $value ] ) ) { if ( ! isset( $this->json['fields'][ $field ]['options']['other_option'] ) ) { $this->json['fields'][ $field ]['options']['other_option'] = 0; } else { $this->json['fields'][ $field ]['options']['other_option'] += 1; } } else { $this->json['fields'][ $field ]['options'][ $value ] += 1; } } }