Conversation
1711d07 to
2824829
Compare
…cumentate into improve-document-flow
| echo '<p>' . esc_html__('Insufficient permissions.', 'documentate') . '</p>'; | ||
| return; | ||
| } | ||
|
|
||
| $nonce_export = wp_create_nonce( 'documentate_export_' . $post->ID ); | ||
| $nonce_prev = wp_create_nonce( 'documentate_preview_' . $post->ID ); | ||
| $nonce_export = wp_create_nonce('documentate_export_' . $post->ID); | ||
| $nonce_prev = wp_create_nonce('documentate_preview_' . $post->ID); | ||
|
|
||
| $preview = $this->build_action_url( 'documentate_preview', $post->ID, $nonce_prev ); | ||
| $docx = $this->build_action_url( 'documentate_export_docx', $post->ID, $nonce_export ); | ||
| $pdf = $this->build_action_url( 'documentate_export_pdf', $post->ID, $nonce_export ); | ||
| $odt = $this->build_action_url( 'documentate_export_odt', $post->ID, $nonce_export ); | ||
| $preview = $this->build_action_url('documentate_preview', $post->ID, $nonce_prev); | ||
| $docx = $this->build_action_url('documentate_export_docx', $post->ID, $nonce_export); | ||
| $pdf = $this->build_action_url('documentate_export_pdf', $post->ID, $nonce_export); | ||
| $odt = $this->build_action_url('documentate_export_odt', $post->ID, $nonce_export); | ||
|
|
||
| $this->ensure_document_generator(); | ||
|
|
||
| $docx_template = Documentate_Document_Generator::get_template_path( $post->ID, 'docx' ); | ||
| $odt_template = Documentate_Document_Generator::get_template_path( $post->ID, 'odt' ); | ||
| $docx_template = Documentate_Document_Generator::get_template_path($post->ID, 'docx'); | ||
| $odt_template = Documentate_Document_Generator::get_template_path($post->ID, 'odt'); | ||
|
|
||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-conversion-manager.php'; | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-conversion-manager.php'; | ||
|
|
||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = ( '' === $docx_template && '' !== $odt_template ); | ||
| $odt_requires_conversion = ( '' === $odt_template && '' !== $docx_template ); | ||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = '' === $docx_template && '' !== $odt_template; | ||
| $odt_requires_conversion = '' === $odt_template && '' !== $docx_template; | ||
|
|
||
| // Check if ZetaJS CDN mode is available for browser-based preview. | ||
| $zetajs_cdn_available = false; | ||
| if ( ! $conversion_ready ) { | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-zetajs-converter.php'; | ||
| if (!$conversion_ready) { | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-zetajs-converter.php'; | ||
| $zetajs_cdn_available = Documentate_Zetajs_Converter::is_cdn_mode(); | ||
| } | ||
|
|
||
| // Check if we need popup-based conversion (bypasses PHP networking issues in Playground). | ||
| // This is needed for: | ||
| // 1. ZetaJS CDN mode (WASM conversion in browser) | ||
| // 2. Collabora in Playground (JavaScript fetch bypasses wp_remote_post multipart issues). | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = | ||
| Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| $use_popup_for_conversion = $zetajs_cdn_available || $collabora_in_playground; | ||
|
|
||
| // In CDN mode or Playground with Collabora, browser can do conversions too. | ||
| $can_convert = $conversion_ready || $use_popup_for_conversion; | ||
| $docx_available = ( '' !== $docx_template ) || ( $docx_requires_conversion && $can_convert ); | ||
| $odt_available = ( '' !== $odt_template ) || ( $odt_requires_conversion && $can_convert ); | ||
| $pdf_available = $can_convert && ( '' !== $docx_template || '' !== $odt_template ); | ||
| $docx_available = '' !== $docx_template || $docx_requires_conversion && $can_convert; | ||
| $odt_available = '' !== $odt_template || $odt_requires_conversion && $can_convert; | ||
| $pdf_available = $can_convert && ('' !== $docx_template || '' !== $odt_template); | ||
|
|
||
| // Determine source format for CDN conversions. | ||
| $source_format = '' !== $odt_template ? 'odt' : ( '' !== $docx_template ? 'docx' : '' ); | ||
| $source_format = '' !== $odt_template ? 'odt' : ('' !== $docx_template ? 'docx' : ''); | ||
|
|
||
| $docx_message = __( 'Configure a DOCX template in the document type.', 'documentate' ); | ||
| if ( $docx_requires_conversion && ! $can_convert ) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message( 'odt', 'docx' ); | ||
| $docx_message = __('Configure a DOCX template in the document type.', 'documentate'); | ||
| if ($docx_requires_conversion && !$can_convert) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message('odt', 'docx'); | ||
| } | ||
|
|
||
| $odt_message = __( 'Configure an ODT template in the document type.', 'documentate' ); | ||
| if ( $odt_requires_conversion && ! $can_convert ) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message( 'docx', 'odt' ); | ||
| $odt_message = __('Configure an ODT template in the document type.', 'documentate'); | ||
| if ($odt_requires_conversion && !$can_convert) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message('docx', 'odt'); | ||
| } | ||
|
|
||
| if ( '' === $docx_template && '' === $odt_template ) { | ||
| $pdf_message = __( 'Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate' ); | ||
| } elseif ( ! $can_convert ) { | ||
| if ('' === $docx_template && '' === $odt_template) { | ||
| $pdf_message = __('Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate'); | ||
| } elseif (!$can_convert) { | ||
| $source_for_pdf = '' !== $docx_template ? 'docx' : 'odt'; | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message( $source_for_pdf, 'pdf' ); | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message($source_for_pdf, 'pdf'); | ||
| } else { | ||
| $pdf_message = ''; | ||
| } | ||
|
|
||
| // Preview is available if server conversion is ready OR if popup conversion is available. | ||
| $preview_available = $pdf_available || ( $use_popup_for_conversion && ( '' !== $docx_template || '' !== $odt_template ) ); | ||
| $preview_message = $pdf_message; | ||
| $preview_available = $pdf_available || $use_popup_for_conversion && ('' !== $docx_template || '' !== $odt_template); | ||
| $preview_message = $pdf_message; | ||
|
|
||
| $preferred_format = ''; | ||
| $types = wp_get_post_terms( $post->ID, 'documentate_doc_type', array( 'fields' => 'ids' ) ); | ||
| if ( ! is_wp_error( $types ) && ! empty( $types ) ) { | ||
| $type_id = intval( $types[0] ); | ||
| $template_format = sanitize_key( (string) get_term_meta( $type_id, 'documentate_type_template_type', true ) ); | ||
| if ( in_array( $template_format, array( 'docx', 'odt' ), true ) ) { | ||
| $types = wp_get_post_terms($post->ID, 'documentate_doc_type', array('fields' => 'ids')); | ||
| if (!is_wp_error($types) && !empty($types)) { | ||
| $type_id = intval($types[0]); | ||
| $template_format = sanitize_key((string) get_term_meta($type_id, 'documentate_type_template_type', true)); | ||
| if (in_array($template_format, array('docx', 'odt'), true)) { | ||
| $preferred_format = $template_format; | ||
| } | ||
| } | ||
| if ( '' === $preferred_format ) { | ||
| if ( '' !== $docx_template ) { | ||
| if ('' === $preferred_format) { | ||
| if ('' !== $docx_template) { | ||
| $preferred_format = 'docx'; | ||
| } elseif ( '' !== $odt_template ) { | ||
| } elseif ('' !== $odt_template) { | ||
| $preferred_format = 'odt'; | ||
| } | ||
| } | ||
|
|
||
| echo '<p>'; | ||
| if ( $preview_available ) { | ||
| // ── Primary row: Preview + Download PDF ────────────────────────── | ||
| $needs_popup_base = $zetajs_cdn_available && !$conversion_ready || $collabora_in_playground; | ||
|
|
||
| echo '<div class="documentate-actions-primary">'; | ||
|
|
||
| // Preview button. | ||
| if ($preview_available) { | ||
| $preview_attrs = array( | ||
| 'class' => 'button button-secondary documentate-action-btn', | ||
| 'href' => '#', | ||
| 'class' => 'button documentate-action-btn documentate-action-btn--preview', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'preview', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| // Use popup for browser-based conversion: | ||
| // - ZetaJS CDN mode when no server conversion is available | ||
| // - Collabora in Playground (always, to bypass wp_remote_post multipart issues). | ||
| $needs_popup = ( $zetajs_cdn_available && ! $conversion_ready ) || $collabora_in_playground; | ||
| if ( $needs_popup ) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $needs_popup = $needs_popup_base; | ||
| if ($needs_popup) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $preview_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo '<a ' . $this->build_action_attributes( $preview_attrs ) . '>' . esc_html__( 'Preview', 'documentate' ) . '</a>'; | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($preview_attrs) | ||
| . '><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo '<button type="button" class="button button-secondary" disabled title="' . esc_attr( $preview_message ) . '">' . esc_html__( 'Preview', 'documentate' ) . '</button>'; | ||
| echo | ||
| '<button type="button" class="button documentate-action-btn--preview" disabled title="' | ||
| . esc_attr($preview_message) | ||
| . '"><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
|
|
||
| // Download PDF button (primary/blue). | ||
| if ($pdf_available) { | ||
| $pdf_attrs = array( | ||
| 'class' => 'button button-primary documentate-action-btn documentate-action-btn--pdf', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'download', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| if ($needs_popup_base && 'pdf' !== $source_format) { | ||
| $pdf_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $pdf_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($pdf_attrs) | ||
| . '><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo | ||
| '<button type="button" class="button button-primary documentate-action-btn--pdf" disabled title="' | ||
| . esc_attr($pdf_message) | ||
| . '"><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
| echo '</p>'; | ||
|
|
||
| $buttons = array( | ||
| 'docx' => array( | ||
| 'href' => $docx, | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'primary' => ( 'docx' === $preferred_format ), | ||
| 'label' => 'DOCX', | ||
| ), | ||
| 'odt' => array( | ||
| 'href' => $odt, | ||
| echo '</div>'; | ||
|
|
||
| // ── Secondary row: Other download formats ──────────────────────── | ||
| $secondary_buttons = array( | ||
| 'odt' => array( | ||
| 'available' => $odt_available, | ||
| 'message' => $odt_message, | ||
| 'primary' => ( 'odt' === $preferred_format ), | ||
| 'label' => 'ODT', | ||
| 'message' => $odt_message, | ||
| 'label' => __('ODT (Source)', 'documentate'), | ||
| ), | ||
| 'pdf' => array( | ||
| 'href' => $pdf, | ||
| 'available' => $pdf_available, | ||
| 'message' => $pdf_message, | ||
| 'primary' => false, | ||
| 'label' => 'PDF', | ||
| 'docx' => array( | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'label' => 'DOCX', | ||
| ), | ||
| ); | ||
|
|
||
| echo '<p>'; | ||
| foreach ( array( 'docx', 'odt', 'pdf' ) as $format ) { | ||
| $data = $buttons[ $format ]; | ||
| $class = $data['primary'] ? 'button button-primary documentate-action-btn' : 'button documentate-action-btn'; | ||
| if ( $data['available'] ) { | ||
| echo '<div class="documentate-actions-secondary">'; | ||
| echo | ||
| '<span class="documentate-actions-secondary__label">' | ||
| . esc_html__('Other download formats:', 'documentate') | ||
| . '</span>' | ||
| ; | ||
| echo '<span class="documentate-actions-secondary__buttons">'; | ||
| foreach ($secondary_buttons as $format => $data) { | ||
| if ($data['available']) { | ||
| $attrs = array( | ||
| 'class' => $class, | ||
| 'href' => '#', | ||
| 'class' => 'button button-small documentate-action-btn', |
Check warning
Code scanning / PHPMD
Code Size Rules: CyclomaticComplexity Warning
| echo '<p>' . esc_html__('Insufficient permissions.', 'documentate') . '</p>'; | ||
| return; | ||
| } | ||
|
|
||
| $nonce_export = wp_create_nonce( 'documentate_export_' . $post->ID ); | ||
| $nonce_prev = wp_create_nonce( 'documentate_preview_' . $post->ID ); | ||
| $nonce_export = wp_create_nonce('documentate_export_' . $post->ID); | ||
| $nonce_prev = wp_create_nonce('documentate_preview_' . $post->ID); | ||
|
|
||
| $preview = $this->build_action_url( 'documentate_preview', $post->ID, $nonce_prev ); | ||
| $docx = $this->build_action_url( 'documentate_export_docx', $post->ID, $nonce_export ); | ||
| $pdf = $this->build_action_url( 'documentate_export_pdf', $post->ID, $nonce_export ); | ||
| $odt = $this->build_action_url( 'documentate_export_odt', $post->ID, $nonce_export ); | ||
| $preview = $this->build_action_url('documentate_preview', $post->ID, $nonce_prev); | ||
| $docx = $this->build_action_url('documentate_export_docx', $post->ID, $nonce_export); | ||
| $pdf = $this->build_action_url('documentate_export_pdf', $post->ID, $nonce_export); | ||
| $odt = $this->build_action_url('documentate_export_odt', $post->ID, $nonce_export); | ||
|
|
||
| $this->ensure_document_generator(); | ||
|
|
||
| $docx_template = Documentate_Document_Generator::get_template_path( $post->ID, 'docx' ); | ||
| $odt_template = Documentate_Document_Generator::get_template_path( $post->ID, 'odt' ); | ||
| $docx_template = Documentate_Document_Generator::get_template_path($post->ID, 'docx'); | ||
| $odt_template = Documentate_Document_Generator::get_template_path($post->ID, 'odt'); | ||
|
|
||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-conversion-manager.php'; | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-conversion-manager.php'; | ||
|
|
||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = ( '' === $docx_template && '' !== $odt_template ); | ||
| $odt_requires_conversion = ( '' === $odt_template && '' !== $docx_template ); | ||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = '' === $docx_template && '' !== $odt_template; | ||
| $odt_requires_conversion = '' === $odt_template && '' !== $docx_template; | ||
|
|
||
| // Check if ZetaJS CDN mode is available for browser-based preview. | ||
| $zetajs_cdn_available = false; | ||
| if ( ! $conversion_ready ) { | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-zetajs-converter.php'; | ||
| if (!$conversion_ready) { | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-zetajs-converter.php'; | ||
| $zetajs_cdn_available = Documentate_Zetajs_Converter::is_cdn_mode(); | ||
| } | ||
|
|
||
| // Check if we need popup-based conversion (bypasses PHP networking issues in Playground). | ||
| // This is needed for: | ||
| // 1. ZetaJS CDN mode (WASM conversion in browser) | ||
| // 2. Collabora in Playground (JavaScript fetch bypasses wp_remote_post multipart issues). | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = | ||
| Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| $use_popup_for_conversion = $zetajs_cdn_available || $collabora_in_playground; | ||
|
|
||
| // In CDN mode or Playground with Collabora, browser can do conversions too. | ||
| $can_convert = $conversion_ready || $use_popup_for_conversion; | ||
| $docx_available = ( '' !== $docx_template ) || ( $docx_requires_conversion && $can_convert ); | ||
| $odt_available = ( '' !== $odt_template ) || ( $odt_requires_conversion && $can_convert ); | ||
| $pdf_available = $can_convert && ( '' !== $docx_template || '' !== $odt_template ); | ||
| $docx_available = '' !== $docx_template || $docx_requires_conversion && $can_convert; | ||
| $odt_available = '' !== $odt_template || $odt_requires_conversion && $can_convert; | ||
| $pdf_available = $can_convert && ('' !== $docx_template || '' !== $odt_template); | ||
|
|
||
| // Determine source format for CDN conversions. | ||
| $source_format = '' !== $odt_template ? 'odt' : ( '' !== $docx_template ? 'docx' : '' ); | ||
| $source_format = '' !== $odt_template ? 'odt' : ('' !== $docx_template ? 'docx' : ''); | ||
|
|
||
| $docx_message = __( 'Configure a DOCX template in the document type.', 'documentate' ); | ||
| if ( $docx_requires_conversion && ! $can_convert ) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message( 'odt', 'docx' ); | ||
| $docx_message = __('Configure a DOCX template in the document type.', 'documentate'); | ||
| if ($docx_requires_conversion && !$can_convert) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message('odt', 'docx'); | ||
| } | ||
|
|
||
| $odt_message = __( 'Configure an ODT template in the document type.', 'documentate' ); | ||
| if ( $odt_requires_conversion && ! $can_convert ) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message( 'docx', 'odt' ); | ||
| $odt_message = __('Configure an ODT template in the document type.', 'documentate'); | ||
| if ($odt_requires_conversion && !$can_convert) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message('docx', 'odt'); | ||
| } | ||
|
|
||
| if ( '' === $docx_template && '' === $odt_template ) { | ||
| $pdf_message = __( 'Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate' ); | ||
| } elseif ( ! $can_convert ) { | ||
| if ('' === $docx_template && '' === $odt_template) { | ||
| $pdf_message = __('Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate'); | ||
| } elseif (!$can_convert) { | ||
| $source_for_pdf = '' !== $docx_template ? 'docx' : 'odt'; | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message( $source_for_pdf, 'pdf' ); | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message($source_for_pdf, 'pdf'); | ||
| } else { | ||
| $pdf_message = ''; | ||
| } | ||
|
|
||
| // Preview is available if server conversion is ready OR if popup conversion is available. | ||
| $preview_available = $pdf_available || ( $use_popup_for_conversion && ( '' !== $docx_template || '' !== $odt_template ) ); | ||
| $preview_message = $pdf_message; | ||
| $preview_available = $pdf_available || $use_popup_for_conversion && ('' !== $docx_template || '' !== $odt_template); | ||
| $preview_message = $pdf_message; | ||
|
|
||
| $preferred_format = ''; | ||
| $types = wp_get_post_terms( $post->ID, 'documentate_doc_type', array( 'fields' => 'ids' ) ); | ||
| if ( ! is_wp_error( $types ) && ! empty( $types ) ) { | ||
| $type_id = intval( $types[0] ); | ||
| $template_format = sanitize_key( (string) get_term_meta( $type_id, 'documentate_type_template_type', true ) ); | ||
| if ( in_array( $template_format, array( 'docx', 'odt' ), true ) ) { | ||
| $types = wp_get_post_terms($post->ID, 'documentate_doc_type', array('fields' => 'ids')); | ||
| if (!is_wp_error($types) && !empty($types)) { | ||
| $type_id = intval($types[0]); | ||
| $template_format = sanitize_key((string) get_term_meta($type_id, 'documentate_type_template_type', true)); | ||
| if (in_array($template_format, array('docx', 'odt'), true)) { | ||
| $preferred_format = $template_format; | ||
| } | ||
| } | ||
| if ( '' === $preferred_format ) { | ||
| if ( '' !== $docx_template ) { | ||
| if ('' === $preferred_format) { | ||
| if ('' !== $docx_template) { | ||
| $preferred_format = 'docx'; | ||
| } elseif ( '' !== $odt_template ) { | ||
| } elseif ('' !== $odt_template) { | ||
| $preferred_format = 'odt'; | ||
| } | ||
| } | ||
|
|
||
| echo '<p>'; | ||
| if ( $preview_available ) { | ||
| // ── Primary row: Preview + Download PDF ────────────────────────── | ||
| $needs_popup_base = $zetajs_cdn_available && !$conversion_ready || $collabora_in_playground; | ||
|
|
||
| echo '<div class="documentate-actions-primary">'; | ||
|
|
||
| // Preview button. | ||
| if ($preview_available) { | ||
| $preview_attrs = array( | ||
| 'class' => 'button button-secondary documentate-action-btn', | ||
| 'href' => '#', | ||
| 'class' => 'button documentate-action-btn documentate-action-btn--preview', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'preview', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| // Use popup for browser-based conversion: | ||
| // - ZetaJS CDN mode when no server conversion is available | ||
| // - Collabora in Playground (always, to bypass wp_remote_post multipart issues). | ||
| $needs_popup = ( $zetajs_cdn_available && ! $conversion_ready ) || $collabora_in_playground; | ||
| if ( $needs_popup ) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $needs_popup = $needs_popup_base; | ||
| if ($needs_popup) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $preview_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo '<a ' . $this->build_action_attributes( $preview_attrs ) . '>' . esc_html__( 'Preview', 'documentate' ) . '</a>'; | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($preview_attrs) | ||
| . '><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo '<button type="button" class="button button-secondary" disabled title="' . esc_attr( $preview_message ) . '">' . esc_html__( 'Preview', 'documentate' ) . '</button>'; | ||
| echo | ||
| '<button type="button" class="button documentate-action-btn--preview" disabled title="' | ||
| . esc_attr($preview_message) | ||
| . '"><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
|
|
||
| // Download PDF button (primary/blue). | ||
| if ($pdf_available) { | ||
| $pdf_attrs = array( | ||
| 'class' => 'button button-primary documentate-action-btn documentate-action-btn--pdf', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'download', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| if ($needs_popup_base && 'pdf' !== $source_format) { | ||
| $pdf_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $pdf_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($pdf_attrs) | ||
| . '><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo | ||
| '<button type="button" class="button button-primary documentate-action-btn--pdf" disabled title="' | ||
| . esc_attr($pdf_message) | ||
| . '"><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
| echo '</p>'; | ||
|
|
||
| $buttons = array( | ||
| 'docx' => array( | ||
| 'href' => $docx, | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'primary' => ( 'docx' === $preferred_format ), | ||
| 'label' => 'DOCX', | ||
| ), | ||
| 'odt' => array( | ||
| 'href' => $odt, | ||
| echo '</div>'; | ||
|
|
||
| // ── Secondary row: Other download formats ──────────────────────── | ||
| $secondary_buttons = array( | ||
| 'odt' => array( | ||
| 'available' => $odt_available, | ||
| 'message' => $odt_message, | ||
| 'primary' => ( 'odt' === $preferred_format ), | ||
| 'label' => 'ODT', | ||
| 'message' => $odt_message, | ||
| 'label' => __('ODT (Source)', 'documentate'), | ||
| ), | ||
| 'pdf' => array( | ||
| 'href' => $pdf, | ||
| 'available' => $pdf_available, | ||
| 'message' => $pdf_message, | ||
| 'primary' => false, | ||
| 'label' => 'PDF', | ||
| 'docx' => array( | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'label' => 'DOCX', | ||
| ), | ||
| ); | ||
|
|
||
| echo '<p>'; | ||
| foreach ( array( 'docx', 'odt', 'pdf' ) as $format ) { | ||
| $data = $buttons[ $format ]; | ||
| $class = $data['primary'] ? 'button button-primary documentate-action-btn' : 'button documentate-action-btn'; | ||
| if ( $data['available'] ) { | ||
| echo '<div class="documentate-actions-secondary">'; | ||
| echo | ||
| '<span class="documentate-actions-secondary__label">' | ||
| . esc_html__('Other download formats:', 'documentate') | ||
| . '</span>' | ||
| ; | ||
| echo '<span class="documentate-actions-secondary__buttons">'; | ||
| foreach ($secondary_buttons as $format => $data) { | ||
| if ($data['available']) { | ||
| $attrs = array( | ||
| 'class' => $class, | ||
| 'href' => '#', | ||
| 'class' => 'button button-small documentate-action-btn', |
Check warning
Code scanning / PHPMD
Code Size Rules: NPathComplexity Warning
| echo '<p>' . esc_html__('Insufficient permissions.', 'documentate') . '</p>'; | ||
| return; | ||
| } | ||
|
|
||
| $nonce_export = wp_create_nonce( 'documentate_export_' . $post->ID ); | ||
| $nonce_prev = wp_create_nonce( 'documentate_preview_' . $post->ID ); | ||
| $nonce_export = wp_create_nonce('documentate_export_' . $post->ID); | ||
| $nonce_prev = wp_create_nonce('documentate_preview_' . $post->ID); | ||
|
|
||
| $preview = $this->build_action_url( 'documentate_preview', $post->ID, $nonce_prev ); | ||
| $docx = $this->build_action_url( 'documentate_export_docx', $post->ID, $nonce_export ); | ||
| $pdf = $this->build_action_url( 'documentate_export_pdf', $post->ID, $nonce_export ); | ||
| $odt = $this->build_action_url( 'documentate_export_odt', $post->ID, $nonce_export ); | ||
| $preview = $this->build_action_url('documentate_preview', $post->ID, $nonce_prev); | ||
| $docx = $this->build_action_url('documentate_export_docx', $post->ID, $nonce_export); | ||
| $pdf = $this->build_action_url('documentate_export_pdf', $post->ID, $nonce_export); | ||
| $odt = $this->build_action_url('documentate_export_odt', $post->ID, $nonce_export); | ||
|
|
||
| $this->ensure_document_generator(); | ||
|
|
||
| $docx_template = Documentate_Document_Generator::get_template_path( $post->ID, 'docx' ); | ||
| $odt_template = Documentate_Document_Generator::get_template_path( $post->ID, 'odt' ); | ||
| $docx_template = Documentate_Document_Generator::get_template_path($post->ID, 'docx'); | ||
| $odt_template = Documentate_Document_Generator::get_template_path($post->ID, 'odt'); | ||
|
|
||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-conversion-manager.php'; | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-conversion-manager.php'; | ||
|
|
||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = ( '' === $docx_template && '' !== $odt_template ); | ||
| $odt_requires_conversion = ( '' === $odt_template && '' !== $docx_template ); | ||
| $conversion_ready = Documentate_Conversion_Manager::is_available(); | ||
| $engine_label = Documentate_Conversion_Manager::get_engine_label(); | ||
| $docx_requires_conversion = '' === $docx_template && '' !== $odt_template; | ||
| $odt_requires_conversion = '' === $odt_template && '' !== $docx_template; | ||
|
|
||
| // Check if ZetaJS CDN mode is available for browser-based preview. | ||
| $zetajs_cdn_available = false; | ||
| if ( ! $conversion_ready ) { | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-zetajs-converter.php'; | ||
| if (!$conversion_ready) { | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-zetajs-converter.php'; | ||
| $zetajs_cdn_available = Documentate_Zetajs_Converter::is_cdn_mode(); | ||
| } | ||
|
|
||
| // Check if we need popup-based conversion (bypasses PHP networking issues in Playground). | ||
| // This is needed for: | ||
| // 1. ZetaJS CDN mode (WASM conversion in browser) | ||
| // 2. Collabora in Playground (JavaScript fetch bypasses wp_remote_post multipart issues). | ||
| require_once plugin_dir_path( __DIR__ ) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| require_once plugin_dir_path(__DIR__) . 'includes/class-documentate-collabora-converter.php'; | ||
| $collabora_in_playground = | ||
| Documentate_Collabora_Converter::is_playground() && Documentate_Collabora_Converter::is_available(); | ||
| $use_popup_for_conversion = $zetajs_cdn_available || $collabora_in_playground; | ||
|
|
||
| // In CDN mode or Playground with Collabora, browser can do conversions too. | ||
| $can_convert = $conversion_ready || $use_popup_for_conversion; | ||
| $docx_available = ( '' !== $docx_template ) || ( $docx_requires_conversion && $can_convert ); | ||
| $odt_available = ( '' !== $odt_template ) || ( $odt_requires_conversion && $can_convert ); | ||
| $pdf_available = $can_convert && ( '' !== $docx_template || '' !== $odt_template ); | ||
| $docx_available = '' !== $docx_template || $docx_requires_conversion && $can_convert; | ||
| $odt_available = '' !== $odt_template || $odt_requires_conversion && $can_convert; | ||
| $pdf_available = $can_convert && ('' !== $docx_template || '' !== $odt_template); | ||
|
|
||
| // Determine source format for CDN conversions. | ||
| $source_format = '' !== $odt_template ? 'odt' : ( '' !== $docx_template ? 'docx' : '' ); | ||
| $source_format = '' !== $odt_template ? 'odt' : ('' !== $docx_template ? 'docx' : ''); | ||
|
|
||
| $docx_message = __( 'Configure a DOCX template in the document type.', 'documentate' ); | ||
| if ( $docx_requires_conversion && ! $can_convert ) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message( 'odt', 'docx' ); | ||
| $docx_message = __('Configure a DOCX template in the document type.', 'documentate'); | ||
| if ($docx_requires_conversion && !$can_convert) { | ||
| $docx_message = Documentate_Conversion_Manager::get_unavailable_message('odt', 'docx'); | ||
| } | ||
|
|
||
| $odt_message = __( 'Configure an ODT template in the document type.', 'documentate' ); | ||
| if ( $odt_requires_conversion && ! $can_convert ) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message( 'docx', 'odt' ); | ||
| $odt_message = __('Configure an ODT template in the document type.', 'documentate'); | ||
| if ($odt_requires_conversion && !$can_convert) { | ||
| $odt_message = Documentate_Conversion_Manager::get_unavailable_message('docx', 'odt'); | ||
| } | ||
|
|
||
| if ( '' === $docx_template && '' === $odt_template ) { | ||
| $pdf_message = __( 'Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate' ); | ||
| } elseif ( ! $can_convert ) { | ||
| if ('' === $docx_template && '' === $odt_template) { | ||
| $pdf_message = __('Configure a DOCX or ODT template in the document type before generating PDF.', 'documentate'); | ||
| } elseif (!$can_convert) { | ||
| $source_for_pdf = '' !== $docx_template ? 'docx' : 'odt'; | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message( $source_for_pdf, 'pdf' ); | ||
| $pdf_message = Documentate_Conversion_Manager::get_unavailable_message($source_for_pdf, 'pdf'); | ||
| } else { | ||
| $pdf_message = ''; | ||
| } | ||
|
|
||
| // Preview is available if server conversion is ready OR if popup conversion is available. | ||
| $preview_available = $pdf_available || ( $use_popup_for_conversion && ( '' !== $docx_template || '' !== $odt_template ) ); | ||
| $preview_message = $pdf_message; | ||
| $preview_available = $pdf_available || $use_popup_for_conversion && ('' !== $docx_template || '' !== $odt_template); | ||
| $preview_message = $pdf_message; | ||
|
|
||
| $preferred_format = ''; | ||
| $types = wp_get_post_terms( $post->ID, 'documentate_doc_type', array( 'fields' => 'ids' ) ); | ||
| if ( ! is_wp_error( $types ) && ! empty( $types ) ) { | ||
| $type_id = intval( $types[0] ); | ||
| $template_format = sanitize_key( (string) get_term_meta( $type_id, 'documentate_type_template_type', true ) ); | ||
| if ( in_array( $template_format, array( 'docx', 'odt' ), true ) ) { | ||
| $types = wp_get_post_terms($post->ID, 'documentate_doc_type', array('fields' => 'ids')); | ||
| if (!is_wp_error($types) && !empty($types)) { | ||
| $type_id = intval($types[0]); | ||
| $template_format = sanitize_key((string) get_term_meta($type_id, 'documentate_type_template_type', true)); | ||
| if (in_array($template_format, array('docx', 'odt'), true)) { | ||
| $preferred_format = $template_format; | ||
| } | ||
| } | ||
| if ( '' === $preferred_format ) { | ||
| if ( '' !== $docx_template ) { | ||
| if ('' === $preferred_format) { | ||
| if ('' !== $docx_template) { | ||
| $preferred_format = 'docx'; | ||
| } elseif ( '' !== $odt_template ) { | ||
| } elseif ('' !== $odt_template) { | ||
| $preferred_format = 'odt'; | ||
| } | ||
| } | ||
|
|
||
| echo '<p>'; | ||
| if ( $preview_available ) { | ||
| // ── Primary row: Preview + Download PDF ────────────────────────── | ||
| $needs_popup_base = $zetajs_cdn_available && !$conversion_ready || $collabora_in_playground; | ||
|
|
||
| echo '<div class="documentate-actions-primary">'; | ||
|
|
||
| // Preview button. | ||
| if ($preview_available) { | ||
| $preview_attrs = array( | ||
| 'class' => 'button button-secondary documentate-action-btn', | ||
| 'href' => '#', | ||
| 'class' => 'button documentate-action-btn documentate-action-btn--preview', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'preview', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| // Use popup for browser-based conversion: | ||
| // - ZetaJS CDN mode when no server conversion is available | ||
| // - Collabora in Playground (always, to bypass wp_remote_post multipart issues). | ||
| $needs_popup = ( $zetajs_cdn_available && ! $conversion_ready ) || $collabora_in_playground; | ||
| if ( $needs_popup ) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $needs_popup = $needs_popup_base; | ||
| if ($needs_popup) { | ||
| $preview_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $preview_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo '<a ' . $this->build_action_attributes( $preview_attrs ) . '>' . esc_html__( 'Preview', 'documentate' ) . '</a>'; | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($preview_attrs) | ||
| . '><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo '<button type="button" class="button button-secondary" disabled title="' . esc_attr( $preview_message ) . '">' . esc_html__( 'Preview', 'documentate' ) . '</button>'; | ||
| echo | ||
| '<button type="button" class="button documentate-action-btn--preview" disabled title="' | ||
| . esc_attr($preview_message) | ||
| . '"><span class="dashicons dashicons-visibility"></span> ' | ||
| . esc_html__('Preview', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
|
|
||
| // Download PDF button (primary/blue). | ||
| if ($pdf_available) { | ||
| $pdf_attrs = array( | ||
| 'class' => 'button button-primary documentate-action-btn documentate-action-btn--pdf', | ||
| 'href' => '#', | ||
| 'data-documentate-action' => 'download', | ||
| 'data-documentate-format' => 'pdf', | ||
| ); | ||
| if ($needs_popup_base && 'pdf' !== $source_format) { | ||
| $pdf_attrs['data-documentate-cdn-mode'] = '1'; | ||
| $pdf_attrs['data-documentate-source-format'] = $source_format; | ||
| } | ||
| // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Attributes sanitized in build_action_attributes(). | ||
| echo | ||
| '<a ' | ||
| . $this->build_action_attributes($pdf_attrs) | ||
| . '><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</a>' | ||
| ; | ||
| } else { | ||
| echo | ||
| '<button type="button" class="button button-primary documentate-action-btn--pdf" disabled title="' | ||
| . esc_attr($pdf_message) | ||
| . '"><span class="dashicons dashicons-pdf"></span> ' | ||
| . esc_html__('Download PDF', 'documentate') | ||
| . '</button>' | ||
| ; | ||
| } | ||
| echo '</p>'; | ||
|
|
||
| $buttons = array( | ||
| 'docx' => array( | ||
| 'href' => $docx, | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'primary' => ( 'docx' === $preferred_format ), | ||
| 'label' => 'DOCX', | ||
| ), | ||
| 'odt' => array( | ||
| 'href' => $odt, | ||
| echo '</div>'; | ||
|
|
||
| // ── Secondary row: Other download formats ──────────────────────── | ||
| $secondary_buttons = array( | ||
| 'odt' => array( | ||
| 'available' => $odt_available, | ||
| 'message' => $odt_message, | ||
| 'primary' => ( 'odt' === $preferred_format ), | ||
| 'label' => 'ODT', | ||
| 'message' => $odt_message, | ||
| 'label' => __('ODT (Source)', 'documentate'), | ||
| ), | ||
| 'pdf' => array( | ||
| 'href' => $pdf, | ||
| 'available' => $pdf_available, | ||
| 'message' => $pdf_message, | ||
| 'primary' => false, | ||
| 'label' => 'PDF', | ||
| 'docx' => array( | ||
| 'available' => $docx_available, | ||
| 'message' => $docx_message, | ||
| 'label' => 'DOCX', | ||
| ), | ||
| ); | ||
|
|
||
| echo '<p>'; | ||
| foreach ( array( 'docx', 'odt', 'pdf' ) as $format ) { | ||
| $data = $buttons[ $format ]; | ||
| $class = $data['primary'] ? 'button button-primary documentate-action-btn' : 'button documentate-action-btn'; | ||
| if ( $data['available'] ) { | ||
| echo '<div class="documentate-actions-secondary">'; | ||
| echo | ||
| '<span class="documentate-actions-secondary__label">' | ||
| . esc_html__('Other download formats:', 'documentate') | ||
| . '</span>' | ||
| ; | ||
| echo '<span class="documentate-actions-secondary__buttons">'; | ||
| foreach ($secondary_buttons as $format => $data) { | ||
| if ($data['available']) { | ||
| $attrs = array( | ||
| 'class' => $class, | ||
| 'href' => '#', | ||
| 'class' => 'button button-small documentate-action-btn', |
Check warning
Code scanning / PHPMD
Code Size Rules: ExcessiveMethodLength Warning
| */ | ||
| private static function build_merge_fields( $post_id ) { | ||
| private static function build_merge_fields($post_id) { | ||
| self::reset_rich_field_values(); | ||
| $opts = get_option( 'documentate_settings', array() ); | ||
| $post = get_post( $post_id ); | ||
| $opts = get_option('documentate_settings', array()); | ||
| $post = get_post($post_id); | ||
| $structured = array(); | ||
| if ( $post && class_exists( 'Documentate_Documents' ) ) { | ||
| $content = get_post_field( 'post_content', $post_id, 'raw' ); | ||
| if ( ! is_string( $content ) || '' === $content ) { | ||
| if ($post && class_exists('Documentate_Documents')) { | ||
| $content = get_post_field('post_content', $post_id, 'raw'); | ||
| if (!is_string($content) || '' === $content) { | ||
| $content = $post->post_content; | ||
| } | ||
| $structured = Documentate_Documents::parse_structured_content( (string) $content ); | ||
| $structured = Documentate_Documents::parse_structured_content((string) $content); | ||
| } | ||
|
|
||
| // Apply case transformation to title based on schema attribute. | ||
| $title = get_post_field( 'post_title', $post_id, 'raw' ); | ||
| $title_case = self::get_title_case_from_schema( $post_id ); | ||
| $title = self::apply_case_transformation( $title, $title_case ); | ||
| $title = get_post_field('post_title', $post_id, 'raw'); | ||
| $title_case = self::get_title_case_from_schema($post_id); | ||
| $title = self::apply_case_transformation($title, $title_case); | ||
|
|
||
| $fields = array( | ||
| 'title' => $title, | ||
| 'title' => $title, | ||
| 'post_title' => $title, // Alias for templates using [post_title]. | ||
| 'margen' => wp_strip_all_tags( isset( $opts['doc_margin_text'] ) ? $opts['doc_margin_text'] : '' ), | ||
| 'margen' => wp_strip_all_tags(isset($opts['doc_margin_text']) ? $opts['doc_margin_text'] : ''), | ||
| ); | ||
|
|
||
| $types = wp_get_post_terms( $post_id, 'documentate_doc_type', array( 'fields' => 'ids' ) ); | ||
| if ( ! is_wp_error( $types ) && ! empty( $types ) ) { | ||
| $type_id = intval( $types[0] ); | ||
| $schema = array(); | ||
| if ( class_exists( 'Documentate_Documents' ) ) { | ||
| $schema = Documentate_Documents::get_term_schema( $type_id ); | ||
| $types = wp_get_post_terms($post_id, 'documentate_doc_type', array('fields' => 'ids')); | ||
| if (!is_wp_error($types) && !empty($types)) { | ||
| $type_id = intval($types[0]); | ||
| $schema = array(); | ||
| if (class_exists('Documentate_Documents')) { | ||
| $schema = Documentate_Documents::get_term_schema($type_id); | ||
| } else { | ||
| $schema = self::get_type_schema( $type_id ); | ||
| $schema = self::get_type_schema($type_id); | ||
| } | ||
| foreach ( $schema as $def ) { | ||
| if ( empty( $def['slug'] ) ) { | ||
| continue; | ||
| foreach ($schema as $def) { | ||
| if (empty($def['slug'])) { | ||
| continue; | ||
| } | ||
| $slug = sanitize_key( $def['slug'] ); | ||
| $slug = sanitize_key($def['slug']); | ||
|
|
||
| // Skip post_title - it's already set from get_the_title() above. | ||
| if ( 'post_title' === $slug ) { | ||
| if ('post_title' === $slug) { | ||
| continue; | ||
| } | ||
| // Prefer the original template name for TinyButStrong merges when available. | ||
| $tbs_name = ''; | ||
| if ( isset( $def['name'] ) && is_string( $def['name'] ) ) { | ||
| $tbs_name = self::sanitize_placeholder_name( $def['name'] ); | ||
| // Prefer the original template name for TinyButStrong merges when available. | ||
| $tbs_name = ''; | ||
| if (isset($def['name']) && is_string($def['name'])) { | ||
| $tbs_name = self::sanitize_placeholder_name($def['name']); | ||
| } | ||
| if ( '' === $tbs_name ) { | ||
| $tbs_name = self::sanitize_placeholder_name( $slug ); | ||
| if ('' === $tbs_name) { | ||
| $tbs_name = self::sanitize_placeholder_name($slug); | ||
| } | ||
|
|
||
| // Keep the legacy key used by UI (placeholder or slug) as alias for backward compatibility. | ||
| $alias_key = ''; | ||
| if ( isset( $def['placeholder'] ) && is_string( $def['placeholder'] ) ) { | ||
| $alias_key = self::sanitize_placeholder_name( $def['placeholder'] ); | ||
| // Keep the legacy key used by UI (placeholder or slug) as alias for backward compatibility. | ||
| $alias_key = ''; | ||
| if (isset($def['placeholder']) && is_string($def['placeholder'])) { | ||
| $alias_key = self::sanitize_placeholder_name($def['placeholder']); | ||
| } | ||
| if ( '' === $alias_key ) { | ||
| $alias_key = self::sanitize_placeholder_name( $slug ); | ||
| if ('' === $alias_key) { | ||
| $alias_key = self::sanitize_placeholder_name($slug); | ||
| } | ||
| $data_type = isset( $def['data_type'] ) ? sanitize_key( $def['data_type'] ) : 'text'; | ||
| $type = isset( $def['type'] ) ? sanitize_key( $def['type'] ) : 'textarea'; | ||
| $data_type = isset($def['data_type']) ? sanitize_key($def['data_type']) : 'text'; | ||
| $type = isset($def['type']) ? sanitize_key($def['type']) : 'textarea'; | ||
|
|
||
| if ( 'array' === $type ) { | ||
| $items = self::get_array_field_items_for_merge( $structured, $slug, $post_id ); | ||
| if ('array' === $type) { | ||
| $items = self::get_array_field_items_for_merge($structured, $slug, $post_id); | ||
|
|
||
| // Apply case transformations to repeater items. | ||
| $item_schema = isset( $def['item_schema'] ) ? $def['item_schema'] : array(); | ||
| $items = self::apply_case_to_array_items( $items, $item_schema ); | ||
| $item_schema = isset($def['item_schema']) ? $def['item_schema'] : array(); | ||
| $items = self::apply_case_to_array_items($items, $item_schema); | ||
|
|
||
| // Use block name for MergeBlock, with alias for legacy behavior. | ||
| $fields[ $tbs_name ] = $items; | ||
| if ( $alias_key !== $tbs_name ) { | ||
| $fields[ $alias_key ] = $items; | ||
| $fields[$tbs_name] = $items; | ||
| if ($alias_key !== $tbs_name) { | ||
| $fields[$alias_key] = $items; | ||
| } | ||
| self::remember_rich_values_from_array_items( $items ); | ||
| self::remember_rich_values_from_array_items($items); | ||
| continue; | ||
| } | ||
|
|
||
| $value = self::get_structured_field_value( $structured, $slug, $post_id ); | ||
| $value = self::get_structured_field_value($structured, $slug, $post_id); | ||
| // Force rich type if value contains block HTML, BEFORE prepare strips tags. | ||
| $original_type = $type; | ||
| if ( ! in_array( $type, array( 'rich', 'html' ), true ) && Documents_Meta_Handler::value_contains_block_html( $value ) ) { | ||
| if (!in_array($type, array('rich', 'html'), true) && Documents_Meta_Handler::value_contains_block_html($value)) { | ||
| $type = 'rich'; | ||
| } | ||
| $prepared = self::prepare_field_value( $value, $type, $data_type, $def ); | ||
| $prepared = self::prepare_field_value($value, $type, $data_type, $def); | ||
|
|
||
| // Apply case transformation if specified (skip for HTML content). | ||
| $field_case = isset( $def['case'] ) ? sanitize_key( $def['case'] ) : ''; | ||
| if ( '' !== $field_case && ! in_array( $type, array( 'rich', 'html' ), true ) ) { | ||
| $prepared = self::apply_case_transformation( $prepared, $field_case ); | ||
| $field_case = isset($def['case']) ? sanitize_key($def['case']) : ''; | ||
| if ('' !== $field_case && !in_array($type, array('rich', 'html'), true)) { | ||
| $prepared = self::apply_case_transformation($prepared, $field_case); | ||
| } | ||
|
|
||
| $fields[ $tbs_name ] = $prepared; | ||
| if ( $alias_key !== $tbs_name ) { | ||
| $fields[ $alias_key ] = $prepared; | ||
| $fields[$tbs_name] = $prepared; | ||
| if ($alias_key !== $tbs_name) { | ||
| $fields[$alias_key] = $prepared; | ||
| } | ||
| // Register for rich text conversion if typed as rich/html. | ||
| // Also check if prepared value still contains HTML as a safety net. | ||
| $has_html_in_prepared = Documents_Meta_Handler::value_contains_block_html( $prepared ); | ||
| if ( in_array( $type, array( 'rich', 'html' ), true ) || $has_html_in_prepared ) { | ||
| self::remember_rich_field_value( $prepared ); | ||
| $has_html_in_prepared = Documents_Meta_Handler::value_contains_block_html($prepared); | ||
| if (in_array($type, array('rich', 'html'), true) || $has_html_in_prepared) { | ||
| self::remember_rich_field_value($prepared); | ||
| } | ||
| // Debug logging - enable with WP_DEBUG. | ||
| if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { | ||
| error_log( | ||
| sprintf( | ||
| 'DOCUMENTATE [%s]: schema_type=%s, effective_type=%s, raw_has_html=%s, prepared_has_html=%s, raw_len=%d, prep_len=%d', | ||
| $slug, | ||
| $original_type, | ||
| $type, | ||
| Documents_Meta_Handler::value_contains_block_html( $value ) ? 'YES' : 'NO', | ||
| $has_html_in_prepared ? 'YES' : 'NO', | ||
| strlen( $value ), | ||
| strlen( $prepared ) | ||
| ) | ||
| ); | ||
| if ( Documents_Meta_Handler::value_contains_block_html( $value ) && strlen( $value ) < 500 ) { | ||
| error_log( 'DOCUMENTATE [' . $slug . '] RAW: ' . substr( $value, 0, 300 ) ); | ||
| if (defined('WP_DEBUG') && WP_DEBUG) { | ||
| error_log(sprintf( | ||
| 'DOCUMENTATE [%s]: schema_type=%s, effective_type=%s, raw_has_html=%s, prepared_has_html=%s, raw_len=%d, prep_len=%d', | ||
| $slug, | ||
| $original_type, | ||
| $type, | ||
| Documents_Meta_Handler::value_contains_block_html($value) ? 'YES' : 'NO', | ||
| $has_html_in_prepared ? 'YES' : 'NO', | ||
| strlen($value), | ||
| strlen($prepared), | ||
| )); | ||
| if (Documents_Meta_Handler::value_contains_block_html($value) && strlen($value) < 500) { | ||
| error_log('DOCUMENTATE [' . $slug . '] RAW: ' . substr($value, 0, 300)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $logos = get_term_meta( $type_id, 'documentate_type_logos', true ); | ||
| if ( is_array( $logos ) && ! empty( $logos ) ) { | ||
| $i = 1; | ||
| foreach ( $logos as $att_id ) { | ||
| $att_id = intval( $att_id ); | ||
| if ( $att_id <= 0 ) { | ||
| continue; | ||
| $logos = get_term_meta($type_id, 'documentate_type_logos', true); | ||
| if (is_array($logos) && !empty($logos)) { | ||
| $i = 1; | ||
| foreach ($logos as $att_id) { | ||
| $att_id = intval($att_id); | ||
| if ($att_id <= 0) { | ||
| continue; | ||
| } | ||
| $fields[ 'logo' . $i . '_path' ] = get_attached_file( $att_id ); | ||
| $fields[ 'logo' . $i . '_url' ] = wp_get_attachment_url( $att_id ); | ||
| $i++; | ||
| $fields['logo' . $i . '_path'] = get_attached_file($att_id); | ||
| $fields['logo' . $i . '_url'] = wp_get_attachment_url($att_id); | ||
| $i++; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ( ! empty( $structured ) ) { | ||
| foreach ( $structured as $slug => $info ) { | ||
| $slug = sanitize_key( $slug ); | ||
| if ( '' === $slug ) { | ||
| continue; | ||
| if (!empty($structured)) { | ||
| foreach ($structured as $slug => $info) { | ||
| $slug = sanitize_key($slug); | ||
| if ('' === $slug) { | ||
| continue; | ||
| } | ||
| $placeholder = $slug; | ||
| if ( isset( $fields[ $placeholder ] ) && '' !== $fields[ $placeholder ] ) { | ||
| continue; | ||
| $placeholder = $slug; | ||
| if (isset($fields[$placeholder]) && '' !== $fields[$placeholder]) { | ||
| continue; | ||
| } | ||
| if ( isset( $info['type'] ) && 'array' === sanitize_key( $info['type'] ) ) { | ||
| $items = self::get_array_field_items_for_merge( $structured, $slug, $post_id ); | ||
| $fields[ $placeholder ] = $items; | ||
| self::remember_rich_values_from_array_items( $items ); | ||
| continue; | ||
| if (isset($info['type']) && 'array' === sanitize_key($info['type'])) { | ||
| $items = self::get_array_field_items_for_merge($structured, $slug, $post_id); | ||
| $fields[$placeholder] = $items; | ||
| self::remember_rich_values_from_array_items($items); | ||
| continue; | ||
| } | ||
|
|
||
| $value = ''; | ||
| if ( isset( $info['value'] ) ) { | ||
| $value = (string) $info['value']; | ||
| $value = ''; | ||
| if (isset($info['value'])) { | ||
| $value = (string) $info['value']; | ||
| } | ||
| if ( '' === $value ) { | ||
| $value = self::get_structured_field_value( $structured, $slug, $post_id ); | ||
| if ('' === $value) { | ||
| $value = self::get_structured_field_value($structured, $slug, $post_id); | ||
| } | ||
| $field_type = isset( $info['type'] ) ? sanitize_key( $info['type'] ) : 'rich'; | ||
| $field_type = isset($info['type']) ? sanitize_key($info['type']) : 'rich'; | ||
| // Force rich type if value contains block HTML, BEFORE prepare strips tags. | ||
| if ( ! in_array( $field_type, array( 'rich', 'html' ), true ) && Documents_Meta_Handler::value_contains_block_html( $value ) ) { | ||
| if ( | ||
| !in_array($field_type, array('rich', 'html'), true) && Documents_Meta_Handler::value_contains_block_html($value) | ||
| ) { | ||
| $field_type = 'rich'; | ||
| } | ||
| $fields[ $placeholder ] = self::prepare_field_value( $value, $field_type, 'text' ); | ||
| $fields[$placeholder] = self::prepare_field_value($value, $field_type, 'text'); | ||
| // Register for rich text conversion if typed as rich/html. | ||
| // Also check if prepared value still contains HTML as a safety net. | ||
| if ( in_array( $field_type, array( 'rich', 'html' ), true ) || Documents_Meta_Handler::value_contains_block_html( $fields[ $placeholder ] ) ) { | ||
| self::remember_rich_field_value( $fields[ $placeholder ] ); | ||
| if ( | ||
| in_array($field_type, array('rich', 'html'), true) | ||
| || Documents_Meta_Handler::value_contains_block_html($fields[$placeholder]) | ||
| ) { | ||
| self::remember_rich_field_value($fields[$placeholder]); | ||
| } | ||
| } | ||
| } |
Check warning
Code scanning / PHPMD
Code Size Rules: CyclomaticComplexity Warning
| */ | ||
| private static function build_merge_fields( $post_id ) { | ||
| private static function build_merge_fields($post_id) { | ||
| self::reset_rich_field_values(); | ||
| $opts = get_option( 'documentate_settings', array() ); | ||
| $post = get_post( $post_id ); | ||
| $opts = get_option('documentate_settings', array()); | ||
| $post = get_post($post_id); | ||
| $structured = array(); | ||
| if ( $post && class_exists( 'Documentate_Documents' ) ) { | ||
| $content = get_post_field( 'post_content', $post_id, 'raw' ); | ||
| if ( ! is_string( $content ) || '' === $content ) { | ||
| if ($post && class_exists('Documentate_Documents')) { | ||
| $content = get_post_field('post_content', $post_id, 'raw'); | ||
| if (!is_string($content) || '' === $content) { | ||
| $content = $post->post_content; | ||
| } | ||
| $structured = Documentate_Documents::parse_structured_content( (string) $content ); | ||
| $structured = Documentate_Documents::parse_structured_content((string) $content); | ||
| } | ||
|
|
||
| // Apply case transformation to title based on schema attribute. | ||
| $title = get_post_field( 'post_title', $post_id, 'raw' ); | ||
| $title_case = self::get_title_case_from_schema( $post_id ); | ||
| $title = self::apply_case_transformation( $title, $title_case ); | ||
| $title = get_post_field('post_title', $post_id, 'raw'); | ||
| $title_case = self::get_title_case_from_schema($post_id); | ||
| $title = self::apply_case_transformation($title, $title_case); | ||
|
|
||
| $fields = array( | ||
| 'title' => $title, | ||
| 'title' => $title, | ||
| 'post_title' => $title, // Alias for templates using [post_title]. | ||
| 'margen' => wp_strip_all_tags( isset( $opts['doc_margin_text'] ) ? $opts['doc_margin_text'] : '' ), | ||
| 'margen' => wp_strip_all_tags(isset($opts['doc_margin_text']) ? $opts['doc_margin_text'] : ''), | ||
| ); | ||
|
|
||
| $types = wp_get_post_terms( $post_id, 'documentate_doc_type', array( 'fields' => 'ids' ) ); | ||
| if ( ! is_wp_error( $types ) && ! empty( $types ) ) { | ||
| $type_id = intval( $types[0] ); | ||
| $schema = array(); | ||
| if ( class_exists( 'Documentate_Documents' ) ) { | ||
| $schema = Documentate_Documents::get_term_schema( $type_id ); | ||
| $types = wp_get_post_terms($post_id, 'documentate_doc_type', array('fields' => 'ids')); | ||
| if (!is_wp_error($types) && !empty($types)) { | ||
| $type_id = intval($types[0]); | ||
| $schema = array(); | ||
| if (class_exists('Documentate_Documents')) { | ||
| $schema = Documentate_Documents::get_term_schema($type_id); | ||
| } else { | ||
| $schema = self::get_type_schema( $type_id ); | ||
| $schema = self::get_type_schema($type_id); | ||
| } | ||
| foreach ( $schema as $def ) { | ||
| if ( empty( $def['slug'] ) ) { | ||
| continue; | ||
| foreach ($schema as $def) { | ||
| if (empty($def['slug'])) { | ||
| continue; | ||
| } | ||
| $slug = sanitize_key( $def['slug'] ); | ||
| $slug = sanitize_key($def['slug']); | ||
|
|
||
| // Skip post_title - it's already set from get_the_title() above. | ||
| if ( 'post_title' === $slug ) { | ||
| if ('post_title' === $slug) { | ||
| continue; | ||
| } | ||
| // Prefer the original template name for TinyButStrong merges when available. | ||
| $tbs_name = ''; | ||
| if ( isset( $def['name'] ) && is_string( $def['name'] ) ) { | ||
| $tbs_name = self::sanitize_placeholder_name( $def['name'] ); | ||
| // Prefer the original template name for TinyButStrong merges when available. | ||
| $tbs_name = ''; | ||
| if (isset($def['name']) && is_string($def['name'])) { | ||
| $tbs_name = self::sanitize_placeholder_name($def['name']); | ||
| } | ||
| if ( '' === $tbs_name ) { | ||
| $tbs_name = self::sanitize_placeholder_name( $slug ); | ||
| if ('' === $tbs_name) { | ||
| $tbs_name = self::sanitize_placeholder_name($slug); | ||
| } | ||
|
|
||
| // Keep the legacy key used by UI (placeholder or slug) as alias for backward compatibility. | ||
| $alias_key = ''; | ||
| if ( isset( $def['placeholder'] ) && is_string( $def['placeholder'] ) ) { | ||
| $alias_key = self::sanitize_placeholder_name( $def['placeholder'] ); | ||
| // Keep the legacy key used by UI (placeholder or slug) as alias for backward compatibility. | ||
| $alias_key = ''; | ||
| if (isset($def['placeholder']) && is_string($def['placeholder'])) { | ||
| $alias_key = self::sanitize_placeholder_name($def['placeholder']); | ||
| } | ||
| if ( '' === $alias_key ) { | ||
| $alias_key = self::sanitize_placeholder_name( $slug ); | ||
| if ('' === $alias_key) { | ||
| $alias_key = self::sanitize_placeholder_name($slug); | ||
| } | ||
| $data_type = isset( $def['data_type'] ) ? sanitize_key( $def['data_type'] ) : 'text'; | ||
| $type = isset( $def['type'] ) ? sanitize_key( $def['type'] ) : 'textarea'; | ||
| $data_type = isset($def['data_type']) ? sanitize_key($def['data_type']) : 'text'; | ||
| $type = isset($def['type']) ? sanitize_key($def['type']) : 'textarea'; | ||
|
|
||
| if ( 'array' === $type ) { | ||
| $items = self::get_array_field_items_for_merge( $structured, $slug, $post_id ); | ||
| if ('array' === $type) { | ||
| $items = self::get_array_field_items_for_merge($structured, $slug, $post_id); | ||
|
|
||
| // Apply case transformations to repeater items. | ||
| $item_schema = isset( $def['item_schema'] ) ? $def['item_schema'] : array(); | ||
| $items = self::apply_case_to_array_items( $items, $item_schema ); | ||
| $item_schema = isset($def['item_schema']) ? $def['item_schema'] : array(); | ||
| $items = self::apply_case_to_array_items($items, $item_schema); | ||
|
|
||
| // Use block name for MergeBlock, with alias for legacy behavior. | ||
| $fields[ $tbs_name ] = $items; | ||
| if ( $alias_key !== $tbs_name ) { | ||
| $fields[ $alias_key ] = $items; | ||
| $fields[$tbs_name] = $items; | ||
| if ($alias_key !== $tbs_name) { | ||
| $fields[$alias_key] = $items; | ||
| } | ||
| self::remember_rich_values_from_array_items( $items ); | ||
| self::remember_rich_values_from_array_items($items); | ||
| continue; | ||
| } | ||
|
|
||
| $value = self::get_structured_field_value( $structured, $slug, $post_id ); | ||
| $value = self::get_structured_field_value($structured, $slug, $post_id); | ||
| // Force rich type if value contains block HTML, BEFORE prepare strips tags. | ||
| $original_type = $type; | ||
| if ( ! in_array( $type, array( 'rich', 'html' ), true ) && Documents_Meta_Handler::value_contains_block_html( $value ) ) { | ||
| if (!in_array($type, array('rich', 'html'), true) && Documents_Meta_Handler::value_contains_block_html($value)) { | ||
| $type = 'rich'; | ||
| } | ||
| $prepared = self::prepare_field_value( $value, $type, $data_type, $def ); | ||
| $prepared = self::prepare_field_value($value, $type, $data_type, $def); | ||
|
|
||
| // Apply case transformation if specified (skip for HTML content). | ||
| $field_case = isset( $def['case'] ) ? sanitize_key( $def['case'] ) : ''; | ||
| if ( '' !== $field_case && ! in_array( $type, array( 'rich', 'html' ), true ) ) { | ||
| $prepared = self::apply_case_transformation( $prepared, $field_case ); | ||
| $field_case = isset($def['case']) ? sanitize_key($def['case']) : ''; | ||
| if ('' !== $field_case && !in_array($type, array('rich', 'html'), true)) { | ||
| $prepared = self::apply_case_transformation($prepared, $field_case); | ||
| } | ||
|
|
||
| $fields[ $tbs_name ] = $prepared; | ||
| if ( $alias_key !== $tbs_name ) { | ||
| $fields[ $alias_key ] = $prepared; | ||
| $fields[$tbs_name] = $prepared; | ||
| if ($alias_key !== $tbs_name) { | ||
| $fields[$alias_key] = $prepared; | ||
| } | ||
| // Register for rich text conversion if typed as rich/html. | ||
| // Also check if prepared value still contains HTML as a safety net. | ||
| $has_html_in_prepared = Documents_Meta_Handler::value_contains_block_html( $prepared ); | ||
| if ( in_array( $type, array( 'rich', 'html' ), true ) || $has_html_in_prepared ) { | ||
| self::remember_rich_field_value( $prepared ); | ||
| $has_html_in_prepared = Documents_Meta_Handler::value_contains_block_html($prepared); | ||
| if (in_array($type, array('rich', 'html'), true) || $has_html_in_prepared) { | ||
| self::remember_rich_field_value($prepared); | ||
| } | ||
| // Debug logging - enable with WP_DEBUG. | ||
| if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { | ||
| error_log( | ||
| sprintf( | ||
| 'DOCUMENTATE [%s]: schema_type=%s, effective_type=%s, raw_has_html=%s, prepared_has_html=%s, raw_len=%d, prep_len=%d', | ||
| $slug, | ||
| $original_type, | ||
| $type, | ||
| Documents_Meta_Handler::value_contains_block_html( $value ) ? 'YES' : 'NO', | ||
| $has_html_in_prepared ? 'YES' : 'NO', | ||
| strlen( $value ), | ||
| strlen( $prepared ) | ||
| ) | ||
| ); | ||
| if ( Documents_Meta_Handler::value_contains_block_html( $value ) && strlen( $value ) < 500 ) { | ||
| error_log( 'DOCUMENTATE [' . $slug . '] RAW: ' . substr( $value, 0, 300 ) ); | ||
| if (defined('WP_DEBUG') && WP_DEBUG) { | ||
| error_log(sprintf( | ||
| 'DOCUMENTATE [%s]: schema_type=%s, effective_type=%s, raw_has_html=%s, prepared_has_html=%s, raw_len=%d, prep_len=%d', | ||
| $slug, | ||
| $original_type, | ||
| $type, | ||
| Documents_Meta_Handler::value_contains_block_html($value) ? 'YES' : 'NO', | ||
| $has_html_in_prepared ? 'YES' : 'NO', | ||
| strlen($value), | ||
| strlen($prepared), | ||
| )); | ||
| if (Documents_Meta_Handler::value_contains_block_html($value) && strlen($value) < 500) { | ||
| error_log('DOCUMENTATE [' . $slug . '] RAW: ' . substr($value, 0, 300)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $logos = get_term_meta( $type_id, 'documentate_type_logos', true ); | ||
| if ( is_array( $logos ) && ! empty( $logos ) ) { | ||
| $i = 1; | ||
| foreach ( $logos as $att_id ) { | ||
| $att_id = intval( $att_id ); | ||
| if ( $att_id <= 0 ) { | ||
| continue; | ||
| $logos = get_term_meta($type_id, 'documentate_type_logos', true); | ||
| if (is_array($logos) && !empty($logos)) { | ||
| $i = 1; | ||
| foreach ($logos as $att_id) { | ||
| $att_id = intval($att_id); | ||
| if ($att_id <= 0) { | ||
| continue; | ||
| } | ||
| $fields[ 'logo' . $i . '_path' ] = get_attached_file( $att_id ); | ||
| $fields[ 'logo' . $i . '_url' ] = wp_get_attachment_url( $att_id ); | ||
| $i++; | ||
| $fields['logo' . $i . '_path'] = get_attached_file($att_id); | ||
| $fields['logo' . $i . '_url'] = wp_get_attachment_url($att_id); | ||
| $i++; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ( ! empty( $structured ) ) { | ||
| foreach ( $structured as $slug => $info ) { | ||
| $slug = sanitize_key( $slug ); | ||
| if ( '' === $slug ) { | ||
| continue; | ||
| if (!empty($structured)) { | ||
| foreach ($structured as $slug => $info) { | ||
| $slug = sanitize_key($slug); | ||
| if ('' === $slug) { | ||
| continue; | ||
| } | ||
| $placeholder = $slug; | ||
| if ( isset( $fields[ $placeholder ] ) && '' !== $fields[ $placeholder ] ) { | ||
| continue; | ||
| $placeholder = $slug; | ||
| if (isset($fields[$placeholder]) && '' !== $fields[$placeholder]) { | ||
| continue; | ||
| } | ||
| if ( isset( $info['type'] ) && 'array' === sanitize_key( $info['type'] ) ) { | ||
| $items = self::get_array_field_items_for_merge( $structured, $slug, $post_id ); | ||
| $fields[ $placeholder ] = $items; | ||
| self::remember_rich_values_from_array_items( $items ); | ||
| continue; | ||
| if (isset($info['type']) && 'array' === sanitize_key($info['type'])) { | ||
| $items = self::get_array_field_items_for_merge($structured, $slug, $post_id); | ||
| $fields[$placeholder] = $items; | ||
| self::remember_rich_values_from_array_items($items); | ||
| continue; | ||
| } | ||
|
|
||
| $value = ''; | ||
| if ( isset( $info['value'] ) ) { | ||
| $value = (string) $info['value']; | ||
| $value = ''; | ||
| if (isset($info['value'])) { | ||
| $value = (string) $info['value']; | ||
| } | ||
| if ( '' === $value ) { | ||
| $value = self::get_structured_field_value( $structured, $slug, $post_id ); | ||
| if ('' === $value) { | ||
| $value = self::get_structured_field_value($structured, $slug, $post_id); | ||
| } | ||
| $field_type = isset( $info['type'] ) ? sanitize_key( $info['type'] ) : 'rich'; | ||
| $field_type = isset($info['type']) ? sanitize_key($info['type']) : 'rich'; | ||
| // Force rich type if value contains block HTML, BEFORE prepare strips tags. | ||
| if ( ! in_array( $field_type, array( 'rich', 'html' ), true ) && Documents_Meta_Handler::value_contains_block_html( $value ) ) { | ||
| if ( | ||
| !in_array($field_type, array('rich', 'html'), true) && Documents_Meta_Handler::value_contains_block_html($value) | ||
| ) { | ||
| $field_type = 'rich'; | ||
| } | ||
| $fields[ $placeholder ] = self::prepare_field_value( $value, $field_type, 'text' ); | ||
| $fields[$placeholder] = self::prepare_field_value($value, $field_type, 'text'); | ||
| // Register for rich text conversion if typed as rich/html. | ||
| // Also check if prepared value still contains HTML as a safety net. | ||
| if ( in_array( $field_type, array( 'rich', 'html' ), true ) || Documents_Meta_Handler::value_contains_block_html( $fields[ $placeholder ] ) ) { | ||
| self::remember_rich_field_value( $fields[ $placeholder ] ); | ||
| if ( | ||
| in_array($field_type, array('rich', 'html'), true) | ||
| || Documents_Meta_Handler::value_contains_block_html($fields[$placeholder]) | ||
| ) { | ||
| self::remember_rich_field_value($fields[$placeholder]); | ||
| } | ||
| } | ||
| } |
Check warning
Code scanning / PHPMD
Code Size Rules: NPathComplexity Warning
| @@ -543,23 +534,23 @@ private function build_schema( $placeholders, $template_type, $template_path ) { | |||
| * @param array<string,mixed> $token Placeholder token. | |||
| * @return array<string,mixed> | |||
| */ | |||
| private function build_repeater_entry( $token ) { | |||
| $name = isset( $token['name'] ) ? (string) $token['name'] : ''; | |||
| $parameters = isset( $token['parameters'] ) ? $token['parameters'] : array(); | |||
| private function build_repeater_entry($token) { | |||
| $name = isset($token['name']) ? (string) $token['name'] : ''; | |||
| $parameters = isset($token['parameters']) ? $token['parameters'] : array(); | |||
|
|
|||
| $title = isset( $parameters['title'] ) ? sanitize_text_field( $parameters['title'] ) : ''; | |||
Check warning
Code scanning / PHPMD
Code Size Rules: NPathComplexity Warning
| @@ -639,35 +630,35 @@ private function build_field_entry( $token ) { | |||
| * @param string $text Normalized XML text. | |||
| * @return array<int,string> | |||
| */ | |||
| private function extract_placeholder_chunks( $text ) { | |||
| $chunks = array(); | |||
| $length = strlen( $text ); | |||
| $in_placeholder = false; | |||
| $buffer = ''; | |||
| $current_quote = null; | |||
| $previous_char = ''; | |||
|
|
|||
| for ( $i = 0; $i < $length; $i++ ) { | |||
| $char = $text[ $i ]; | |||
|
|
|||
| if ( $in_placeholder ) { | |||
| private function extract_placeholder_chunks($text) { | |||
| $chunks = array(); | |||
| $length = strlen($text); | |||
| $in_placeholder = false; | |||
| $buffer = ''; | |||
| $current_quote = null; | |||
| $previous_char = ''; | |||
Check warning
Code scanning / PHPMD
Code Size Rules: CyclomaticComplexity Warning
| @@ -639,35 +630,35 @@ private function build_field_entry( $token ) { | |||
| * @param string $text Normalized XML text. | |||
| * @return array<int,string> | |||
| */ | |||
| private function extract_placeholder_chunks( $text ) { | |||
| $chunks = array(); | |||
| $length = strlen( $text ); | |||
| $in_placeholder = false; | |||
| $buffer = ''; | |||
| $current_quote = null; | |||
| $previous_char = ''; | |||
|
|
|||
| for ( $i = 0; $i < $length; $i++ ) { | |||
| $char = $text[ $i ]; | |||
|
|
|||
| if ( $in_placeholder ) { | |||
| private function extract_placeholder_chunks($text) { | |||
| $chunks = array(); | |||
| $length = strlen($text); | |||
| $in_placeholder = false; | |||
| $buffer = ''; | |||
| $current_quote = null; | |||
| $previous_char = ''; | |||
Check warning
Code scanning / PHPMD
Code Size Rules: NPathComplexity Warning
| @@ -87,53 +97,57 @@ public function render( WP_Post $post ) { | |||
| * @param bool $update Whether this is an existing post being updated. | |||
| * @return void | |||
| */ | |||
| public function save( $post_id, $post = null, $update = false ) { | |||
| unset( $update ); | |||
| public function save($post_id, $post = null, $update = false) { | |||
| unset($update); | |||
|
|
|||
| if ( ! isset( $_POST[ self::NONCE_NAME ] ) ) { | |||
| if (!isset($_POST[self::NONCE_NAME])) { | |||
| return; | |||
| } | |||
|
|
|||
| $nonce = sanitize_text_field( wp_unslash( $_POST[ self::NONCE_NAME ] ) ); | |||
| if ( ! wp_verify_nonce( $nonce, self::NONCE_ACTION ) ) { | |||
| $nonce = sanitize_text_field(wp_unslash($_POST[self::NONCE_NAME])); | |||
| if (!wp_verify_nonce($nonce, self::NONCE_ACTION)) { | |||
| return; | |||
| } | |||
|
|
|||
| if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { | |||
| if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { | |||
| return; | |||
| } | |||
|
|
|||
| if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) { | |||
| if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { | |||
| return; | |||
| } | |||
|
|
|||
| if ( ! current_user_can( 'edit_post', $post_id ) ) { | |||
| if (!current_user_can('edit_post', $post_id)) { | |||
| return; | |||
| } | |||
|
|
|||
| if ( null === $post ) { | |||
| $post = get_post( $post_id ); | |||
| if (null === $post) { | |||
| $post = get_post($post_id); | |||
| } | |||
|
|
|||
| if ( ! $post instanceof WP_Post ) { | |||
| if (!$post instanceof WP_Post) { | |||
| return; | |||
| } | |||
|
|
|||
| $title_source = get_post_field( 'post_title', $post_id, 'raw' ); | |||
| if ( ! is_string( $title_source ) || '' === $title_source ) { | |||
| $title_source = get_post_field('post_title', $post_id, 'raw'); | |||
| if (!is_string($title_source) || '' === $title_source) { | |||
| $title_source = $post->post_title; | |||
| } | |||
|
|
|||
| $title_raw = sanitize_text_field( (string) $title_source ); | |||
| $subject = $this->sanitize_limited_text( $title_raw, 255 ); | |||
| $author_input = isset( $_POST['documentate_document_meta_author'] ) ? sanitize_text_field( wp_unslash( $_POST['documentate_document_meta_author'] ) ) : ''; | |||
| $author = $this->sanitize_limited_text( $author_input, 255 ); | |||
| $keywords_raw = isset( $_POST['documentate_document_meta_keywords'] ) ? sanitize_text_field( wp_unslash( $_POST['documentate_document_meta_keywords'] ) ) : ''; | |||
| $keywords = $this->sanitize_keywords( $keywords_raw ); | |||
|
|
|||
| $this->persist_meta( $post_id, self::META_KEY_SUBJECT, $subject ); | |||
| $this->persist_meta( $post_id, self::META_KEY_AUTHOR, $author ); | |||
| $this->persist_meta( $post_id, self::META_KEY_KEYWORDS, $keywords ); | |||
| $title_raw = sanitize_text_field((string) $title_source); | |||
| $subject = $this->sanitize_limited_text($title_raw, 255); | |||
| $author_input = isset($_POST['documentate_document_meta_author']) | |||
| ? sanitize_text_field(wp_unslash($_POST['documentate_document_meta_author'])) | |||
Check warning
Code scanning / PHPMD
Code Size Rules: NPathComplexity Warning
| * @param string $input_type Input type being rendered. | ||
| * @return array<string,string> | ||
| */ | ||
| public static function build_scalar_input_attributes( $raw_field, $input_type ) { | ||
| $attributes = array(); | ||
| $input_type = sanitize_key( $input_type ); | ||
| $allows_placeholder = ! in_array( $input_type, array( 'checkbox', 'select' ), true ); | ||
| public static function build_scalar_input_attributes($raw_field, $input_type) { | ||
| $attributes = array(); | ||
| $input_type = sanitize_key($input_type); | ||
| $allows_placeholder = !in_array($input_type, array('checkbox', 'select'), true); | ||
|
|
||
| if ( ! is_array( $raw_field ) ) { | ||
| if (!is_array($raw_field)) { | ||
| return $attributes; | ||
| } | ||
|
|
||
| if ( $allows_placeholder && ! empty( $raw_field['placeholder'] ) ) { | ||
| $attributes['placeholder'] = sanitize_text_field( $raw_field['placeholder'] ); | ||
| if ($allows_placeholder && !empty($raw_field['placeholder'])) { | ||
| $attributes['placeholder'] = sanitize_text_field($raw_field['placeholder']); | ||
| } | ||
|
|
||
| if ( $allows_placeholder && ! empty( $raw_field['pattern'] ) ) { | ||
| if ($allows_placeholder && !empty($raw_field['pattern'])) { | ||
| $attributes['pattern'] = (string) $raw_field['pattern']; | ||
| } | ||
|
|
||
| if ( $allows_placeholder && isset( $raw_field['length'] ) ) { | ||
| $length = intval( $raw_field['length'] ); | ||
| if ( $length > 0 ) { | ||
| if ($allows_placeholder && isset($raw_field['length'])) { | ||
| $length = intval($raw_field['length']); | ||
| if ($length > 0) { | ||
| $attributes['maxlength'] = (string) $length; | ||
| } | ||
| } | ||
|
|
||
| $numeric_types = array( 'number', 'range', 'date', 'datetime-local', 'time' ); | ||
| $numeric_types = array('number', 'range', 'date', 'datetime-local', 'time'); | ||
|
|
||
| if ( isset( $raw_field['minvalue'] ) && in_array( $input_type, $numeric_types, true ) ) { | ||
| if (isset($raw_field['minvalue']) && in_array($input_type, $numeric_types, true)) { | ||
| $attributes['min'] = (string) $raw_field['minvalue']; | ||
| } | ||
|
|
||
| if ( isset( $raw_field['maxvalue'] ) && in_array( $input_type, $numeric_types, true ) ) { | ||
| if (isset($raw_field['maxvalue']) && in_array($input_type, $numeric_types, true)) { | ||
| $attributes['max'] = (string) $raw_field['maxvalue']; | ||
| } | ||
|
|
||
| self::add_parameter_attributes( $raw_field, $input_type, $attributes ); | ||
| self::add_parameter_attributes($raw_field, $input_type, $attributes); | ||
|
|
||
| // Add title attribute from pattern message or field title. | ||
| if ( ! isset( $attributes['title'] ) ) { | ||
| $title_attribute = self::get_field_pattern_message( $raw_field ); | ||
| if ( '' === $title_attribute ) { | ||
| $title_attribute = self::get_field_title( $raw_field ); | ||
| if (!isset($attributes['title'])) { | ||
| $title_attribute = self::get_field_pattern_message($raw_field); | ||
| if ('' === $title_attribute) { | ||
| $title_attribute = self::get_field_title($raw_field); | ||
| } | ||
| if ( '' !== $title_attribute ) { | ||
| if ('' !== $title_attribute) { | ||
| $attributes['title'] = $title_attribute; | ||
| } |
Check warning
Code scanning / PHPMD
Code Size Rules: CyclomaticComplexity Warning
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
This pull request introduces a major refactor of the document workflow UI and backend logic, streamlining the document management experience for both admins and editors. The legacy WordPress "submitdiv" is replaced with a custom Document Management meta box, and workflow actions (draft, review, publish, revert) are now handled by dedicated buttons. The code removes complex status restriction logic and legacy UI hiding, centralizing all workflow controls in the new meta box. End-to-end tests and CSS are updated to reflect these changes.
Workflow UI and Logic Refactor
Replaces the legacy WordPress "submitdiv" with a unified Document Management meta box, removing all related status restriction, visibility, and scheduling logic from
documentate-workflow.jsand backend code. All workflow actions (save draft, send to review, approve & publish, return to draft/review, save pending) are now handled by custom buttons, with backend hooks and CSS updated accordingly. [1] [2] [3] [4] [5] [6]Removes legacy meta box controls and CSS hiding for submit box elements, including visibility options and scheduling UI, from the backend (
class-documentate-documents.php). [1] [2] [3]UI/UX Improvements
Adds a compact download row for document export buttons in the Document Management meta box, with improved styling via new CSS classes (
documentate-download-row,documentate-download-label). [1] [2] [3]Moves the actions meta box to a more prominent position (
'core'context instead of'high'), and updates the supported features for the custom post type to include comments. [1] [2]End-to-End Test Updates
Workflow State Notices
These changes modernize and simplify the document workflow, making it easier for users to manage document states and for developers to maintain the codebase.