Skip to content

Commit

Permalink
initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
svandragt committed Jun 4, 2020
0 parents commit 792a9a9
Show file tree
Hide file tree
Showing 4 changed files with 493 additions and 0 deletions.
77 changes: 77 additions & 0 deletions 404-fallback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
/**
* Plugin Name: 404 Fallback
* Plugin URI: PLUGIN SITE HERE
* Description: PLUGIN DESCRIPTION HERE
* Author: YOUR NAME HERE
* Author URI: YOUR SITE HERE
* Text Domain: 404-fallback
* Domain Path: /languages
* Version: 0.1.0
*
* @package 404_Fallback
*/

require_once plugin_dir_path( __FILE__ ) . '/lib/menus.php';
require_once plugin_dir_path( __FILE__ ) . '/lib/menu-site.php';

function fb404_redirect_404() {
global $wp;

$request = wp_unslash( $_SERVER['REQUEST_URI'] );
$url = stripslashes( get_option( 'fb404_setting_fallback_url' ));
if ( is_404() && !empty($url) ) {
$location = $url . $request;
$status = 302;
$x_redirect_by = '404 Fallback';
wp_redirect( $location, $status, $x_redirect_by );
die();
}
}

add_action( 'template_redirect', 'fb404_redirect_404' );

/**
* Add a site menu called Cluster
*/
function fb404_add_settings_menu() {
wpc_menu_register_page( [
'id' => 'fb404',
'menu_slug' => 'fb404_page',
'page_title' => '404 Fallback Settings',
'menu_title' => '404 Fallback',
'action' => 'fb404_page_update_handler',
] );

wpc_menu_register_settings( 'fb404', [
'general' => [
'fb404_setting_fallback_url' => 'Fallback URL',
],
] );
do_action( __FUNCTION__ );
}

add_action( 'init', 'fb404_add_settings_menu' );

/**
* Templating for our menu page. The function must match the 'menu_slug' in the menu config.
*/
function fb404_page() {
// Use the default page rendering instead of templating our page here.
wpc_menu_page_render( 'fb404' );
}

/**
* Handling the form submission. The function must match the 'action' key in the menu config.
*/
function fb404_page_update_handler() {
// Use the default page update handler instead of processing our options in a custom way.
wpc_menu_page_update_handler( 'fb404' );
}

