Plugin von persönlicher API aktualisieren

9

Ich entwickle gerade ein WordPress-Plugin, das ich nicht im Wordpress-Plugin-Repository haben möchte. Ich möchte jedoch weiterhin in der Lage sein, Updates aus meinem eigenen API-Repository an meine Kunden zu senden.

Ich habe ziemlich viel darüber gelesen, und eine Sache, die etwas zu sein scheint, ist der pre_set_site_transient_update_pluginsFilter, aber ich kann nicht viele Informationen darüber finden. Ich habe dieses Tutorial ( http://konstruktors.com/blog/wordpress/2538-automatic-updates-for-plugins-and-themes-hosted-outside-wordpress-extend/ ) ausprobiert, das ich nicht zum Laufen bringen konnte. Ich kann den Kommentaren entnehmen, dass andere dies tatsächlich mit der fast aktuellen Version von WP zum Laufen bringen können (letzte Antwort 22. April).

Ich habe versucht, das Plugin von der Site zu installieren und den API-Ordner in eine zweite Domäne zu stellen, aber die Update-Benachrichtigung, die ich normalerweise erhalte, wenn ein Update verfügbar ist, wurde überhaupt nicht angezeigt.

Ich bin mir nicht sicher, ob es tatsächlich möglich ist, dass benutzerdefinierte Plugins das automatische Update von anderen Repositorys ausführen, also würde ich gerne hören, ob jemand hier überhaupt Erfahrung mit diesem Zeug hat. Die Lösung im Tutorial schien eine einfache Lösung zu sein - ich frage mich, ob es irgendwie möglich ist, dies auf fortgeschrittenere Weise zu tun.

Jede Hilfe, um dieses automatische Update aus meinem eigenen Repository zum Laufen zu bringen, wäre sehr dankbar!

(PS: Ich verwende WP Version 3.1.3)

Simon
quelle
Ich
komme

Antworten:

2

Ja, das ist möglich. Es gibt ein ganzes Kapitel in der professionellen WordPress-Plugin-Entwicklung , das diesem Thema gewidmet ist. Wenn Sie es noch nicht getan haben, holen Sie sich eine Kopie. Es wird definitiv helfen.

EAMann
quelle
Ich habe tatsächlich eine PDF-Version davon online gefunden, aber das schien auch für mich nicht zu funktionieren.
Simon
Es funktioniert, wenn Sie es richtig machen, ich habe es getan, schauen Sie sich die HTTP-API an, codex.wordpress.org/HTTP_API
Wyck
Ich habe gerade wieder von vorne angefangen. Was ich bisher habe, ist das Einbinden in die Plugin-Update-Prüfung mit add_filter("pre_set_site_transient_update_plugins","dne_altapi_check"); Danach habe ich die Funktion dne_altapi_check, die enthält print_r("hi");- aber wenn ich unter Updates auf die Schaltfläche "Erneut prüfen " drücke, wird überhaupt nichts gedruckt. Bin ich etwas falsch machen, wenn Sie sich in den Update Checker einhängen?
Simon
Ich erinnere mich, dass jemand eine Klasse für Plugin-Update-Mitarbeiter geschrieben hat, aber einen Link für diesen Beitrag finden kann: /
Mamaduka
1

Es gibt diesen kommerziellen Plugin und Theme Update API Manager für WooCommerce, der speziell funktioniert, wenn das Plugin oder Theme nicht auf wordpress.org gehostet wird. Es wurde entwickelt, um Updates für selbst gehostete Plugins und Themes bereitzustellen. Das Plugin ist für diejenigen gedacht, die es nicht selbst schreiben möchten und viele Funktionen sowie Arbeitsbeispiele für Plugins und Themen benötigen, die verkauft werden.

http://www.toddlahman.com/shop/wordpress-automatic-update-api-manager/

Todd Lahman
quelle
1

Es gibt auch einen netten Service unter http://wp-updates.com/ - Sie erhalten ein Thema oder Plugin kostenlos. Zu Ihrer Information - dies ist nicht meine Seite, aber ich habe es vor einiger Zeit versucht und es schien ziemlich gut zu sein.

cwd
quelle
Scheint ein netter Service zu sein, aber ich habe HTTPS weder im Web-Control-Panel noch in der Kommunikation bemerkt (fast nach freiem Plan). Außerdem habe ich bei der Durchführung des Update-Checks keine Eigentumsprüfung gefunden (es scheint mir sehr einfach zu sein) POST-Anfrage), ich habe das Gefühl, dass Sachen gestohlen werden könnten, wenn man den Namen des Plugins kennt und einige Vermutungen anstellt. Ich hätte es gerne benutzt, wenn es auf der Sicherheitsseite etwas professioneller gewesen wäre.
wirklich schön
1

