'wp_block', 'post_status' => 'publish', 'posts_per_page' => 200, 'orderby' => 'title', 'order' => 'ASC', 's' => 'wp:alpeg-forms/form', ) ); $out = array(); foreach ( $posts as $post ) { foreach ( parse_blocks( $post->post_content ) as $block ) { if ( 'alpeg-forms/form' === $block['blockName'] ) { $out[] = array( 'id' => (int) $post->ID, 'title' => $post->post_title, 'attributes' => (array) $block['attrs'], ); break; } } } return $out; } /** * Download the selected templates as a JSON file (admin-post). */ public static function export() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'alpeg-forms' ), 403 ); } check_admin_referer( 'alpeg_forms_template_export' ); $wanted = isset( $_POST['af_templates'] ) ? array_map( 'absint', (array) wp_unslash( $_POST['af_templates'] ) ) : array(); $items = array(); foreach ( self::templates() as $t ) { if ( in_array( $t['id'], $wanted, true ) ) { $attrs = $t['attributes']; // A new form ID is created on the target site; recipients belong to this website only. unset( $attrs['formId'], $attrs['notifyEmail'] ); $items[] = array( 'title' => $t['title'], 'attributes' => $attrs, ); } } if ( ! $items ) { wp_safe_redirect( admin_url( 'admin.php?page=alpeg-forms-import#templates' ) ); exit; } $json = wp_json_encode( array( 'format' => self::FORMAT, 'version' => 1, 'plugin' => ALPEG_FORMS_VERSION, 'exported' => gmdate( 'c' ), 'templates' => $items, ), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ); nocache_headers(); header( 'Content-Type: application/json; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="alpeg-forms-templates-' . gmdate( 'Y-m-d' ) . '.json"' ); header( 'X-Content-Type-Options: nosniff' ); echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON file download. exit; } /** * Import templates from an uploaded JSON file (admin-post). */ public static function import() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You are not allowed to do this.', 'alpeg-forms' ), 403 ); } check_admin_referer( 'alpeg_forms_template_import' ); $result = self::import_file( isset( $_FILES['af_template_file'] ) ? $_FILES['af_template_file'] : array() ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- Validated in import_file(). set_transient( 'alpeg_forms_template_notice_' . get_current_user_id(), $result, 60 ); wp_safe_redirect( admin_url( 'admin.php?page=alpeg-forms-import#templates' ) ); exit; } /** * Read and validate an uploaded file. * * @param array $file Entry from $_FILES. * @return array done (titles), error (message). */ public static function import_file( $file ) { $fail = static function ( $msg ) { return array( 'done' => array(), 'error' => $msg, ); }; if ( empty( $file['tmp_name'] ) || ! empty( $file['error'] ) || ! is_uploaded_file( $file['tmp_name'] ) ) { return $fail( __( 'Please choose a template file.', 'alpeg-forms' ) ); } if ( (int) $file['size'] > self::MAX_BYTES ) { return $fail( __( 'The file is too large for a template file.', 'alpeg-forms' ) ); } $data = json_decode( (string) file_get_contents( $file['tmp_name'] ), true ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local temporary upload. return self::import_data( $data ); } /** * Create templates from decoded file data. * * @param mixed $data Decoded JSON. * @return array done (titles), error (message). */ public static function import_data( $data ) { if ( ! is_array( $data ) || ! isset( $data['format'] ) || self::FORMAT !== $data['format'] || empty( $data['templates'] ) || ! is_array( $data['templates'] ) ) { return array( 'done' => array(), 'error' => __( 'This is not an ALPEG Forms template file.', 'alpeg-forms' ), ); } $done = array(); foreach ( array_slice( $data['templates'], 0, 50 ) as $t ) { if ( ! is_array( $t ) || empty( $t['attributes'] ) || ! is_array( $t['attributes'] ) ) { continue; } $attrs = self::clean_attributes( $t['attributes'] ); if ( ! $attrs['fields'] ) { continue; } $title = sanitize_text_field( isset( $t['title'] ) && is_scalar( $t['title'] ) ? $t['title'] : '' ); $title = '' !== $title ? $title : __( 'Imported form', 'alpeg-forms' ); $id = wp_insert_post( array( 'post_type' => 'wp_block', 'post_status' => 'publish', 'post_title' => $title, 'post_content' => wp_slash( '' ), ), true ); if ( ! is_wp_error( $id ) ) { update_post_meta( $id, 'wp_pattern_sync_status', 'unsynced' ); $done[] = $title; } } return array( 'done' => $done, 'error' => $done ? '' : __( 'The file does not contain any usable form.', 'alpeg-forms' ), ); } /** * Only known block attributes, each validated. * * @param array $in Attributes from the file. * @return array */ private static function clean_attributes( array $in ) { $out = array( 'fields' => Fields::normalize( isset( $in['fields'] ) && is_array( $in['fields'] ) ? $in['fields'] : array() ) ); $texts = array( 'formTitle', 'submitLabel', 'notifySubject', 'confirmationSubject', 'firstStepTitle' ); $areas = array( 'successMessage', 'confirmationMessage' ); $bools = array( 'sendConfirmation', 'attachFiles' ); foreach ( $texts as $k ) { if ( isset( $in[ $k ] ) && is_scalar( $in[ $k ] ) ) { $out[ $k ] = sanitize_text_field( (string) $in[ $k ] ); } } foreach ( $areas as $k ) { if ( isset( $in[ $k ] ) && is_scalar( $in[ $k ] ) ) { $out[ $k ] = sanitize_textarea_field( (string) $in[ $k ] ); } } foreach ( $bools as $k ) { if ( isset( $in[ $k ] ) ) { $out[ $k ] = (bool) $in[ $k ]; } } if ( isset( $in['accentColor'] ) && is_string( $in['accentColor'] ) && sanitize_hex_color( $in['accentColor'] ) ) { $out['accentColor'] = sanitize_hex_color( $in['accentColor'] ); } // The recipient address is deliberately not taken over: it belongs to the source website. return $out; } /** * Section on the import page. */ public static function render() { $notice = get_transient( 'alpeg_forms_template_notice_' . get_current_user_id() ); delete_transient( 'alpeg_forms_template_notice_' . get_current_user_id() ); $templates = self::templates(); ?>