บทช่วยสอน Schema
บทช่วยสอน Schemaบทเรียนที่ 9: การแทรก/ลบบล็อก (Gutenberg) แบบกลุ่ม

บทเรียนที่ 9: การแทรก/ลบบล็อก (Gutenberg) แบบกลุ่ม

เราสามารถอัปเดตโพสต์ได้ด้วยการแก้ไขเนื้อหา HTML ของบล็อก (Gutenberg)

นอกเหนือจากกรณีการใช้งานอื่นๆ แล้ว สิ่งนี้มีประโยชน์สำหรับการโปรโมตแคมเปญ (เช่น เมื่อเสนอส่วนลดในช่วง Black Friday):

  • ก่อนแคมเปญ เราสร้างบล็อกแบบกำหนดเอง mycompany:black-friday-campaign-video พร้อม Call To Action ของเรา และทำการดำเนินการแบบกลุ่มเพื่อเพิ่มลงในทุกโพสต์ในเว็บไซต์
  • หลังแคมเปญ เราทำการดำเนินการแบบกลุ่มเพื่อลบบล็อกออกจากทุกโพสต์

เพื่อให้ GraphQL queries ในบทเรียนนี้ทำงานได้ Schema Configuration ที่ใช้กับ endpoint จำเป็นต้องเปิดใช้งาน Nested Mutations

การแทรกบล็อกแบบกลุ่ม

GraphQL query นี้จะระบุบล็อกย่อหน้าที่ 3 ในโพสต์ (โดยการค้นหา <!-- /wp:paragraph -->) และวางเนื้อหา HTML ของบล็อกแบบกำหนดเองไว้ทันทีหลังจากนั้น:

mutation InjectBlock(
  $limit: Int! = 5,
  $offset: Int! = 0
) {
  posts: posts(
    pagination: { limit: $limit, offset: $offset }
    sort: { by: ID, order: ASC }
  ) {
    id
    rawContent
    adaptedRawContent: _strRegexReplace(
      in: $__rawContent,
      searchRegex: "#(<!-- /wp:paragraph -->[\\s\\S]+<!-- /wp:paragraph -->[\\s\\S]+<!-- /wp:paragraph -->)#U",
      replaceWith: "$1<!-- mycompany:black-friday-campaign-video -->\n<figure class=\"wp-block-video\"><video controls src=\"https://mysite.com/videos/BlackFriday2023.mp4\"></video></figure>\n<!-- /mycompany:black-friday-campaign-video -->",
      limit: 1
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent },
    }) {
      status
      errors {
        __typename
        ...on ErrorPayload {
          message
        }
      }
      post {
        id
        rawContent
      }
    }
  }
}

การแทรกบล็อกพร้อมตัวเลือกเพิ่มเติม

GraphQL query นี้คล้ายกับอันก่อนหน้า แต่จะสร้าง regex แบบไดนามิก ทำให้เราสามารถระบุประเภทบล็อกที่จะค้นหา และจะวางบล็อกแบบกำหนดเองหลังจากบล็อกดังกล่าวกี่บล็อก:

query CreateRegex(
  $searchBlockType: String! = "wp:paragraph"
  $injectAfterBlockCount: Int!
  $injectBlockMarkup: String!
) {
  endingBlockMarkup: _sprintf(
    string: "<!-- /%s -->",
    values: [$searchBlockType]
  )
    @remove
  endingBlockMarkupArray: _arrayPad(
    array: [],
    length: $injectAfterBlockCount,
    value: $__endingBlockMarkup
  )
    @remove
  regexString: _arrayJoin(
    array: $__endingBlockMarkupArray,
    separator: "[\\s\\S]+"
  )
    @remove
  regex: _sprintf(
    string: "#(%s)#U",
    values: [$__regexString]
  )
    @export(as: "regex")
    @remove
  replaceWith: _sprintf(
    string: "$1%s",
    values: [$injectBlockMarkup]
  )
    @export(as: "replaceWith")
    @remove
}
 
mutation InjectBlock(
  $limit: Int! = 5,
  $offset: Int! = 0
  $times: Int! = 1
)
  @depends(on: "CreateRegex")
{
  posts: posts(
    pagination: { limit: $limit, offset: $offset }
    sort: { by: ID, order: ASC }
  ) {
    id
    rawContent
    adaptedRawContent: _strRegexReplace(
      in: $__rawContent,
      searchRegex: $regex,
      replaceWith: $replaceWith,
      limit: $times
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent },
    }) {
      status
      errors {
        __typename
        ...on ErrorPayload {
          message
        }
      }
      post {
        id
        rawContent
      }
    }
  }
}

เราระบุ dictionary variables แบบนี้:

{
  "injectBlockMarkup": "<!-- mycompany:black-friday-campaign-video -->\n<figure class=\"wp-block-video\"><video controls src=\"https://mysite.com/videos/BlackFriday2023.mp4\"></video></figure>\n<!-- /mycompany:black-friday-campaign-video -->",
  "injectAfterBlockCount": 3
}
  • ระหว่างการพัฒนา/ทดสอบ GraphQL query ให้พิมพ์รูปแบบ regex ในการตอบกลับด้วยการใส่ # ก่อนไดเรกทีฟ @remove (เพื่อคอมเมนต์ออก):
{
  field
    # @remove   <= Adding "#" before will disable the directive
}

การลบบล็อกแบบกลุ่ม

GraphQL query นี้จะค้นหาทุกโพสต์ที่มีบล็อกแบบกำหนดเอง และลบออกจากซอร์ส HTML ของโพสต์เหล่านั้น:

mutation RemoveBlock {
  posts(filter: { search: "\"<!-- /mycompany:black-friday-campaign-video -->\"" } ) {
    id
    rawContent
    adaptedRawContent: _strRegexReplace(
      in: $__rawContent,
      searchRegex: "#(<!-- mycompany:black-friday-campaign-video -->[\\s\\S]+<!-- /mycompany:black-friday-campaign-video -->)#",
      replaceWith: ""
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent },
    }) {
      status
      errors {
        __typename
        ...on ErrorPayload {
          message
        }
      }
      post {
        id
        rawContent
      }
    }
  }
}

การลบบล็อกพร้อมตัวเลือกเพิ่มเติม

GraphQL query นี้คล้ายกับอันก่อนหน้า แต่จะสร้าง regex แบบไดนามิก ทำให้เราสามารถระบุประเภทบล็อกที่จะลบได้:

query CreateVars(
  $removeBlockType: String!
) {
  regex: _sprintf(
    string: "#(<!-- %1$s -->[\\s\\S]+<!-- /%1$s -->)#",
    values: [$removeBlockType]
  )
    @export(as: "regex")
    @remove
 
  search: _sprintf(
    string: "\"<!-- /%1$s -->\"",
    values: [$removeBlockType]
  )
    @export(as: "search")
    @remove
}
 
mutation RemoveBlock
  @depends(on: "CreateVars")
{
  posts(filter: { search: $search } ) {
    id
    rawContent
    adaptedRawContent: _strRegexReplace(
      in: $__rawContent,
      searchRegex: $regex,
      replaceWith: ""
    )
    update(input: {
      contentAs: { html: $__adaptedRawContent },
    }) {
      status
      errors {
        __typename
        ...on ErrorPayload {
          message
        }
      }
      post {
        id
        rawContent
      }
    }
  }
}

เราระบุ dictionary variables แบบนี้:

{
  "removeBlockType": "mycompany:black-friday-campaign-video"
}