如何将静态的 gutenberg 块转换为使用 PHP 注册的动态块?

问题描述 投票:0回答:2

我正在尝试将为 WordPress 创建的静态古腾堡块转换为动态块。我已经寻找其他解决方案,但没有成功。这个问题(将使用@wordpress/create-block创建的静态gutenberg块转换为使用PHP注册的动态块的正确方法是什么?)与我正在寻找的非常相似,但我的静态块不是使用 @wordpress/create-block 制作,在完成所有建议的步骤后,我看到了似乎是弃用问题。

class-hello-tools-custom-blocks.php(注册块)

静态版本如下所示:

register_block_type( 'hello-tools/custom-cta', array(
    'style' => $this->plugin_slug . '-public',
    'editor_style' => 'hello-gutenberg-admin',
    'editor_script' => $this->plugin_slug . '-custom-blocks',
) );

动态变化如下:

register_block_type( __DIR__ . '/src/js/blocks/custom-cta/custom-cta-block.json', array(
    'style' => $this->plugin_slug . '-public',
    'editor_style' => 'hello-gutenberg-admin',
    'editor_script' => $this->plugin_slug . '-custom-blocks',
    'render_callback' => array( $this, 'hello_tools_custom_cta_callback' )
) );

同一插件文件中的回调函数如下所示:

public function hello_tools_custom_cta_callback( $attributes, $content ) {
    ob_start();
    require plugin_dir_path( __DIR__ ) . 'includes/partials/block-callbacks/hello-custom-cta-callback.php';
    $output = ob_get_contents();
    ob_end_clean();
    return $output;
}

custom-cta-block.json(定义块属性)

如上面

register_block_type()
中所引用,这是 block.json 文件。

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 2,
    "name": "hello-tools/custom-cta",
    "title": "Custom CTA",
    "category": "hello-blocks",
    "icon": "align-center",
    "description": "Create call to action element with photo image, text, and button link",
    "keywords": [ "call", "action" ],
    "version": "1.0.1",
    "textdomain": "hello-tools",
    "editorScript": "hello-tools-custom-blocks",
    "editorStyle": "hello-gutenberg-admin",
    "style": "hello-tools-public",
    "attributes": {
        "switchOrientation": {
            "type": "boolean",
            "default": false
        },
        "imageID": {
            "type": "integer"
        },
        "imageURL": {
            "type": "string"
        },
        "imageALT": {
            "type": "string",
            "default": ""
        },
        "imageBgColor": {
            "type": "string",
            "default": "orange"
        },
        "hideCTAImageOnMobile": {
            "type": "boolean",
            "default": false
        },
        "renderWithoutImageBg": {
            "type": "boolean",
            "default": false
        },
        "imageRatio": {
            "type": "string",
            "default": "golden"
        },
        "textBgColor": {
            "type": "string",
            "default": "faint-gray"
        },
        "hasIcon": {
            "type": "boolean",
            "default": false
        },
        "iconID": {
            "type": "integer"
        },
        "iconURL": {
            "type": "string"
        },
        "iconALT": {
            "type": "string",
            "default": ""
        },
        "hasSuperHeading": {
            "type": "boolean",
            "default": false
        },
        "superHeading": {
            "type": "string"
        },
        "headline": {
            "type": "string"
        },
        "blurb": {
            "type": "string"
        },
        "ctaButtonText": {
            "type": "string"
        },
        "ctaLinkURL": {
            "type": "string"
        },
        "textClasses": {
            "type": "string",
            "default": "hello-custom-cta__description flex-fill hello-flex hello-flex--fixed-size align-self-stretch align-items-center p-3 p-sm-4 p-lg-5"
        },
        "blockClasses": {
            "type": "string",
            "default": "hello-block--fullwidth px-sm-3 mb-5 mb-md-6 mb-lg-7 mb-7"
        }
    },
    "supports": {
        "multiple": true
    },
    "example": {
        "attributes": {
            "headline": "This is a custom CTA!",
            "blurb": "<p>Add a catchy headline and body text to capture people's attention</p>",
            "ctaButtonText": "Click here"
        }
    }
}

自定义-cta.js

原来的

