Mettre à jour le plugin à partir de l'API personnelle

9

Je suis en train de développer un plugin wordpress pour le moment que je ne veux pas dans le référentiel de plugins Wordpress. Cependant, je veux toujours pouvoir envoyer des mises à jour à mes clients depuis mon propre référentiel d'API.

J'ai lu beaucoup de choses à ce sujet, et une chose qui semble être quelque chose est le pre_set_site_transient_update_pluginsfiltre, mais je ne trouve pas beaucoup d'informations à ce sujet. J'ai essayé ce tutoriel ( http://konstruktors.com/blog/wordpress/2538-automatic-updates-for-plugins-and-themes-hosted-outside-wordpress-extend/ ) que je n'ai pas réussi à faire fonctionner. Je peux dire d'après les commentaires que d'autres peuvent réellement faire fonctionner cela avec ce qui doit être presque la version actuelle de WP (dernière réponse le 22 avril).

J'ai essayé d'installer le plugin à partir du site et de placer le dossier API sur un deuxième domaine, mais la notification de mise à jour que j'obtiens généralement lorsqu'une mise à jour est disponible, ne s'affichait nulle part.

Je ne sais pas s'il est réellement possible que des plugins personnalisés exécutent la mise à jour automatique à partir d'autres référentiels, donc j'aimerais savoir si quelqu'un ici a une quelconque expérience avec ce genre de choses? La solution du tutoriel semblait être une solution facile - je me demande s'il est possible de le faire d'une manière plus avancée?

Toute aide pour obtenir cette mise à jour automatique à partir de mon propre référentiel de travail serait très appréciée!

(PS: j'utilise WP version 3.1.3)

Simon
la source
Je suis peut-être en retard à la fête, mais vous pouvez trouver un plugin que j'ai construit exactement pour cela: WP Plugin Update Server
froger.me

Réponses:

2

Oui, c'est possible. Il y a un chapitre entier dans le développement de plugins WordPress professionnel dédié à cela. Si ce n'est pas déjà fait, prenez-en une copie. Ça va certainement aider.

EAMann
la source
J'ai en fait trouvé une version PDF de ceci en ligne, mais cela ne semble pas fonctionner pour moi non plus.
Simon
Cela fonctionne si vous le faites correctement, je l'ai fait, regardez l'API HTTP, codex.wordpress.org/HTTP_API
Wyck
Je viens de recommencer. Ce que j'ai jusqu'à présent, add_filter("pre_set_site_transient_update_plugins","dne_altapi_check"); c'est de me connecter à la vérification de la mise à jour du plugin en utilisant Après cela, j'ai la fonction dne_altapi_check qui contient print_r("hi");- cependant, lorsque j'appuie sur le bouton "Vérifier à nouveau" sous les mises à jour, cela n'imprime rien du tout .. Suis-je faire quelque chose de mal lors de la connexion au vérificateur de mise à jour?
Simon
Je me souviens que quelqu'un a écrit un cours pour le personnel de mise à jour du plugin, mais peut trouver un lien pour ce post: /
Mamaduka
1

Il existe ce gestionnaire d'API de mise à jour de plugin et de thème commercial pour WooCommerce qui fonctionne spécifiquement si le plugin ou le thème n'est pas hébergé sur wordpress.org. Il est conçu pour fournir des mises à jour pour les plugins et les thèmes auto-hébergés. Le plugin est destiné à ceux qui ne veulent pas l'écrire vous-même et qui ont besoin de beaucoup de fonctionnalités, ainsi que d'exemples de travail pour les plugins et les thèmes qui sont vendus.

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

Todd Lahman
la source
1

Il existe également un service soigné sur http://wp-updates.com/ - vous obtenez un thème ou un plugin gratuitement. Pour info - ce n'est pas mon site mais je l'ai essayé il y a un moment et il me semblait plutôt bien.

cwd
la source
Semble un bon service, mais je n'ai pas remarqué (presque sur un plan gratuit) HTTPS dans le panneau de contrôle Web ni dans la communication: en outre, je n'ai trouvé aucun type de contrôle de propriété lors de la vérification de la mise à jour (il me semble très simple POST request), je pense que des choses pourraient être volées, connaissant le nom du plugin et faisant quelques suppositions. J'aurais adoré l'utiliser, si ça avait l'air un peu plus professionnel côté sécurité.
reallynice
1

Pour une installation sur un seul site (je ne l'ai pas testée sur un site multiple), il n'y a que deux hooks que vous devez mettre à jour à partir d'un service externe tel que github ou gitlab. Dans le code ci-dessous, j'utilise gitlab car c'est ce que j'utilise pour héberger mon code en ce moment. Je devrais probablement résumer les parties de gitlab ...

Le premier crochet que vous devrez utiliser est pre_set_site_transient_update_themes. Il s'agit du filtre que WordPress utilise pour définir le site_transient pour qu'il affiche si des mises à jour sont disponibles. Utilisez ce crochet pour vous connecter à votre version distante et voir si des mises à jour sont disponibles. S'il y en a, modifiez le transitoire afin que WordPress sache qu'il y a des mises à jour et puisse afficher l'avis à l'utilisateur.

L'autre crochet que vous devrez utiliser est upgrader_source_selection. Ce filtre est nécessaire, pour gitlab de toute façon, car le nom du dossier téléchargé n'est pas le même que le thème, nous utilisons donc ce crochet pour le renommer avec le nom correct. Si votre référentiel distant fournit un zip avec le nom correct, vous n'avez même pas besoin de ce crochet.

Le troisième crochet, facultatif, que vous pouvez utiliser est auto_update_themesi vous souhaitez mettre à jour automatiquement votre thème. Dans l'exemple ci-dessous, j'utilise ce crochet pour mettre à jour automatiquement uniquement ce thème spécifique.

Ce code n'a été testé qu'avec WordPress 4.9.x. Il nécessite 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
la source