Für eine Single-Site-Installation (ich habe sie nicht auf einer Multi-Site-Installation getestet) müssen nur zwei Hooks von einem externen Dienst wie Github oder Gitlab aktualisiert werden. Im folgenden Code verwende ich gitlab, da ich damit meinen Code gerade hoste. Ich sollte wahrscheinlich die Gitlab-Teile abstrahieren ...

Der erste Haken, den Sie verwenden müssen, ist pre_set_site_transient_update_themes. Dies ist der Filter, mit dem WordPress den site_transient so einstellt, dass angezeigt wird, ob Updates verfügbar sind. Verwenden Sie diesen Hook, um eine Verbindung zu Ihrer Remote-Version herzustellen und festzustellen, ob Updates verfügbar sind. Wenn dies der Fall ist, ändern Sie den Übergang so, dass WordPress weiß, dass Aktualisierungen vorhanden sind, und dem Benutzer den Hinweis anzeigen kann.

Der andere Haken, den Sie verwenden müssen, ist upgrader_source_selection. Dieser Filter wird für gitlab ohnehin benötigt, da der Name des heruntergeladenen Ordners nicht mit dem Thema übereinstimmt. Daher verwenden wir diesen Hook, um ihn in den richtigen Namen umzubenennen. Wenn Ihr Remote-Repository eine Zip-Datei mit dem richtigen Namen bereitstellt, benötigen Sie diesen Hook nicht einmal.

Der dritte optionale Hook, den Sie verwenden können, ist, auto_update_themewenn Sie Ihr Thema automatisch aktualisieren möchten. Im folgenden Beispiel verwende ich diesen Hook, um nur dieses spezielle Thema automatisch zu aktualisieren.

Dieser Code wurde nur mit WordPress 4.9.x getestet. Es erfordert PHP> 7.0.

functions.php

//* Load the updater.
require PATH_TO . 'updater.php';
$updater = new updater();
\add_action( 'init', [ $updater, 'init' ] );

updater.php

/**
 * @package StackExchange\WordPress
 */
declare( strict_types = 1 );
namespace StackExchange\WordPress;

/**
 * Class for updating the theme.
 */
class updater {

  /**
   * @var Theme slug.
   */
  protected $theme = 'theme';

  /**
   * @var Theme repository name.
   */
  protected $repository = 'project/theme';

  /**
   * @var Repository domain.
   */
  protected $domain = 'https://gitlab.com/';

  /**
   * @var CSS endpoint for repository.
   */
  protected $css_endpoint = '/raw/master/style.css';

  /**
   * @var ZIP endpoint for repository.
   */
  protected $zip_endpoint = '/repository/archive.zip';

  /**
   * @var Remote CSS URI.
   */
  protected $remote_css_uri;

  /**
   * @var Remote ZIP URI.
   */
  protected $remote_zip_uri;

  /**
   * @var Remote version.
   */
  protected $remote_version;

  /**
   * @var Local version.
   */
  protected $local_version;

  /**
   * Method called from the init hook to initiate the updater
   */
  public function init() {
    \add_filter( 'auto_update_theme', [ $this, 'auto_update_theme' ], 20, 2 );
    \add_filter( 'upgrader_source_selection', [ $this, 'upgrader_source_selection' ], 10, 4 );
    \add_filter( 'pre_set_site_transient_update_themes', [ $this, 'pre_set_site_transient_update_themes' ] );
  }

  /**
   * Method called from the auto_update_theme hook.
   * Only auto update this theme.
   * This hook and method are only needed if you want to auto update the theme.
   *
   * @return bool Whether to update the theme.
   */
  public function auto_update_theme( bool $update, \stdClass $item ) : bool {
    return $this->theme === $item->theme;
  }