save()
函数已被删除,以告诉 Wordpres 它应该动态渲染,但之前的弃用版本已保持不变。

import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { InspectorControls, MediaUpload, MediaUploadCheck, RichText, URLInput } from '@wordpress/blockEditor';
import { Button, PanelBody, TextControl, TextareaControl, ToggleControl, SelectControl, IconButton } from '@wordpress/components';
import { omit } from 'lodash';
import settings from './custom-cta-block.json';
const blockAttributes = settings.attributes;

registerBlockType( settings, {

  edit: ( props ) => {

    const { attributes: { switchOrientation, imageID, imageURL, imageALT, imageBgColor, imageRatio, hideCTAImageOnMobile, textBgColor, hasIcon, iconID, iconURL, iconALT, hasSuperHeading, superHeading, headline, blurb, ctaButtonText, ctaLinkURL, blockClasses, textClasses, renderWithoutImageBg }, setAttributes, className, isSelected } = props;
    const ctaButtonPlaceholderText = __( "Button text", "hello-tools" );
    const flexClasses = `hello-flex hello-wrap--content align-items-center ${switchOrientation && 'switch-orientation'}`;

    const onImageSelect = ( imageObj ) => {

      // use the medium_large image size of it exists, otherwise use the full-size image
      const imageObjURL = ( imageObj.sizes.medium_large ) ? imageObj.sizes.medium_large.url : imageObj.sizes.full.url;
      
      // set the image attributes
      setAttributes( { imageID: imageObj.id } );
      setAttributes( { imageURL: imageObjURL } );
      setAttributes( { imageALT: imageObj.alt } );
    
    }

    const onImageBgChange = ( value ) => {
      setAttributes( { imageBgColor: value } );
      setAttributes( { renderWithoutImageBg: ( value == 'none') ? true : false } );
    }

    const onIconSelectorChange = ( value ) => {
      setAttributes( { hasIcon: value } );
      
      // clear icon image attributes if show icon toggle is changed to false
      if ( !value ) {
        setAttributes( { iconID: '' } );
        setAttributes( { iconURL: '' } );
        setAttributes( { iconALT: '' } );
      }

    }

    const onIconSelect = ( imageObj ) => {
      setAttributes( { iconID: imageObj.id } );

      if ( imageObj.sizes.thumbnail ) {
        setAttributes( { iconURL: imageObj.sizes.thumbnail.url } );  
      } else {
        setAttributes( { iconURL: imageObj.sizes.full.url } );
      }

      setAttributes( { iconALT: imageObj.alt } );
    }

    return (
      <div className="hello-custom-cta-editor p-0 mb-0">
        <InspectorControls>
          <PanelBody
            title={ __( 'Image settings', 'hello-tools' ) }
            initialOpen={ true }
          >
            { imageID && __( 'You can change the CTA image here', 'hello-tools' ) }
            { imageID && (
              <div style={{ margin: '0 0 15px 0', }}>
                <MediaUploadCheck>
                  <MediaUpload
                    onSelect={ onImageSelect }
                    allowedTypes="image"
                    value={ imageID }
                    render={ ( { open } ) => (
                      <Button className="hello-components-button" onClick={ open }>
                        { __( 'Choose new image', 'hello-tools' ) }
                      </Button>
                    ) }
                  />
                </MediaUploadCheck>
              </div>
            ) }
            <SelectControl
              label={ __( 'Image background color', 'hello-tools' ) }
              value={ imageBgColor }
              onChange={ onImageBgChange }
              options={ [
                  { value: 'orange', label: __( 'Orange', 'hello-tools' ) },
                  { value: 'blue', label: __( 'Blue', 'hello-tools' ) },
                  { value: 'powder-blue', label: __( 'Light blue', 'hello-tools' ) },
                  { value: 'faint-gray', label: __( 'Gray', 'hello-tools' ) },
                  { value: 'green', label: __( 'Green', 'hello-tools' ) },
                  { value: 'none', label: __( 'No background color', 'hello-tools' ) },
              ] }
            />
            <SelectControl
              label={ __( 'Image ratio', 'hello-tools' ) }
              value={ imageRatio }
              onChange={ value => setAttributes( { imageRatio: value } ) }
              options={ [
                  { value: 'golden', label: '16:9' },
                  { value: 'half', label: '1:1' },
              ] }
            />
            <ToggleControl
              label={ __( 'Hide image on mobile phones?', 'hello-tools' ) }
              checked={ hideCTAImageOnMobile }
              onChange={ value => setAttributes( { hideCTAImageOnMobile: value } ) }
            />
            <ToggleControl
              label={ __( 'Move photo to the right of the text?', 'hello-tools' ) }
              help='The default is to have the photo to the left of the text, but you can switch it here.'
              checked={ switchOrientation }
              onChange={ value => setAttributes( { switchOrientation: value } ) }
            />
          </PanelBody>
          <PanelBody
            title={ __( 'Text settings', 'hello-tools' ) }
            initialOpen={ true }
          >
            <SelectControl
              label={ __( 'Background color', 'hello-tools' ) }
              value={ textBgColor }
              onChange={ value => setAttributes( { textBgColor: value } ) }
              options={ [
                  { value: 'faint-gray', label: __( 'Gray', 'hello-tools' ) },
                  { value: 'white', label: __( 'White', 'hello-tools' ) },
              ] }
            />
            <ToggleControl
              label={ __( 'Show icon above the text?', 'hello-tools' ) }
              checked={ hasIcon }
              onChange={ onIconSelectorChange }
            />
            { hasIcon && (
              <div style={{ margin: '-15px 0 15px 0', }}>
                <MediaUploadCheck>
                  <MediaUpload
                    onSelect={ onIconSelect }
                    allowedTypes="image"
                    value={ iconID }
                    render={ ( { open } ) => (
                      <Button className="hello-components-button" onClick={ open }>
                        { !iconID && __( 'Choose icon image', 'hello-tools' ) }
                        { iconID && __( 'Replace icon image', 'hello-tools' ) }
                      </Button>
                    ) }
                  />
                </MediaUploadCheck>
              </div>
            ) }
            <ToggleControl
              label={ __( 'Show super heading?', 'hello-tools' ) }
              checked={ hasSuperHeading }
              onChange={ value => setAttributes( { hasSuperHeading: value } ) }
            />
          </PanelBody>
        </InspectorControls>
        <div className={ flexClasses }>
          { renderWithoutImageBg && imageURL && (
          <div className={ `hello-custom-cta__image-wrap ${imageRatio} no-padding hello-flex align-self-stretch align-items-center` }>
            <div className="objectfit__container w-100 h-100">
              <img className="hello-custom-cta__image objectfit__image w-100 h-100" src={ imageURL }  alt={ imageALT } />
            </div>
          </div>
          ) }
          { !renderWithoutImageBg && imageURL && (
          <div className={ `hello-custom-cta__image-wrap ${imageRatio} hello-bg--${imageBgColor} hello-flex align-self-stretch align-items-center p-sm-4 p-lg-5` }>
            <img className="hello-custom-cta__image" src={ imageURL } alt={ imageALT } />
          </div>
          ) }
          { !renderWithoutImageBg && !imageID && (
            <MediaUploadCheck>
              <MediaUpload
                onSelect={ onImageSelect }
                allowedTypes="image"
                value={ imageID }
                render={ ( { open } ) => (
                  <Button onClick={ open }>
                    { __( 'Choose Image', 'hello-tools' ) }
                  </Button>
                ) }
              />
            </MediaUploadCheck>
          ) }
          <div className={ `${textClasses} hello-bg--${textBgColor}` }>
            <div>
              { hasIcon && iconID && (
                <div className="flex-item--fullwidth">
                  <img className="hello-custom-cta__icon circle d-block mx-auto" src={ iconURL } alt={ iconALT } />
                </div>
              ) }
              { hasSuperHeading && (
                <TextControl
                  className="hello-custom-cta__superheading hello-interactive-input"
                  value={ superHeading }
                  onChange={ value => setAttributes( { superHeading: value } ) }
                  placeholder={ __( 'Add super heading here (optional)', 'hello-tools' ) }
                  allowedFormats={ [] }
                />
              ) }
              <TextareaControl
                className="hello-custom-cta__headline w-100 hello-interactive-input font-weight-bold"
                value={ headline }
                onChange={ value => setAttributes( { headline: value } ) }
                placeholder={ __( 'Add CTA headline here', 'hello-tools' ) }
                allowedFormats={ [] }
                rows="2"
              />
              { ( isSelected || ( blurb && blurb != '<p></p>' ) ) && ( 
                <div className="w-100">
                  <RichText
                    tagName="div"
                    multiline="p"
                    className="hello-custom-cta__blurb font-weight-light mt-0 w-100"
                    translate-name="blurb"
                    onChange={ value => setAttributes( { blurb: value } ) }
                    placeholder={ __( 'Subtext goes here (optional)', 'hello-tools' ) }
                    value={ blurb }
                    allowedFormats={ [ 'core/bold', 'core/italic' ] }
                    focusOnInsert={ false }
                  />
                </div>
              ) }
              <div className="hello-tools-editable-btn-text-wrapper">
                <div className="hello-inline-flex">
                  <RichText
                    tagName="div"
                    placeholder={ ctaButtonPlaceholderText }
                    onFocus={ (e) => e.target.placeholder = "" } 
                    value={ ctaButtonText }
                    onChange={ value => setAttributes( { ctaButtonText: value } ) }
                    className="hello-tools-editable-btn-text mt-4 hello-btn hello-btn--blue"
                    withoutInteractiveFormatting
                    allowedFormats={ [] }
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
        { isSelected && (
          <div className="hello-block-post-selector">  
            <form
              key={ "form-link" }
              onSubmit={ ( event ) => event.preventDefault() }
              className="hello-flex hello-bg--white">
              <URLInput
                value={ ctaLinkURL }
                onChange={ value => setAttributes( { ctaLinkURL: value } ) }
                autoFocus={ false }
              />
              <IconButton
                className="hello-bg--white"
                icon={ "editor-break" }
                label={ __( "Apply", "hello-tools" ) }
                type={ "submit" }
              />
            </form>
          </div>
        ) }
      </div>
    );

  },

  save() {
    return null; // Data is rendered via PHP callback
  },

  deprecated: [
    {
      attributes: { ...blockAttributes },

      save( { attributes } ) {

        const { switchOrientation, imageID, imageURL, imageALT, imageBgColor, imageRatio, hideCTAImageOnMobile, textBgColor, hasIcon, iconID, iconURL, iconALT, hasSuperHeading, superHeading, headline, blurb, ctaButtonText, ctaLinkURL, blockClasses, textClasses, renderWithoutImageBg } = attributes;
        const flexClasses = `hello-flex hello-wrap--content align-items-center ${switchOrientation && 'switch-orientation'}`;
        const superHeadingExtraClasses = ( hasIcon && iconID ) ? 'mt-2 ' : '';
        const hideImageOnPhones = ( hideCTAImageOnMobile ) ? ' d-upto-md-none' : '';

        return (
          <div className={ blockClasses }>
            <div className="hello-wrap--narrow">
              <div className={ flexClasses }
                >
                { renderWithoutImageBg && imageURL && (
                <div className={ `hello-custom-cta__image-wrap ${imageRatio} hello-flex align-self-stretch align-items-center${hideImageOnPhones}` }>
                  <div className="objectfit__container w-100 h-100">
                    <img className="hello-custom-cta__image objectfit__image w-100 h-100" src={ imageURL }  alt={ imageALT } />
                  </div>
                </div>
                ) }
                { !renderWithoutImageBg && imageURL && (
                <div className={ `hello-custom-cta__image-wrap ${imageRatio} hello-bg--${imageBgColor} hello-flex align-self-stretch align-items-center p-sm-4 p-lg-5${hideImageOnPhones}` }>
                  <img className="hello-custom-cta__image" src={ imageURL } alt={ imageALT } />
                </div>
                ) }
                <div className={ `${textClasses} hello-bg--${textBgColor}` }>
                  <div>
                    { iconID && (
                      <div className="flex-item--fullwidth">
                        <img className="hello-custom-cta__icon circle d-block mx-auto" src={ iconURL } alt={ iconALT } />
                      </div>
                    ) }
                    { hasSuperHeading && superHeading && (
                      <div translate-name="custom-cta__superheading" className={`${superHeadingExtraClasses}hello-custom-cta__superheading hello-1rem-text font-weight-bold text-uppercase hello-text--orange`}>
                        <span>{ superHeading }</span>
                      </div>
                    ) }
                    <div translate-name="custom-cta__headline" className="hello-custom-cta__headline h2 font-weight-bold my-2 my-md-3">
                      { headline }
                    </div>
                    { ( blurb && blurb != '<p></p>' ) && ( 
                      <RichText.Content 
                        className="hello-custom-cta__blurb" 
                        tagName="div" 
                        value={ blurb } 
                      />
                    ) }
                    { ctaButtonText && ctaLinkURL && (
                      <a href={ ctaLinkURL } translate-name="custom-cta__btn-link" className="hello-custom-cta__btn-link mb-3 mb-md-0 btn hello-btn hello-btn--blue">
                        { ctaButtonText }
                      </a>
                    ) }
                  </div>
                </div>
              </div>
            </div>          
          </div>
        )

      }

    },
    {
      attributes: { 
        ...blockAttributes, 
        blockClasses: {
          type: 'string',
          default: 'hello-block--fullwidth px-sm-3 mb-7',
        },
      },

      save( { attributes } ) {

        const { switchOrientation, imageID, imageURL, imageALT, imageBgColor, imageRatio, hideCTAImageOnMobile, textBgColor, hasIcon, iconID, iconURL, iconALT, hasSuperHeading, superHeading, headline, blurb, ctaButtonText, ctaLinkURL, blockClasses, textClasses, renderWithoutImageBg } = attributes;
        const flexClasses = `hello-flex hello-wrap--content align-items-center ${switchOrientation && 'switch-orientation'}`;
        const superHeadingExtraClasses = ( hasIcon && iconID ) ? 'mt-2 ' : '';
        const hideImageOnPhones = ( hideCTAImageOnMobile ) ? ' d-upto-md-none' : '';

        return (
          <div className={ blockClasses }>
            <div className="hello-wrap--narrow">
              <div className={ flexClasses }
                >
                { renderWithoutImageBg && imageURL && (
                <div className={ `hello-custom-cta__image-wrap ${imageRatio} hello-flex align-self-stretch align-items-center${hideImageOnPhones}` }>
                  <div className="objectfit__container w-100 h-100">
                    <img className="hello-custom-cta__image objectfit__image w-100 h-100" src={ imageURL }  alt={ imageALT } />
                  </div>
                </div>
                ) }
                { !renderWithoutImageBg && imageURL && (
                <div className={ `hello-custom-cta__image-wrap ${imageRatio} hello-bg--${imageBgColor} hello-flex align-self-stretch align-items-center p-sm-4 p-lg-5${hideImageOnPhones}` }>
                  <img className="hello-custom-cta__image" src={ imageURL } alt={ imageALT } />
                </div>
                ) }
                <div className={ `${textClasses} hello-bg--${textBgColor}` }>
                  <div>
                    { iconID && (
                      <div className="flex-item--fullwidth">
                        <img className="hello-custom-cta__icon circle d-block mx-auto" src={ iconURL } alt={ iconALT } />
                      </div>
                    ) }
                    { hasSuperHeading && superHeading && (
                      <div translate-name="custom-cta__superheading" className={`${superHeadingExtraClasses}hello-custom-cta__superheading hello-1rem-text font-weight-bold text-uppercase hello-text--orange`}>
                        <span>{ superHeading }</span>
                      </div>
                    ) }
                    <div translate-name="custom-cta__headline" className="hello-custom-cta__headline h2 font-weight-bold my-2 my-md-3">
                      { headline }
                    </div>
                    { ( blurb && blurb != '<p></p>' ) && ( 
                      <RichText.Content 
                        className="hello-custom-cta__blurb" 
                        tagName="div" 
                        value={ blurb } 
                      />
                    ) }
                    { ctaButtonText && ctaLinkURL && (
                      <a href={ ctaLinkURL } translate-name="custom-cta__btn-link" className="hello-custom-cta__btn-link mb-3 mb-md-0 btn hello-btn hello-btn--blue no-external-icon same-window">
                        { ctaButtonText }
                      </a>
                    ) }
                  </div>
                </div>
              </div>
            </div>          
          </div>
        )

      }

    }
  ],

} );

