Modifying WordPress theme's copyright from the Customizer

This post is about modifying WordPress theme's copyright from the Customizer.

One of the most asked question by new WordPress users is: "how to change the copyright ?".
They don't want a label of any kind on their site and that's totally comprehensible.
In this post, I'll be talking of my own sauce to give users the ability to remove or modify the copyright without touching one line of code !

If you are new to the Customizer, don't be afraid, I was too a long time ago...
So in this post I'll show you a technique to control the copyright of WordPress, generally displayed in the footer of a theme, from the Customizer.
You can use it in your own theme to give your users a clean and easy way to modify the footer copyright, or use it in a child theme to modify the footer copyright of the parent theme that you are using.

1- Replace the footer copyright by a function

First of all select the part that should be modified. Generally speaking, it's a sentence like: "Proudly powered by WordPress, Theme: theme-name by theme-author". I'm going to take the generated footer by _s (underscores) as an example for this task. Looking inside the footer.php, we can see a code like this:

<footer id="colophon" class="site-footer">
    <div class="site-info">
        <a href="<?php echo esc_url( __( 'https://wordpress.org/', 'midday' ) ); ?>">
            <?php
            /* translators: %s: CMS name, i.e. WordPress. */
            printf( esc_html__( 'Proudly powered by %s', 'midday' ), 'WordPress' );
            ?>
        </a>
        <span class="sep"> | </span>
            <?php
            /* translators: 1: Theme name, 2: Theme author. */
            printf( esc_html__( 'Theme: %1$s by %2$s.', 'midday' ), 'midday', '<a href="https://github.com/LebCit">LebCit</a>' );
            ?>
    </div><!-- .site-info -->
</footer><!-- #colophon -->

Here, we are interested with the code inside <div class="site-info">, so let's cut it, paste it somewhere else (like notepad), and replace it by a php function.
The code should now be like the following:

<footer id="colophon" class="site-footer">
    <div id="site-info" class="site-info">
        <?php midday_site_info(); ?>
    </div><!-- .site-info -->
</footer><!-- #colophon -->

You can name the function whatever you like, but be sure to replace any name modification according to the changes you have made in the wright place in the code.
Please note that I've added an <id="site-info"> this will be used in the Customizer.

2- Put the footer copyright in functions.php

Now we have to connect this midday_site_info() function with the block of code previously pasted elsewhere.
In the functions.php file of your theme or your child theme, put this code, I'll explain it just after :

/**
 * Output the theme's copyright depending on user's choice.
 */
function midday_site_info() {
    $midday_footer_copyright_area_checkbox = get_theme_mod( 'midday_footer_copyright_area_checkbox', true );
    $midday_custom_copyright_textarea      = get_theme_mod( 'midday_custom_copyright_textarea', '' );
    if ( ! empty( $midday_footer_copyright_area_checkbox ) ) :
            $html  = '<a href="' . esc_url( 'https://wordpress.org/' ) . '">' . esc_html( 'Proudly powered by WordPress' ) . '</a>';
            $html .= '<span class="sep"> | </span>';
            $html .= esc_html( 'Theme: MidDay by ' ) . '<a href="' . esc_url( 'https://lebcit.github.io/' ) . '">' . esc_html( 'LebCit' ) . '</a>';
            echo wp_kses(
                $html,
                array(
                    'a'  => array(
                        'href' => array(),
                    ),
                    'span'  => array(
                        'class' => array(),
                    ),
                )
            );
    elseif ( empty( $midday_footer_copyright_area_checkbox ) && ! empty( $midday_custom_copyright_textarea ) ) :
        echo wp_kses_post( $midday_custom_copyright_textarea ); // Allow html.
    endif;
}

What in the hell is this ?
It's nothing 😂 it's just the same pasted elsewhere code in PHP with some variables and an if/elseif statement to take care of the user's choice.

Inside the function, I've defined 2 variables. Each one is related to a theme_mod (theme modification) that we will create and explain in a moment.

