├── readme.txt
├── .editorconfig
├── .gitignore
├── package.json
├── readme.md
├── example-query-loop-button.php
└── src
└── index.js
/readme.txt:
--------------------------------------------------------------------------------
1 | === Example Query Loop Button ===
2 | Contributors: bacoords
3 | Tags: block
4 | Tested up to: 6.4.1
5 | Stable tag: 0.1.0
6 | License: GPL-2.0-or-later
7 | License URI: https://www.gnu.org/licenses/gpl-2.0.html
8 |
9 | Example block extension for the WordPress core/button block
10 |
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 |
4 | # WordPress Coding Standards
5 | # https://make.wordpress.org/core/handbook/coding-standards/
6 |
7 | root = true
8 |
9 | [*]
10 | charset = utf-8
11 | end_of_line = lf
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 | indent_style = tab
15 |
16 | [*.{yml,yaml}]
17 | indent_style = space
18 | indent_size = 2
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Coverage directory used by tools like istanbul
9 | coverage
10 |
11 | # Compiled binary addons (https://nodejs.org/api/addons.html)
12 | build/Release
13 |
14 | # Dependency directories
15 | node_modules/
16 |
17 | # Optional npm cache directory
18 | .npm
19 |
20 | # Optional eslint cache
21 | .eslintcache
22 |
23 | # Output of `npm pack`
24 | *.tgz
25 |
26 | # Output of `wp-scripts plugin-zip`
27 | *.zip
28 |
29 | # dotenv environment variables file
30 | .env
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-query-loop-button",
3 | "version": "0.1.0",
4 | "description": "Example block extension for the WordPress core/button block.",
5 | "author": "The WordPress Contributors",
6 | "license": "GPL-2.0-or-later",
7 | "main": "build/index.js",
8 | "scripts": {
9 | "build": "wp-scripts build",
10 | "format": "wp-scripts format",
11 | "lint:css": "wp-scripts lint-style",
12 | "lint:js": "wp-scripts lint-js",
13 | "packages-update": "wp-scripts packages-update",
14 | "plugin-zip": "wp-scripts plugin-zip",
15 | "start": "wp-scripts start"
16 | },
17 | "devDependencies": {
18 | "@wordpress/scripts": "^26.17.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Example Query Loop Button Extension
2 |
3 | Extends the button block to allow you to populate the `href` value automatically with the permalink or to a custom meta field. This is especially useful in the query loop, where you may want a custom button for your read more link.
4 |
5 | [🎥 The full tutorial](https://www.briancoords.com/adding-custom-fields-attributes-to-core-blocks/).
6 |
7 |
8 |
9 | This repo is part of a tutorial that teaches you how to:
10 |
11 | 1. Add custom attributes (aka custom fields) to a core block, and
12 | 2. Modify the final frontend markup of the block based on the attribute values
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example-query-loop-button.php:
--------------------------------------------------------------------------------
1 | next_tag( 'a' ) ) {
47 | $p->set_attribute( 'href', get_permalink() );
48 | $p->set_attribute( 'rel', 'bookmark' );
49 | $block_content = $p->get_updated_html();
50 | }
51 | }
52 | if ( isset( $block['attrs']['isPostLink'] ) && 'custom_field' === $block['attrs']['isPostLink'] && isset( $block['attrs']['customFieldName'] ) ) {
53 | $p = new WP_HTML_Tag_Processor( $block_content );
54 | if ( $p->next_tag( 'a' ) ) {
55 | $p->set_attribute( 'href', get_post_meta( get_the_ID(), $block['attrs']['customFieldName'], true ) );
56 | $block_content = $p->get_updated_html();
57 | }
58 | }
59 |
60 | return $block_content;
61 | }
62 | add_filter( 'render_block_core/button', __NAMESPACE__ . '\filter_button_block_render_block', 10, 2 );
63 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { addFilter } from "@wordpress/hooks";
2 | import { createHigherOrderComponent } from "@wordpress/compose";
3 | import { InspectorControls } from "@wordpress/block-editor";
4 | import {
5 | SelectControl,
6 | TextControl,
7 | PanelBody,
8 | PanelRow,
9 | } from "@wordpress/components";
10 | import { __ } from "@wordpress/i18n";
11 |
12 | /**
13 | * Add the attribute to the block.
14 | * This is the attribute that will be saved to the database.
15 | *
16 | * @param {object} settings block settings
17 | * @param {string} name block name
18 | * @returns {object} modified settings
19 | *
20 | * @see https://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#blocks-registerblocktype
21 | */
22 | addFilter(
23 | "blocks.registerBlockType",
24 | "wpdev/is-post-link",
25 | function (settings, name) {
26 | if (name !== "core/button") {
27 | return settings;
28 | }
29 |
30 | return {
31 | ...settings,
32 | attributes: {
33 | ...settings.attributes,
34 | isPostLink: {
35 | type: "string",
36 | default: "",
37 | },
38 | customFieldName: {
39 | type: "string",
40 | default: "",
41 | },
42 | },
43 | };
44 | }
45 | );
46 |
47 | /**
48 | * Edit component for the block.
49 | *
50 | * @param {object} props block props
51 | * @returns {JSX}
52 | */
53 | function Edit(props) {
54 | const setIsPostLink = (value) => {
55 | props.setAttributes({ isPostLink: value });
56 | };
57 |
58 | const setCustomFieldName = (value) => {
59 | props.setAttributes({ customFieldName: value });
60 | };
61 |
62 | return (
63 |
64 |
65 |
66 |
77 |
78 | {"custom_field" === props.attributes.isPostLink && (
79 |
80 |
86 |
87 | )}
88 |
89 |
90 | );
91 | }
92 |
93 | /**
94 | * Add the edit component to the block.
95 | * This is the component that will be rendered in the editor.
96 | * It will be rendered after the original block edit component.
97 | *
98 | * @param {function} BlockEdit Original component
99 | * @returns {function} Wrapped component
100 | *
101 | * @see https://developer.wordpress.org/block-editor/developers/filters/block-filters/#editor-blockedit
102 | */
103 | addFilter(
104 | "editor.BlockEdit",
105 | "wpdev/is-post-link",
106 | createHigherOrderComponent((BlockEdit) => {
107 | return (props) => {
108 | if (props.name !== "core/button") {
109 | return ;
110 | }
111 |
112 | return (
113 | <>
114 |
115 |
116 | >
117 | );
118 | };
119 | })
120 | );
121 |
--------------------------------------------------------------------------------