templates = $templates; } /** * Registers the hooks. */ public function register_hooks() { add_action( 'add_meta_boxes_' . Post_Types::FORM, array( $this, 'add_box' ) ); add_action( 'save_post_' . Post_Types::FORM, array( $this, 'save' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); add_action( 'admin_post_' . self::POLICY_ACTION, array( $this, 'add_policy_paragraph' ) ); add_action( 'admin_post_' . self::POLICY_COVERED_ACTION, array( $this, 'policy_covered' ) ); } /** * Helps the business with the privacy policy of the site. The form * already tells visitors how their request is handled, under the consent * box: this only offers to add the same information to the privacy * policy page, in one click, never on its own. * * @param int $form_id Form post ID. */ private function privacy_notice( $form_id ) { if ( ! current_user_can( 'manage_privacy_options' ) ) { return; } $page = self::policy_page(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only flag set by add_policy_paragraph() after its own nonce check. if ( $page && isset( $_GET['primiko_policy'] ) && 'added' === $_GET['primiko_policy'] ) { ?>
ID || ! current_user_can( 'edit_post', $page->ID ) ) { return; } $url = wp_nonce_url( add_query_arg( array( 'action' => self::POLICY_ACTION, 'form' => $form_id, ), admin_url( 'admin-post.php' ) ), self::POLICY_ACTION ); $covered = wp_nonce_url( add_query_arg( array( 'action' => self::POLICY_COVERED_ACTION, 'form' => $form_id, ), admin_url( 'admin-post.php' ) ), self::POLICY_COVERED_ACTION ); ?> post_type && 'trash' !== $page->post_status ? $page : null; } /** * Tells whether the privacy policy page still holds the added paragraph. * * @param \WP_Post $page Privacy policy page. * @return bool */ private static function has_policy_paragraph( $page ) { return false !== strpos( $page->post_content, self::POLICY_CLASS ); } /** * Adds the paragraph about quote requests at the end of the privacy * policy page, when the business clicks the button, once. */ public function add_policy_paragraph() { check_admin_referer( self::POLICY_ACTION ); $form_id = isset( $_GET['form'] ) ? absint( $_GET['form'] ) : 0; $page = self::policy_page(); if ( ! $page || ! current_user_can( 'manage_privacy_options' ) || ! current_user_can( 'edit_post', $page->ID ) ) { wp_die( esc_html__( 'You are not allowed to change the privacy policy page.', 'primiko' ), 403 ); } if ( ! self::has_policy_paragraph( $page ) ) { $blocks = '" . esc_html( $paragraph ) . '
'; } wp_update_post( array( 'ID' => $page->ID, 'post_content' => self::insert_paragraph( $page->post_content, $blocks ), ) ); } wp_safe_redirect( add_query_arg( 'primiko_policy', 'added', get_edit_post_link( $form_id, 'url' ) ) ); exit; } /** * Places the paragraph at the end of the page, but before a closing line * such as "This page was updated in October 2026.": a short last * paragraph with a year in it. * * @param string $content Content of the privacy policy page. * @param string $blocks Block markup to add. * @return string */ private static function insert_paragraph( $content, $blocks ) { $parsed = parse_blocks( $content ); $last = null; foreach ( $parsed as $index => $block ) { if ( null !== $block['blockName'] || '' !== trim( $block['innerHTML'] ) ) { $last = $index; } } if ( null !== $last && 'core/paragraph' === $parsed[ $last ]['blockName'] ) { $text = trim( wp_strip_all_tags( $parsed[ $last ]['innerHTML'] ) ); if ( strlen( $text ) < 160 && preg_match( '/\b(19|20)\d{2}\b/', $text ) ) { array_splice( $parsed, $last, 0, parse_blocks( $blocks . "\n\n" ) ); return serialize_blocks( $parsed ); } } return rtrim( $content ) . "\n\n" . $blocks; } /** * Remembers that the privacy policy page already covers quote requests, * when the business says so: the offer is not shown again for this page. */ public function policy_covered() { check_admin_referer( self::POLICY_COVERED_ACTION ); $form_id = isset( $_GET['form'] ) ? absint( $_GET['form'] ) : 0; $page = self::policy_page(); if ( ! current_user_can( 'manage_privacy_options' ) ) { wp_die( esc_html__( 'You are not allowed to change the privacy policy page.', 'primiko' ), 403 ); } if ( $page ) { update_option( self::POLICY_COVERED_OPTION, $page->ID, false ); } wp_safe_redirect( get_edit_post_link( $form_id, 'url' ) ); exit; } /** * Adds the settings box. */ public function add_box() { add_meta_box( 'primiko-form-settings', __( 'Form settings', 'primiko' ), array( $this, 'render' ), Post_Types::FORM, 'normal', 'high' ); add_meta_box( 'primiko-questions', __( 'Questions and messages', 'primiko' ), array( $this, 'render_questions' ), Post_Types::FORM, 'normal', 'default' ); } /** * Loads the questions editor on the form screens. * * @param string $hook Admin page. */ public function enqueue( $hook ) { $screen = get_current_screen(); $asset = PRIMIKO_DIR . 'build/admin/index.asset.php'; if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) || ! $screen || Post_Types::FORM !== $screen->post_type || ! is_readable( $asset ) ) { return; } $asset = require $asset; wp_enqueue_script( 'primiko-admin', PRIMIKO_URL . 'build/admin/index.js', $asset['dependencies'], $asset['version'], true ); wp_set_script_translations( 'primiko-admin', 'primiko', PRIMIKO_DIR . 'languages' ); wp_enqueue_style( 'wp-components' ); if ( is_readable( PRIMIKO_DIR . 'build/admin/style-index.css' ) ) { wp_enqueue_style( 'primiko-admin', PRIMIKO_URL . 'build/admin/style-index.css', array( 'wp-components' ), $asset['version'] ); } } /** * Prints the mount point of the questions editor, with what it needs: * every template, translated, and the customizations already saved. * The editor writes its result in a hidden field saved with the form. * * @param \WP_Post $post Form post. */ public function render_questions( $post ) { $templates = array(); foreach ( array_keys( $this->templates->choices() ) as $id ) { $template = $this->templates->localized( $id ); foreach ( Customizations::MESSAGES as $key ) { if ( empty( $template['messages'][ $key ] ) ) { $template['messages'][ $key ] = Mailer::default_message( $key ); } } $templates[ $id ] = $template; } $saved = get_post_meta( $post->ID, Customizations::META, true ); $config = array( 'templates' => $templates, 'customizations' => is_array( $saved ) ? $saved : array(), ); ?>| ID ); ?> | |
[ form="ID ); ?>"]
|