3

For my current project (a custom and not public WordPress theme) I would like to show additional information with the themes existing meta data (version, author, description, "Visit theme website", etc).

To be more specific: The theme can save an deploy key, which will be checked against my own little deploy-server for validity using jQuery/AJAX. I would like to show whether the theme is having a valid deploy key and whether the key is eligible for support and theme-upgrades.

Unfortunately, there seem to be no actions or filters that could be used to add to or modify the meta-data. Can someone offer any advice on this?

Thanks a million in advance! Best regards, Jonathan

2

It is not possible to extend the default headers used by WP_Theme:

private static $file_headers = array(
    'Name'        => 'Theme Name',
    'ThemeURI'    => 'Theme URI',
    'Description' => 'Description',
    'Author'      => 'Author',
    'AuthorURI'   => 'Author URI',
    'Version'     => 'Version',
    'Template'    => 'Template',
    'Status'      => 'Status',
    'Tags'        => 'Tags',
    'TextDomain'  => 'Text Domain',
    'DomainPath'  => 'Domain Path',
);

Here's another post where someone was trying to do the same thing.

I kept digging, and found this post over on Stack Overflow which provided a workaround for being able to hard code and read custom file headers.

I realize that you want to be able to read and write these headers dynamically and display messages based on the info, and this answer doesn't cover all of that, but it's a good start.

Assuming this header in the theme:

/*
Theme Name: Dave's Good Stuff 80's Theme
Theme URI: https://www.youtube.com/playlist?list=PL3k1BzkuZjd7F0EE6mp5LPQWxigJ-8_td
Author: Dave Romsey
Author URI: http://daveromsey.com
Description: A cool theme.
Version: 0.1.0
Tags: 
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: goto10
Key: 867-5309
*/

This code will be able to pull out custom file header keys:

/**
 * Retrieve metadata from a file.
 *
 * Searches for metadata in the first 8kiB of a file, such as a plugin or theme.
 * Each piece of metadata must be on its own line. Fields can not span multiple
 * lines, the value will get cut at the end of the first line.
 *
 * If the file data is not within that first 8kiB, then the author should correct
 * their plugin file and move the data headers to the top.
 *
 * @param string $file Path to the file
 * @param array $default_headers List of headers, in the format array('HeaderKey' => 'Header Name')
 */

function wpse238644_get_file_data( $file, $default_headers) {
    $fp = fopen( $file, 'r' );
    $file_data = fread( $fp, 8192 );
    fclose( $fp );
    $file_data = str_replace( "\r", "\n", $file_data );
    $all_headers = $default_headers;

    foreach ( $all_headers as $field => $regex ) {
            if (preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) 
                    && $match[1])
                    $all_headers[ $field ] = trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $match[1]));
            else
                    $all_headers[ $field ] = '';
    }

    return $all_headers;
}


function wpse238644_get_theme_data() {
    // Customize these to fit your needs
    $file_headers = array(
        'Name'        => 'Theme Name',
        'ThemeURI'    => 'Theme URI',
        'Description' => 'Description',
        'Author'      => 'Author',
        'AuthorURI'   => 'Author URI',
        'Version'     => 'Version',
        'Template'    => 'Template',
        'Status'      => 'Status',
        'Tags'        => 'Tags',
        'TextDomain'  => 'Text Domain',
        'DomainPath'  => 'Domain Path',
        'Key'         => 'Key',
    );

    $theme_headers = wpse238644_get_file_data( get_template_directory() . '/style.css', $file_headers );

    $theme_key = isset( $theme_headers['Key'] ) ? $theme_headers['Key'] : false;

    // Do something with the key
    //var_dump( $theme_key );
}
add_action( 'init', 'wpse238644_get_theme_data' );
| improve this answer | |
  • 1
    Thank you for this detailed answer! Anyways, I don't want to save the key in the theme headers (this would require the end-user to modify the theme code) but in a theme_mod that can be changed in the the theme customizer... For the purpose of saving additional theme meta-data with the theme itself your answer is great! – Jonathan Weber Sep 9 '16 at 15:57
0

As far as my research goes, there is, at the moment of writing, no way to hook into the WordPress theme listing routines on the theme-screen. This means, that there is likely no way of changing the screens content without either modifying the core files or replacing the themes screen with your own implementation. Both are non-acceptable solutions.

For the time being, I solved the problem as follows:

  1. The deploy-server provides a wordpress.js file (somewhat like a CDN). This file is loaded with wp_enqueue_script(..). This file is localized with the theme-slug, the deploy-server, the deploy-repository and the deploy-key. Based on the theme-slug, it runs an AJAX GET request for every "theme" div on the theme admin screen, asking for deploy-key validation and giving the theme a colored border depending on server response.
  2. The deploy-key is stored in the WordPress database as theme_mod and can be added, removed and modified via a theme customizer text field.
  3. To make things easy, I wrote a small PHP class that themes can simply include. This class requires the theme slug, server and repository upon creation `new RevUpdater($slug, $server, $repository); and handles the following: script inclusion, theme customizer settings for deploy-key, settings saving. This way, upgrade for all themes simply requires replacing this class-file.

I know, that this is hardly prohibiting anything - anyone could still use, steal, modify this theme. But trying to prevent usage of the theme would be pointless either, since anyone could simply modify the theme code to prevent license check.

I plan on further improving the API by making the theme updater-class require a server-side license check every few days - triggered by page visit. Failing this check would mean front-end blocking.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.