hello-custom-cta-callback.php(处理实际的PHP渲染,在回调函数中引用)

<?php
global $post;

$plugin_slug = hello_get_plugin_slug();
$is_admin = ( is_admin() ) ? true : false;

$switchOrientation = ( array_key_exists( 'switchOrientation', $attributes ) ) ? $attributes['switchOrientation'] : false;
$imageID = ( array_key_exists( 'imageID', $attributes ) ) ? $attributes['imageID'] : '';
$imageURL = ( array_key_exists( 'imageURL', $attributes ) ) ? $attributes['imageURL'] : '';
$imageALT = ( array_key_exists( 'imageALT', $attributes ) ) ? $attributes['imageALT'] : '';
$imageBgColor = ( array_key_exists( 'imageBgColor', $attributes ) ) ? $attributes['imageBgColor'] : 'orange';
$hideCTAImageOnMobile = ( array_key_exists( 'hideCTAImageOnMobile', $attributes ) ) ? $attributes['hideCTAImageOnMobile'] : false;
$renderWithoutImageBg = ( array_key_exists( 'renderWithoutImageBg', $attributes ) ) ? $attributes['renderWithoutImageBg'] : false;
$imageRatio = ( array_key_exists( 'imageRatio', $attributes ) ) ? $attributes['imageRatio'] : 'golden';
$textBgColor = ( array_key_exists( 'textBgColor', $attributes ) ) ? $attributes['textBgColor'] : 'faint-gray';
$hasIcon = ( array_key_exists( 'hasIcon', $attributes ) ) ? $attributes['hasIcon'] : false;
$iconID = ( array_key_exists( 'iconID', $attributes ) ) ? $attributes['iconID'] : '';
$iconURL = ( array_key_exists( 'iconURL', $attributes ) ) ? $attributes['iconURL'] : '';
$iconALT = ( array_key_exists( 'iconALT', $attributes ) ) ? $attributes['iconALT'] : '';
$hasSuperHeading = ( array_key_exists( 'hasSuperHeading', $attributes ) ) ? $attributes['hasSuperHeading'] : false;
$superHeading = ( array_key_exists( 'superHeading', $attributes ) ) ? $attributes['superHeading'] : '';
$headline = ( array_key_exists( 'headline', $attributes ) ) ? $attributes['headline'] : '';
$blurb = ( array_key_exists( 'blurb', $attributes ) ) ? $attributes['blurb'] : '';
$ctaButtonText = ( array_key_exists( 'ctaButtonText', $attributes ) ) ? $attributes['ctaButtonText'] : '';
$ctaLinkURL = ( array_key_exists( 'ctaLinkURL', $attributes ) ) ? $attributes['ctaLinkURL'] : '';
$textClasses = ( array_key_exists( 'textClasses', $attributes ) ) ? $attributes['textClasses'] : 'hello-custom-cta__description flex-fill hello-flex hello-flex--fixed-size align-self-stretch align-items-center p-3 p-sm-4 p-lg-5';
$blockClasses = ( array_key_exists( 'blockClasses', $attributes ) ) ? $attributes['blockClasses'] : 'hello-block--fullwidth px-sm-3 mb-5 mb-md-6 mb-lg-7 mb-7';
$flexClasses = 'hello-flex hello-wrap--content align-items-center';
$flexClasses = ($switchOrientation) ? $flexClasses . ' switch-orientation' : $flexClasses;
$superHeadingExtraClasses = ( $hasIcon && $iconID ) ? 'mt-2 ' : '';
$hideImageOnPhones = ( $hideCTAImageOnMobile ) ? ' d-upto-md-none' : '';

