Skip to content

Commit e297181

Browse files
committed
feat: support generating meta boxes
- scaffold directory for custom meta box declarations - add script to generate meta box configs
1 parent 481c68a commit e297181

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

generators/meta-box.js

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
const { writeFileSync } = require('fs');
2+
const { join } = require('path');
3+
const prompts = require('prompts');
4+
5+
const getScriptTemplate = ({
6+
name,
7+
label,
8+
abstractClassName,
9+
boxIdentifier,
10+
postTypes,
11+
context,
12+
priority,
13+
}) => `<?php
14+
/**
15+
* File for setting up the ${name} meta box.
16+
*/
17+
18+
/**
19+
* Class that handles all functionality for the ${name} meta box.
20+
*/
21+
abstract class ${abstractClassName} {
22+
/**
23+
* Set up and add the meta box.
24+
*/
25+
public static function add() {
26+
/**
27+
* Set up basic details about the meta box.
28+
*
29+
* @see https://developer.wordpress.org/reference/functions/add_meta_box/
30+
*/
31+
add_meta_box(
32+
'${boxIdentifier}_id',
33+
'${name}',
34+
array( self::class, '${boxIdentifier}_html' ),
35+
array( ${postTypes.map((postType) => `'${postType}'`).join(', ')} ),
36+
'${context}',
37+
'${priority}',
38+
);
39+
}
40+
41+
/**
42+
* Save the meta box selections.
43+
*
44+
* @param int $post_id The post ID.
45+
*/
46+
public static function save( $post_id ) {
47+
if ( ! isset( $_POST['${boxIdentifier}_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['${boxIdentifier}_nonce'] ), basename( __FILE__ ) ) ) {
48+
return $post_id;
49+
}
50+
51+
$post = get_post( $post_id );
52+
$post_type = get_post_type_object( $post->post_type );
53+
if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) {
54+
return $post_id;
55+
}
56+
57+
if ( array_key_exists( '${boxIdentifier}', $_POST ) ) {
58+
update_post_meta(
59+
$post_id,
60+
'_${boxIdentifier}',
61+
sanitize_text_field( wp_unslash( $_POST['${boxIdentifier}'] ) )
62+
);
63+
}
64+
}
65+
66+
/**
67+
* Display the meta box HTML to the user.
68+
*
69+
* @param WP_Post $post Post object.
70+
*/
71+
public static function ${boxIdentifier}_html( $post ) {
72+
wp_nonce_field( basename( __FILE__ ), '${boxIdentifier}_nonce' );
73+
$value = get_post_meta( $post->ID, '_${boxIdentifier}', true );
74+
?>
75+
<div>
76+
<label for="${boxIdentifier}">${label}</label>
77+
<div>
78+
<input id="${boxIdentifier}" type="text" name="${boxIdentifier}" value="<?php echo esc_attr( $value ); ?>">
79+
</div>
80+
</div>
81+
<?php
82+
}
83+
}
84+
85+
add_action( 'add_meta_boxes', array( '${abstractClassName}', 'add' ) );
86+
add_action( 'save_post', array( '${abstractClassName}', 'save' ) );
87+
`;
88+
89+
const getDetails = async () => {
90+
const questions = [
91+
{
92+
type: 'text',
93+
name: 'name',
94+
message: 'What should the meta box be called?',
95+
},
96+
{
97+
type: 'text',
98+
name: 'label',
99+
message: 'What should be the label for the field?',
100+
},
101+
{
102+
type: 'list',
103+
name: 'postTypes',
104+
message:
105+
'Which post types should this meta box be enabled for? Enter post type slugs separated by commas (the slugs should match the first argument used in register_post_type).',
106+
initial: 'post',
107+
separator: ',',
108+
},
109+
{
110+
type: 'select',
111+
name: 'context',
112+
message: 'In which context should the box be displayed by default? (It can be moved by admins later)',
113+
choices: [
114+
{
115+
title: 'side (in the sidebar)',
116+
value: 'side',
117+
},
118+
{
119+
title: 'normal (below the post body)',
120+
value: 'normal',
121+
},
122+
{
123+
title: 'advanced (below the post body and "normal" meta boxes)',
124+
value: 'advanced',
125+
},
126+
],
127+
initial: 0,
128+
},
129+
{
130+
type: 'select',
131+
name: 'priority',
132+
message:
133+
'What priority level should be used for placing this box by default? (It can be moved by admins later)',
134+
choices: [
135+
{
136+
title: 'high',
137+
value: 'high',
138+
},
139+
{
140+
title: 'core',
141+
value: 'core',
142+
},
143+
{
144+
title: 'default',
145+
value: 'default',
146+
},
147+
{
148+
title: 'low',
149+
value: 'low',
150+
},
151+
],
152+
initial: 2,
153+
},
154+
];
155+
156+
const response = await prompts(questions);
157+
158+
return response;
159+
};
160+
161+
const generatePageTemplate = async () => {
162+
const { name, label, postTypes, context, priority } = await getDetails();
163+
const abstractClassName = name.replace(/\W/g, '_');
164+
const boxIdentifier = name.toLowerCase().replace(/\W/g, '_');
165+
const templateDetails = { name, label, abstractClassName, boxIdentifier, postTypes, context, priority };
166+
167+
const scriptTemplate = getScriptTemplate(templateDetails);
168+
169+
const fileName = `class-${name.toLowerCase().replace(/\W/g, '-')}`;
170+
const scriptPath = join(__dirname, '../src/php/inc/meta-boxes', `${fileName}.php`);
171+
172+
writeFileSync(scriptPath, scriptTemplate, 'utf-8');
173+
console.log(`Created ${scriptPath}`);
174+
};
175+
176+
generatePageTemplate();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"preimport:uploads": "npm run backup:uploads",
4545
"generate:custom-block": "node ./generators/custom-block.js",
4646
"generate:custom-blocks-plugin": "node ./generators/custom-blocks-plugin.js",
47+
"generate:meta-box": "node ./generators/meta-box.js",
4748
"generate:page-template": "node ./generators/page-template.js",
4849
"generate:pattern": "node ./generators/pattern.js",
4950
"generate:post-type": "node ./generators/post-type.js",

src/php/functions.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@
6060
require_once $filename;
6161
}
6262

63+
/**
64+
* Custom Meta Boxes
65+
*/
66+
foreach ( glob( get_template_directory() . '/inc/meta-boxes/*.php' ) as $filename ) {
67+
require_once $filename;
68+
}
69+
6370
/**
6471
* Enqueue scripts and styles.
6572
*/

src/php/inc/meta-boxes/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)