function fb404_setting_fallback_url_render() {
$option_name = 'fb404_setting_fallback_url';
$config = stripslashes( get_option( $option_name ) );
printf( '<input name="%1$s" value="%2$s"
size="48"/>', $option_name, $config );
}
137 changes: 137 additions & 0 deletions lib/menu-site.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

/**
* Code used by site menus.
*/

/**
* List of menus and their setup configuration
*
* @param string $menu_id Identifier of the menu configuration to access. Leave empty to return all the configurations
*
* @return array Menu configuration(s)
*/
function wpc_menu_page_configs( $menu_id = '' ) {
return wpc_menu_configs( 'wpc_menu_page_configs', $menu_id );
}

function wpc_menu_page_render( $menu_id ) {
$config = wpc_menu_page_configs( $menu_id );
wpc_menu_render( 'site', $config );
}

/**
* Registration of the setting groups to the menu_slug.
*/
function wpc_menu_page_settings_registration() {
$menus = wpc_menu_page_configs();
wpc_menu_registration( $menus );
}

add_action( 'admin_init', 'wpc_menu_page_settings_registration' );

/**
* A generic way to handle the form post request.
*
* @param string $menu_id Menu page configuration id
*/
function wpc_menu_page_update_handler( $menu_id ) {
// Make sure we are posting from our options page. Note we must add the '-options' postfix
// when we check the referrer.
$config = wpc_menu_page_configs( $menu_id );
$updated = wpc_menu_update_options( 'site', $config, true );

wp_redirect( add_query_arg( [
'page' => $config['menu_slug'],
'updated' => (string) $updated,
], admin_url( 'admin.php' ) ) );
exit;

}

/**
* Register a grouped setting to a menu page id.
*
* @example Add a setting to the general settings group of the cluster menu-page:
* wpc_menu_register_page_settings( 'cluster', [
* 'general' => [
* 'wpc_cluster_use_production_images' => 'Use Production Images',
* ],
* ] );
*
* @param string|array $menu_id Menu identifier or configuration
* @param array $grouped_settings Array of setting groups.
*/
function wpc_menu_register_settings( $menu_id, $grouped_settings ) {

add_filter( 'wpc_menu_page_configs', function ( $menus ) use ( $menu_id, $grouped_settings ) {
if ( empty( $menus[ $menu_id ]['setting_sections'] ) ) {
$menus[ $menu_id ]['setting_sections'] = [];
}
$menus[ $menu_id ]['setting_sections'] = array_merge_recursive( $menus[ $menu_id ]['setting_sections'], $grouped_settings );

return $menus;
}, 11 );

}

/**
* Register a menu-page.
*
* @example Add a setting to the general settings group of the cluster menu-page:
* wpc_menu_register_page( [
* 'id' => 'cluster',
* 'menu_slug' => 'wpc_network_cluster_page',
* 'page_title' => 'Cluster Settings',
* 'menu_title' => 'Cluster',
* ] );
*
* The following keys are optional:
* - action: points to the function that will update the options instead
* of wpc_menu_page_update_handler()
*
* @param $config
*/
function wpc_menu_register_page( $config ) {
add_filter( 'wpc_menu_page_configs', function ( $menus ) use ( $config ) {
$menus[ $config['id'] ] = $config;

return $menus;
} );

$defaults = [
'page_title' => 'My Menu Page',
'menu_title' => 'My Menu',
];
$config = wp_parse_args( $config, $defaults );

add_action( 'admin_menu', function () use ( $config ) {
$menu_slug = $config['menu_slug'];

if ( empty( $config['parent_slug'] ) ) {
add_menu_page(
$config['page_title'],
$config['menu_title'],
'manage_options',
$menu_slug,
$menu_slug
);
} else {
add_submenu_page(
$config['parent_slug'],
$config['page_title'],
$config['menu_title'],
'manage_options',
$menu_slug,
$menu_slug
);
}
} );

$action = $config['action'];

/**
* This function here is hooked up to a special action and necessary to process the saving of the options.
*/
add_action( 'admin_post_' . $action, $action );
}
164 changes: 164 additions & 0 deletions lib/menus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php
/**
* Code used by both networkmenus and sitemenus
*/

/**
* Accessor for creating menupage configurations
*
* @param string $filter_id Extension point for other code to hook menus into.
* @param string $menu_id Identifier of the menu to retrieve from the filter.
*
* @return array Menu configuration
*/
function wpc_menu_configs( $filter_id, $menu_id = '' ) {
/*
* Amend the networkmenupage configurations
* Almost always it's better to use one of the following functions instead of calling this directly:
* - function wpc_menu_register_networkpage( $config )
* - function wpc_menu_register_network_settings( $menu_id, $grouped_settings )
*/
$menus = apply_filters( $filter_id, [] );

// All menus
if ( false === isset( $menus[ $menu_id ] ) ) {
return $menus;
}

return $menus[ $menu_id ];
}

/**
* @param $menus
*/
function wpc_menu_registration( array $menus ): void {
// for each menu's data build out sections and register the section's settings
foreach ( array_keys( $menus ) as $id ) {
$config = $menus[ $id ];
if ( empty( $config['setting_sections'] ) ) {
continue;
}
$sections = $config['setting_sections'];

if ( is_iterable( $sections ) ) {
foreach ( $sections as $section => $settings ) {
$page = $config['menu_slug'];
add_settings_section( $section, strtoupper( $section ), null, $page );

foreach ( (array) $settings as $name => $title ) {
$sanitization = is_callable( $name . '_sanitize' ) ? $name . '_sanitize' : [];
register_setting( $section, $name, $sanitization );
add_settings_field( $name, $title,
$name . '_render', $page,
$section );
}
}
}
}
}

/**
* Update a single option
*
* @param string $type Type: network or site
* @param bool $delete_missing Whether to delete the option if not submitted?
* @param string $option Option name
*
* @return bool False if value was not updated, true if updated.
*/
function wpc_menu_update_option( $type, $delete_missing, $option ): bool {
$updated = false;

if ( isset( $_POST[ $option ] ) ) {
if ( 'network' === $type ) {
$updated = update_site_option( $option, $_POST[ $option ] );
} else {
$updated = update_option( $option, $_POST[ $option ] );

}
} elseif ( $delete_missing ) {
if ( 'network' === $type ) {
$updated = delete_site_option( $option );
} else {
$updated = delete_option( $option );
}
}

return $updated;
}

/**
* Update the options for a given network page configuration
*
* @param string $type network|site configuration type
* @param array|string $config menu configuration or id of one.
* @param bool $delete_missing if missing options should be deleted or skipped
*
* @return bool if any of the options was updated or deleted
*/
function wpc_menu_update_options( $type, $config, $delete_missing ) {
global $new_whitelist_options;

check_admin_referer( $config['menu_slug'] . '-options' );

$did_update = false;

// Update or delete all the options
$sections = $config['setting_sections'];
if ( false === is_iterable( $sections ) ) {
return $did_update ? 'true' : 'false';
}
foreach ( (array) $sections as $section => $options ) {

$options = $new_whitelist_options[ $section ];
foreach ( (array) $options as $option ) {
$updated = wpc_menu_update_option( $type, $delete_missing, $option );
if ( $updated ) {
$did_update = true;
}
}
}

return $did_update ? 'true' : 'false';

}

function wpc_menu_render( $type, $config ) {
// Nonce is verified by wpc_menu_fields
if ( isset( $_GET['updated'] ) ): ?>
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Options saved.' ); ?></p></div>
<?php endif;

$full_action = [
'network' => 'edit.php?action=' . esc_attr( $config['action'] ),
'site' => admin_url( 'admin-post.php' ),
];
?>
<div class="wrap custom-options">
<header class="custom-options__header">
<h1><?php echo esc_html( $config['page_title'] ); ?></h1>
</header>

<form action="<?php echo $full_action[ $type ] ?>" method="POST">
<?php
wpc_menu_fields( $type, $config );
do_settings_sections( $config['menu_slug'] );
submit_button();
?>
</form>
</div>
<?php
}

/**
* Configuration type aware settings fields
*
* @param string $type network|site
* @param array $config menu configuration
*/
function wpc_menu_fields( $type, $config ) {
settings_fields( $config['menu_slug'] );
if ( 'network' !== $type ) {
echo "<input type='hidden' name='action' value='" . esc_attr( $config['action'] ) . "' />";
}
}
Loading

0 comments on commit 792a9a9

Please sign in to comment.