$is_rtl = ( apply_filters( 'wpml_is_rtl', NULL) ) ? true : false;
if ( is_object( $post ) && get_post_meta( $post->ID, '_icl_lang_duplicate_of', true ) ) { 
    $is_rtl = false; // if this is on a duplicate page, keep the content LTR
}

echo '<pre>'.print_r($attributes,true).'</pre>';
?>

<div class="<?= $blockClasses; ?>">
    <div class="hello-wrap--narrow">
        <div class="<?= $flexClasses; ?>">
            <?php if ($renderWithoutImageBg && $imageURL) : ?>
                <div class="hello-custom-cta__image-wrap <?= $imageRatio; ?> hello-flex align-self-stretch align-items-center<?= $hideImageOnPhones; ?>">
                    <div class="objectfit__container w-100 h-100">
                        <img class="hello-custom-cta__image objectfit__image w-100 h-100" src="<?= $imageURL; ?>"  alt="<?= $imageALT; ?>" />
                    </div>
                </div>
            <?php elseif ( !$renderWithoutImageBg && $imageURL ) : ?>
                <div class="hello-custom-cta__image-wrap <?= $imageRatio; ?> hello-bg--<?= $imageBgColor; ?> hello-flex align-self-stretch align-items-center p-sm-4 p-lg-5<?= $hideImageOnPhones; ?>">
                    <img class="hello-custom-cta__image" src="<?= $imageURL; ?>" alt="<?= $imageALT; ?>" />
                </div>
            <?php endif; ?>
            <div class="<?= $textClasses; ?> hello-bg--<?= $textBgColor; ?>">
              <div>
                <?php if ($iconID) : ?>
                <div class="flex-item--fullwidth">
                    <img class="hello-custom-cta__icon circle d-block mx-auto" src="<?= $iconURL; ?>" alt="<?= $iconALT; ?>" />
                </div>
                <?php endif; ?>
                <?php if ($hasSuperHeading && $superHeading) : ?>
                <div translate-name="custom-cta__superheading" class="<?= $superHeadingExtraClasses; ?>hello-custom-cta__superheading hello-1rem-text font-weight-bold text-uppercase hello-text--orange">
                    <span><?= $superHeading; ?></span>
                </div>
                <?php endif; ?>
                <div translate-name="custom-cta__headline" class="hello-custom-cta__headline h2 font-weight-bold my-2 my-md-3">
                    <?= $headline; ?>
                </div>
                <?php if ($blurb && $blurb !== '<p></p>') : ?>
                <div class="hello-custom-cta__blurb"><?= $blurb; ?></div>
                <?php endif; ?>
                <?php if ($ctaButtonText && $ctaLinkURL) : ?>
                <a href="<?= $ctaLinkURL; ?>" translate-name="custom-cta__btn-link" class="hello-custom-cta__btn-link mb-3 mb-md-0 btn hello-btn hello-btn--blue"><?= $ctaButtonText; ?></a>
                <?php endif; ?>
              </div>
            </div>
        </div>
    </div>