  /**
   * Rename the unzipped folder to be the same as the existing folder
   *
   * @param string       $source        File source location
   * @param string       $remote_source Remote file source location
   * @param \WP_Upgrader $upgrader      \WP_Upgrader instance
   * @param array        $hook_extra    Extra arguments passed to hooked filters
   *
   * @return string | \WP_Error The updated source location or a \WP_Error object on failure
   */
  public function upgrader_source_selection( string $source, string $remote_source, \WP_Upgrader $upgrader, array $hook_extra ) {
    global $wp_filesystem;

    $update = [ 'update-selected', 'update-selected-themes', 'upgrade-theme' ];

    if( ! isset( $_GET[ 'action' ] ) || ! in_array( $_GET[ 'action' ], $update, true ) ) {
      return $source;
    }

    if( ! isset( $source, $remote_source ) ) {
      return $source;
    }

    if( false === stristr( basename( $source ), $this->theme ) ) {
      return $source;
    }

    $basename = basename( $source );
    $upgrader->skin->feedback( esc_html_e( 'Renaming theme directory.', 'bootstrap' ) );
    $corrected_source = str_replace( $basename, $this->theme, $source );

    if( $wp_filesystem->move( $source, $corrected_source, true ) ) {
      $upgrader->skin->feedback( esc_html_e( 'Rename successful.', 'bootstrap' ) );
      return $corrected_source;
    }

    return new \WP_Error();
  }

  /**
   * Add respoinse to update transient if theme has an update.
   *
   * @param $transient
   *
   * @return
   */
  public function pre_set_site_transient_update_themes( $transient ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    $this->local_version = ( \wp_get_theme( $this->theme ) )->get( 'Version' );

    if( $this->hasUpdate() ) {
      $response = [
        'theme'       => $this->theme,
        'new_version' => $this->remote_version,
        'url'         => $this->construct_repository_uri(),
        'package'     => $this->construct_remote_zip_uri(),
        'branch'      => 'master',
      ];
      $transient->response[ $this->theme ] = $response;
    }

    return $transient;
  }

  /**
   * Construct and return the URI to the remote stylesheet
   *
   * @return string The remote stylesheet URI
   */
  protected function construct_remote_stylesheet_uri() : string {
    return $this->remote_css_uri = $this->domain . $this->repository . $this->css_endpoint;
  }

  /**
   * Construct and return the URI to the remote ZIP file
   *
   * @return string The remote ZIP URI
   */
  protected function construct_remote_zip_uri() : string {
    return $this->remote_zip_uri = $this->domain . $this->repository . $this->zip_endpoint;
  }

  /**
   * Construct and return the URI to remote repository
   *
   * @access protected
   * @since  1.0
   *
   * @return string The remote repository URI
   */
  protected function construct_repository_uri() : string {
    return $this->repository_uri = $this->domain . \trailingslashit( $this->repository );
  }

  /**
   * Get and return the remote version
   *
   * @return string The remote version
   */
  protected function get_remote_version() : string {
    $this->remote_stylesheet_uri = $this->construct_remote_stylesheet_uri();
    $response = $this->remote_get( $this->remote_stylesheet_uri );
    $response = str_replace( "\r", "\n", \wp_remote_retrieve_body( $response ) );
    $headers = [ 'Version' => 'Version' ];

    foreach( $headers as $field => $regex ) {
      if( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $response, $match ) && $match[1] ) {
        $headers[ $field ] = _cleanup_header_comment( $match[1] );
      }
      else {
        $headers[ $field ] = '';
      }
    }

    return $this->remote_version = ( '' === $headers[ 'Version' ] ) ? '' : $headers[ 'Version' ];
  }

  /**
   * Return whether the theme has an update
   *
   * @return bool Whether the theme has an update
   */
  protected function hasUpdate() : bool {
    if( ! $this->remote_version ) $this->remote_version = $this->get_remote_version();
    return version_compare( $this->remote_version, $this->local_version, '>' );
  }

  /**
   * Wrapper for \wp_remote_get()
   *
   * @param string $url  The URL to get
   * @param array  $args Array or arguments to pass through to \wp_remote_get()
   *
   * @return array|WP_Error Return the request or an error object
   */
  protected function remote_get( string $url, array $args = [] ) {
    return \wp_remote_get( $url, $args );
  }
}
Nathan Johnson
quelle