I've opened an if statement saying:
if the first variable (remember it's related to a theme_mod, yes it's a checkbox) 😉 is not empty (so it have a check tick, it's checked) please populate the copyright with the following code. The code here is pretty easy to understand. I've defined an $html variable replicating the pasted elsewhere code, then I've asked PHP to echo this code using wp_kses filtering the text content and striping out disallowed HTML.

In other words:
hey wp_kses, please echo the defined $html variable, and please allow it to only have a tag with href attribute and span tag with class attribute, thank you very much 😊

After that, I've opened an elseif statement saying:
okay, if the first variable is empty (the checkbox is not checked) and the second variable (a text area) is not empty, please populate the copyright with the content of the text area allowing the user to use HTML inside it with wp_kses_post that will keep an eye and make sure the user type allowed HTML only, that's it I've nothing more to ask so please close the if statement with this endif;

3- Create settings and controls in the Customizer

Do you remember the 2 previous variables ?
They where related to theme's modifications.
It's time to create those theme_mod and test our code.
To keep the functions.php file clean, we will put the following in a customizer.php file if you don't have one already. Yous just have to require it from functions.php like so :

require get_template_directory() . '/inc/customizer.php';

Please note that in this example the file is in a folder named inc (for includes) at the root of the theme or the child theme, you can change this but be sure to indicate the correct path.
Now, put the following in customizer.php, let's see the code and explain it later:

function midday_customize_register( $wp_customize ) {
    /**
     * MidDay Theme Panel
     */
    $wp_customize->add_panel(
        'midday_panel',
        array(
            'title'       => __( 'MidDay Theme', 'midday' ),
            'description' => esc_html__( 'Customize MidDay Theme', 'midday' ),
            'priority'    => 0,
        )
    );

    /**
     * Footer Copyright Area Section.
     */
    $wp_customize->add_section(
        'midday_footer_copyright_area_section',
        array(
            'title'       => esc_html__( 'Footer Copyright Area', 'midday' ),
            'description' => __( 'Modify <b>Footer Copyright Area</b>.', 'midday' ),
            'panel'       => 'midday_panel',
            'priority'    => 15,
        )
    );

    // Default copyright.
    $wp_customize->add_setting(
        'midday_footer_copyright_area_checkbox',
        array(
            'default'           => true,
            'transport'         => 'postMessage',
            'sanitize_callback' => 'midday_sanitize_checkbox',
        )
    );

    $wp_customize->add_control(
        'midday_footer_copyright_area_checkbox',
        array(
            'label'       => __( 'Enable/Disable Default Copyright.', 'midday' ),
            'description' => __( 'This checkbox, once <b>unchecked</b>,<br>removes <b>Default Copyright.</b>', 'midday' ),
            'section'     => 'midday_footer_copyright_area_section',
            'type'        => 'checkbox',
        )
    );

    $wp_customize->selective_refresh->add_partial(
        'midday_footer_copyright_area_checkbox',
        array(
            'selector'        => '#site-info',
            'settings'        => array( 'midday_footer_copyright_area_checkbox' ),
            'render_callback' => 'midday_site_info',
        )
    );

    // Custom copyright.
    $wp_customize->add_setting(
        'midday_custom_copyright_textarea',
        array(
            'default'           => '',
            'transport'         => 'postMessage',
            'sanitize_callback' => 'wp_kses_post', // Allow html.
        )
    );

    $wp_customize->add_control(
        'midday_custom_copyright_textarea',
        array(
            'label'       => esc_html__( 'Custom Copyright Textarea', 'midday' ),
            'description' => __( 'To display a <b>Custom Copyright</b>,<br><b>uncheck</b> the <b>Default Copyright</b> checkbox,<br>then type a custom copyright in the textarea.<br><b>HTML</b> is allowed !', 'midday' ),
            'section'     => 'midday_footer_copyright_area_section',
            'type'        => 'textarea',
            'input_attrs' => array(
                'style'       => 'border: 1px solid #999',
                'placeholder' => __( 'Enter Custom Copyright...', 'midday' ),
            ),
        )
    );

    $wp_customize->selective_refresh->add_partial(
        'midday_custom_copyright_textarea',
        array(
            'selector'        => '#site-info',
            'settings'        => array( 'midday_custom_copyright_textarea' ),
            'render_callback' => 'midday_site_info',
        )
    );

}
add_action( 'customize_register', 'midday_customize_register' );

Don't panic, it's pretty straightforward !
Let's break it down and you'll see.

function mytheme_customize_register( $wp_customize )
{
    //All our sections, settings, and controls will be added here
}
add_action( 'customize_register', 'mytheme_customize_register' );

This is how we hook a function to the 'customize_register' action and put inside it our panels, sections, settings and controls.
Looking at our code, you can now understand that I've created a panel, a section, 2 settings and their 2 related controls.
I'm not going to dive into the Customizer, but if you're not familiar with it, a good start would be this excellent guide by Anthony Hortin.
Instead, I'm going to explain a more important aspect here. If you take a good look at the code, you'll see something else under each control :

$wp_customize->selective_refresh->add_partial

What is this and what does it do ?
Well, look closer and you'll figure it out yourself 😂
Just kidding, but in fact it's really clear.
Let's take one setting it's control and the related selective_refresh:

// Default copyright.
$wp_customize->add_setting(
    'midday_footer_copyright_area_checkbox',
    array(
        'default'           => true,
        'transport'         => 'postMessage',
        'sanitize_callback' => 'midday_sanitize_checkbox',
    )
);

$wp_customize->add_control(
    'midday_footer_copyright_area_checkbox',
    array(
        'label'       => __( 'Enable/Disable Default Copyright.', 'midday' ),
        'description' => __( 'This checkbox, once <b>unchecked</b>,<br>removes <b>Default Copyright.</b>', 'midday' ),
        'section'     => 'midday_footer_copyright_area_section',
        'type'        => 'checkbox',
    )
);

$wp_customize->selective_refresh->add_partial(
    'midday_footer_copyright_area_checkbox',
    array(
        'selector'        => '#site-info',
        'settings'        => array( 'midday_footer_copyright_area_checkbox' ),
        'render_callback' => 'midday_site_info',
    )
);

Remember the first variable ?
Well here is it's theme_mod !
Take a look at the setting name midday_footer_copyright_area_checkbox 😉
The important part here is 'transport' => 'postMessage', because it tells the browser not to reload, but to make the change(s) in place !
Another important aspect in the setting is 'sanitize_callback' => 'midday_sanitize_checkbox', this is a function to sanitize the checkbox, you should put it after the 'customize_register' action hook:

if ( ! function_exists( 'midday_sanitize_checkbox' ) ) {
    /**
     * Switch sanitization
     *
     * @param string $input Switch value.
     * @return integer  Sanitized value
     */
    function midday_sanitize_checkbox( $input ) {
        if ( false === $input ) {
            return 0;
        } else {
            return 1;
        }
    }
}

In the control, the important part is the type of the control, as you can see it's defined as checkbox, no surprise, WYaskIWYG 😂
For the partial, the important part is the selector, it must be an id, now you know why I've added an id previously 👍
If you look at the settings and the render_callback of the partial, you'll understand that everything is related 🔗 and that we are just putting the wright piece in the wright place 🧩

You maybe guessed it out or not, but yes I'm developing a new theme called MidDay (in fact I've finished it, just some clean up remaining) and I'll submit it very soon 😁

I really hope that this was helpful.

SYA,
LebCit.