</div>
javascript php wordpress wordpress-gutenberg gutenberg-blocks
2个回答
2
投票

我注意到渲染回调中无法在 JavaScript 中完成的主要功能是检查

wpml_is_rtl
_icl_lang_duplicate_of
。为此,使用 PHP/动态渲染来获取该值是有意义的。尽管将原来的
save()
函数重写到 PHP 中,弃用前一个块然后从 PHP 中的属性重置所有变量似乎并不理想。最终目标是相同的输出:渲染的 HTML。我在将现有插件迁移到 Gutenberg 块时遇到了类似的问题,您实际上只需要一点点 PHP 功能即可在最终标记中获得正确的逻辑。

替代方法:

注册块后,可以使用 wp_localize_script 本地化块 JavaScript。这种方法的优点是您可以将值从 PHP 传递到 JavaScript

save()
,而不必仅仅为了访问 PHP 函数而重写所有标记。

class-hello-tools-custom-blocks.php

// Revert to original static block
register_block_type( 'hello-tools/custom-cta', array(
    'style' => $this->plugin_slug . '-public',
    'editor_style' => 'hello-gutenberg-admin',
    'editor_script' => $this->plugin_slug . '-custom-blocks',
) );

// Localize script with an array (data) containing the values of PHP functions as needed
function hello_tools_localize_scripts()
{
    $id = get_the_ID(); // Changed from $post->ID in this context

    $is_rtl = (apply_filters('wpml_is_rtl', NULL)) ? true : false;

    if (is_object($post) && get_post_meta($id, '_icl_lang_duplicate_of', true)) {
        $is_rtl = false; // if this is on a duplicate page, keep the content LTR
    }

    // Name of script is santized name from block.json
    wp_localize_script('hello-tools-custom-cta', 'data', array(
        'is_rtl' => $is_rtl,
        'is_admin' => is_admin()
    ));
}
add_action('wp_enqueue_scripts', 'hello_tools_localize_scripts');

