Skip to content

Instantly share code, notes, and snippets.

@ravewebdev
Last active December 31, 2021 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ravewebdev/180f48723615ca43b659c7d0959e0b97 to your computer and use it in GitHub Desktop.
Save ravewebdev/180f48723615ca43b659c7d0959e0b97 to your computer and use it in GitHub Desktop.
Examples of registering core and custom settings with WP GraphQL.
<?php
/**
* Register custom settings with WordPress.
*/
function register_settings() {
register_setting(
'custom_settings_group',
'custom_settings',
[
'description' => esc_html__( 'Custom Settings', 'ravewebdev' ),
'sanitize_callback' => 'sanitize_settings',
'type' => 'array',
]
);
}
add_action( 'init', 'register_settings' );
/**
* Sanitize custom settings.
*
* @param array $input Settings inputs.
* @return array Sanitized inputs.
*/
function sanitize_settings( $input ) {
$sanitized_input = [];
if ( empty( $input ) ) {
return $sanitized_input;
}
foreach ( $input as $key => $value ) {
if ( 'error_404_page' === $key ) {
if ( is_nan( $value ) ) {
continue;
}
$sanitized_input[ $key ] = absint( $value );
continue;
}
$sanitized_input[ $key ] = sanitize_text_field( $value );
}
return $sanitized_input;
}
/**
* Add custom settings page link.
*/
function add_settings_link() {
add_options_page(
esc_html__( 'Custom Settings', 'ravewebdev' ),
esc_html__( 'Custom Settings', 'ravewebdev' ),
'edit_posts',
'custom-settings',
'display_settings_page'
);
}
add_action( 'admin_menu', 'add_settings_link' );
/**
* Display custom settings page.
*/
function display_settings_page() {
?>
<div class="wrap">
<h2><?php esc_html_e( 'Custom Settings', 'ravewebdev' ); ?></h2>
<div>
<form method="post" action="options.php" enctype="multipart/form-data">
<?php
settings_fields( 'custom_settings_group' );
do_settings_sections( 'custom-settings' );
submit_button();
?>
</form>
</div>
</div>
<?php
}
/**
* Register custom settings fields.
*/
function add_settings_fields() {
// Settings section: custom page options.
add_settings_section(
'pages',
esc_html__( 'Custom Page Options', 'ravewebdev' ),
null,
'custom-settings'
);
// Settings field: page to display 404 error content.
add_settings_field(
'error_404_page',
esc_html__( '404 Page', 'ravewebdev' ),
'display_error_404_page_input',
'custom-settings',
'pages'
);
}
add_action( 'admin_init', 'add_settings_fields' );
/**
* Display Error 404 Page input.
*/
function display_error_404_page_input() {
if ( ! defined( 'custom_settings_group' ) ) {
return;
}
$field_id = 'error_404_page';
$options = get_option( 'custom_settings' );
$selected_page = $options[ $field_id ] ?? '';
$pages = get_posts(
[
'numberposts' => -1,
'post_type' => 'page',
'post_status' => 'publish',
]
);
?>
<div>
<p style="margin: 0 0 1rem 0; font-style: italic;"><?php esc_html_e( 'Optional. Select a custom 404 page. The content entered on this page will appear on the headless frontend.', 'ravewebdev' ); ?></p>
<select id="<?php echo esc_attr( $field_id ); ?>" name="<?php echo esc_attr( "custom_settings[$field_id]" ); ?>">
<option><?php esc_html_e( '-- Select page --', 'ravewebdev' ); ?></option>
<?php foreach ( $pages as $page ) : ?>
<option value="<?php echo esc_attr( $page->ID ); ?>" <?php echo $selected_page === $page->ID ? 'selected="selected"' : ''; ?>><?php echo esc_attr( $page->post_title ); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php
}
<?php
/**
* Register core WordPress front page and posts page settings with WP GraphQL.
*/
function add_core_settings_types() {
// Register custom GraphQL object type that includes WP front page and posts page.
register_graphql_object_type(
'PageSettings',
[
'description' => esc_html__( 'Front and posts archive page data', 'ravewebdev' ),
'fields' => [
'frontPage' => [ 'type' => 'Page' ],
'postsPage' => [ 'type' => 'Page' ],
],
]
);
// Register top-level field to enable querying for new object type.
register_graphql_field(
'RootQuery',
'pageSettings',
[
'type' => 'PageSettings',
'description' => esc_html__( 'Connection between the RootQuery type and the PageSettings type', 'ravewebdev' ),
'resolve' => function( $source, array $args, \WPGraphQL\AppContext $context ) {
global $wpdb;
// Get front page and posts page settings.
$settings = $wpdb->get_row(
"
SELECT
(select option_value from {$wpdb->prefix}options where option_name = 'page_for_posts') as 'page_for_posts',
(select option_value from {$wpdb->prefix}options where option_name = 'page_on_front') as 'page_on_front'
",
ARRAY_A
);
// Format settings data.
$settings_data = [];
foreach ( $settings as $key => $value ) {
// Get page data.
$page_data = ! empty( $value ?? 0 ) ? $context->get_loader( 'post' )->load_deferred( intval( $value ) ) : null;
switch ( $key ) {
case 'page_for_posts':
$settings_data['postsPage'] = $page_data;
break;
case 'page_on_front':
$settings_data['frontPage'] = $page_data;
break;
}
}
return $settings_data;
},
]
);
}
add_action( 'graphql_register_types', 'add_core_settings_types' );
# Example query.
query QUERY_PAGE_SETTINGS {
pageSettings {
frontPage {
databaseId
isFrontPage
title
uri
}
postsPage {
databaseId
isPostsPage
title
uri
}
}
}
# Example response.
{
"data": {
"pageSettings": {
"frontPage": {
"databaseId": 2,
"isFrontPage": true,
"title": "Home",
"uri": "/"
},
"postsPage": {
"databaseId": 150,
"isPostsPage": true,
"title": "Post Archive",
"uri": "/post-archive/"
}
}
}
}
<?php
/**
* Register custom settings with WP GraphQL.
*
* @param TypeRegistry $type_registry The GraphQL type registry.
*/
function register_headless_settings( $type_registry ) {
// Register custom union type that supports pages only.
register_graphql_union_type(
'PageUnion',
[
'typeNames' => [ 'Page' ],
'resolveType' => function( $post ) use ( $type_registry ) {
$post_type = $post->post_type;
$post_type_object = get_post_type_object( $post_type );
$graphql_name = $post_type_object->graphql_single_name ?? null;
return $type_registry->get_type( $graphql_name );
},
]
);
// Register custom object type that uses new union type.
register_graphql_object_type(
'NestedSettings',
[
'description' => esc_html__( 'Nested settings', 'ravewebdev' ),
'fields' => [
'error404Page' => [ 'type' => 'PageUnion' ],
],
]
);
// Register custom object type that uses new nested object type.
register_graphql_object_type(
'CustomSettings',
[
'description' => esc_html__( 'Custom settings', 'ravewebdev' ),
'fields' => [
'nestedSettings' => [ 'type' => 'NestedSettings' ],
],
]
);
// Register top-level field to enable querying for new object type.
register_graphql_field(
'RootQuery',
'customSettings',
[
'type' => 'CustomSettings',
'description' => esc_html__( 'Connection between the RootQuery type and the CustomSettings type', 'ravewebdev' ),
'resolve' => function( $source, array $args, \WPGraphQL\AppContext $context ) {
$options = get_option( 'custom_settings' );
$error_404_page_id = $options['error_404_page'];
$error_404_page_id = is_nan( $error_404_page_id ) ? null : absint( $error_404_page_id );
$error_404_page = $context->get_loader( 'post' )->load_deferred( $error_404_page_id );
return [
'nestedSettings' => [
'error404Page' => $error_404_page,
],
];
},
]
);
}
add_action( 'graphql_register_types', 'register_headless_settings' );
# Example query.
query QUERY_CUSTOM_SETTINGS {
customSettings {
nestedSettings {
error404Page {
... on Page {
databaseId
title
uri
}
}
}
}
}
# Example response.
{
"data": {
"customSettings": {
"nestedSettings": {
"error404Page": {
"databaseId": 302,
"title": "404 Not Found",
"uri": "/404-not-found/"
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment