1

I am making a theme that will be updateable via github. https://github.com/pallazzio/skeleton

I am trying to use the plugin updater tutorial from smashing magazine, modified for updating a theme instead. https://www.smashingmagazine.com/2015/08/deploy-wordpress-plugins-with-github-using-transients/

I got it almost working. The update gets downloaded and installed to the correct folder. However, instead of leaving the same theme active, it is activating a new theme whose name is pallazzio-skeleton-b203a7f.

The weird part is that there is no folder created with that name. The files get installed to the correct place. The update is fully functional once I switch the active theme back to the original theme name.

The only thing I need to finish is how to make sure the current active theme doesn't change to a random name. I'm stuck.

Any help would be greatly appreciated.

Here is the relevant part in functions.php

// Init theme updater
if( ! class_exists( 'Pallazzio_Theme_Updater' ) ){
    include_once( 'updater.php' );
}
$updater = new Pallazzio_Theme_Updater( 'skeleton' );
$updater->set_username( 'pallazzio' );
$updater->set_repository( 'skeleton' );
//$updater->authorize( 'abcdefghijk1234567890' ); // auth code for private repos
$updater->initialize();

Here is the contents of updater.php

<?php
class Pallazzio_Theme_Updater {
    private $theme;
    private $username;
    private $repository;
    private $authorize_token;
    private $github_response;

    public function __construct( $theme ) {
        $this->theme = wp_get_theme( $theme );
        return $this;
    }

    public function set_username( $username ) {
        $this->username = $username;
    }

    public function set_repository( $repository ) {
        $this->repository = $repository;
    }

    public function authorize( $token ) {
        $this->authorize_token = $token;
    }

    public function initialize() {
        add_filter( 'pre_set_site_transient_update_themes', array( $this, 'modify_transient' ), 10, 1 );
        add_filter( 'upgrader_post_install', array( $this, 'after_install' ), 10, 3 );
    }

    public function modify_transient( $transient ) {
        if( property_exists( $transient, 'checked') ) { // Check if transient has a checked property

            if( $checked = $transient->checked ) { // Did Wordpress check for updates?

                $this->get_repository_info(); // Get the repo info

                $out_of_date = version_compare( $this->github_response['tag_name'], $checked[ $this->theme->template ], 'gt' ); // Check if we're out of date

                if( $out_of_date ) {

                    $new_files = $this->github_response['zipball_url']; // Get the ZIP

                    $theme = array( // setup our theme info
                        'theme' => $this->theme->template,
                        'url' => $this->theme->get( 'ThemeURI' ),
                        'package' => $new_files,
                        'new_version' => $this->github_response['tag_name']
                    );

                    $transient->response[$this->theme->template] = $theme; // Return it in response
                }
            }
        }

        return $transient; // Return filtered transient
    }

    public function after_install( $response, $hook_extra, $result ) {
        global $wp_filesystem; // Get global FS object

        $install_directory = get_template_directory(); // Our theme directory

        $result['destination_name'] = $this->theme->template; // Set the destination name for the rest of the stack
        $result['remote_destination'] = $install_directory; // Set the remote destination for the rest of the stack
        $wp_filesystem->move( $result['destination'], $install_directory ); // Move files to the theme dir
        $result['destination'] = $install_directory; // Set the destination for the rest of the stack

        //switch_theme( $this->theme->template );

        return $result;
    }

    private function get_repository_info() {
        if ( is_null( $this->github_response ) ) { // Do we have a response?
                $request_uri = sprintf( 'https://api.github.com/repos/%s/%s/releases', $this->username, $this->repository ); // Build URI

                if( $this->authorize_token ) { // Is there an access token?
                        $request_uri = add_query_arg( 'access_token', $this->authorize_token, $request_uri ); // Append it
                }

                $response = json_decode( wp_remote_retrieve_body( wp_remote_get( $request_uri ) ), true ); // Get JSON and parse it

                if( is_array( $response ) ) { // If it is an array
                        $response = current( $response ); // Get the first item
                }

                if( $this->authorize_token ) { // Is there an access token?
                        $response['zipball_url'] = add_query_arg( 'access_token', $this->authorize_token, $response['zipball_url'] ); // Update our zip url with token
                }

                $this->github_response = $response;
        }
    }
}
?>

3 Answers 3

0

The theme name is not related to the folder. The theme name comes from the header information inside the style.css file inside the theme. It's quite possible that the update being downloaded is a different theme. That's because of a loophole in the update system itself. The update is checked via the theme-slug instead of the theme name. Make sure the correct theme slug is being checked for and the update package on the server has the correct slug and theme name.

0

The whole process is too complicated to run in my head, but I can offer you a suggestion what has happened. As you know the theme name is stored in two entries in the database. It looks like somewhere these entries are changed to a temporary name, consisting of the actual name, the repository name and some sort of transient/nonce. The question is where.

My advice is trying to trace this by echoing get_option('template') a couple of times in your code. This should help you finding where the switch happens. My wild guess is here:

$result['destination_name'] = $this->theme->template;
0

Make sure all theme files are inside a directory, not at the root of the ZIP file.

OS X tricked me here. It looked like the ZIP file contained the theme folder with all theme files inside when this was actually not the case.

Upload your ZIP file to your server, unzip it to double check if it extracts the theme folder, and not the files at root.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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