自定义-cta.js

JavaScript 块现在可以访问

data
并使用其内容来保存所需的标记,例如:

save({ attributes }) {
   ...
   return (
       <div className={blockClasses}>
           {data.is_rtl && (
              // save something different for RTL
           )}
        ...
       </div>
   )
}
...

如果这就是最初导致您切换到使用 PHP 渲染的原因,那么希望您可以实现上面的建议,完全删除

hello-custom-cta-callback.php
,并使用附加变量重用现有的
save()
函数。

另请检查

custom-cta-block.json
的先前版本,了解先前如何定义属性。对于可编辑的 <RichText ../>
attributes
,该值可以来自保存的标记 - 您可以使用类选择器设置源,例如:

"attributes" :{
    ...
    "blurb": {
        "type": "string",
        "source": "text",
        "selector": ".hello-custom-cta__blurb",
        "default": ""
    },
...
}

0
投票

我尝试使用你的方法,但服务器端输出没有在我的前端页面中呈现,我不知道我做错了什么?

save: function (props) {
      return null;
    },

    deprecated: [
      {
        save: function (props) {
          return el(
            "form",
            {
              class: "intelius_simple_align_left_phone_form",
              action: "/redirect/impact.php",
              target: "_blank",
              method: "get",
            },
            el(
              "div",
              {
                class: "intelius_simple_align_left_phone_relavite",
              },
              el("input", {
                class: "intelius_simple_align_left_phone_input",
                type: "type",
                placeholder: "(212) 333-4567",
                onkeydown: "enforceFormatIntelius_value(event)",
                onkeyup: "formatToPhoneIntelius_value(event)",
                name: "phone",
                maxlength: "14",
              }),
              el("i", {
                class: "usa-flag-by-phone",
              }),
              el("input", {
                class: "intelius_simple_align_phone_btn",
                type: "submit",
                value: props.attributes.button_content,
              })
            ),
            el("input", {
              type: "hidden",
              name: "type",
              value: "phone",
            }),
            el("input", {
              type: "hidden",
              name: "merchant",
              value: "intelius",
            }),
            el("input", {
              type: "hidden",
              name: "source",
              value: "{{SUPEREASY_ARTICLE_URL}}",
            })
          );
        }
      }
    ]

// Register block script and style.
    register_block_type('easeware-intelius-simple-phone/simple-intelius-to-action', [
        // 'style' => 'simple-intelius-to-action', // Loads both on editor and frontend.
        'editor_script' => 'simple-intelius-to-action', // Loads only on editor.
        'editor_style' => 'simple-intelius-to-action', // Loads only on editor.
        'render_callback' => 'simple_intelius_render_form'
    ]);

function simple_intelius_render_form($attributes)
{
    return '
        <form class="intelius_simple_align_left_phone_form" action="/redirect/impact.php" target="_blank" method="get">
            <div class="intelius_simple_align_left_phone_relavite">
                <input class="intelius_simple_align_left_phone_input" type="type" placeholder="(212) 333-4567" name="phone" maxlength="14">
                <i class="usa-flag-by-phone"></i>
                <input class="intelius_simple_align_phone_btn" type="submit" value="' . esc_attr($attributes['button_content']) . '">
            </div>
            <input type="hidden" name="type" value="phone">
            <input type="hidden" name="merchant" value="intelius">
            <input type="hidden" name="source" value="{{SUPEREASY_ARTICLE_URL}}">
        </form>
    ';
}

© www.soinside.com 2019 - 2024. All rights reserved.