Skip to content

Theme updater may target active child theme instead of registered parent theme #54

@robincornett

Description

@robincornett

The theme updater uses wp_get_theme()->get_stylesheet() to determine which theme to update, rather than using the theme slug from the registration args. When a child theme is active, this causes:

  1. Updates applied to the wrong theme — WordPress registers the update against the child theme slug, so clicking "Update" deletes the child theme directory and leaves the parent theme untouched.
  2. False update notifications for child themes — Because the update data is keyed under the child theme's slug in the update_themes transient, WordPress displays the notification on the child theme instead of the parent.

Steps to Reproduce

  1. Create a parent theme registered with the SDK:
  $init->register( array(
      'id'      => 'parent-theme',
      'url'     => 'https://example.com',
      'item_id' => 123,
      'version' => '1.0.0',
      'type'    => 'theme',
  ) );
  1. Create and activate a child theme of that parent
  2. Release an update for the parent theme on the EDD store
  3. Visit Dashboard > Updates

Result: Update notification appears for the child theme. Clicking "Update" deletes the child theme.

Expected: Update notification appears for the parent theme. Clicking "Update" updates the parent theme.

Root Cause

Two gaps in how the registered slug flows from the Handler to the Updater:

  1. Handlers\Theme::auto_updater() does not pass the slug in the args to the ThemeUpdater constructor.
  2. Updaters\Theme::get_slug() hardcodes wp_get_theme()->get_stylesheet() instead of using the slug from $this->args.

The Handlers\Theme::get_slug() method correctly returns $this->args['id'], and sets $this->args['slug'] from it during construction — but that value is never forwarded to the Updater.

Proposed Fix

src/Handlers/Theme.php — Pass the slug to the ThemeUpdater in auto_updater():

  $args         = $this->get_default_api_request_args();
  $args['slug'] = $this->args['slug'];

src/Updaters/Theme.php — Use the passed slug when available in get_slug():

  protected function get_slug(): string {
      if ( ! empty( $this->args['slug'] ) ) {
          return $this->args['slug'];
      }

      return wp_get_theme()->get_stylesheet();
  }

This requires no changes from theme developers — the id parameter they already pass during registration is correctly propagated to the updater.

Impact

Affects any theme developer using parent/child theme architecture with the SDK. Without this fix, they must manually activate the parent theme on every site before updating, or add custom site_transient_update_themes filters to work around the issue.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions