Zaktualizuj wtyczkę z osobistego interfejsu API

9

Obecnie rozwijam wtyczkę Wordpress, której nie chcę w repozytorium wtyczek Wordpress. Nadal chcę jednak móc przesyłać aktualizacje moim klientom z mojego własnego repozytorium API.

Czytałem o tym sporo, a jedną z rzeczy, która wydaje się być czymś, jest pre_set_site_transient_update_pluginsfiltr, ale nie mogę znaleźć dużo informacji na ten temat. Próbowałem tego samouczka ( http://konstruktors.com/blog/wordpress/2538-automatic-updates-for-plugins-and-themes-hosted-outside-wordpress-extend/ ), którego nie mogłem uruchomić. Na podstawie komentarzy mogę stwierdzić, że inni mogą to zrobić z prawie aktualną wersją WP (ostatnia odpowiedź 22 kwietnia).

Próbowałem zainstalować wtyczkę z witryny i umieścić folder API w drugiej domenie, ale powiadomienie o aktualizacji, które zwykle otrzymuję, gdy aktualizacja jest dostępna, nigdzie się nie pokazało.

Nie jestem pewien, czy rzeczywiście możliwe jest, aby niestandardowe wtyczki uruchamiały automatyczną aktualizację z innych repozytoriów, więc chciałbym usłyszeć, czy ktoś tutaj ma jakieś doświadczenie z tymi rzeczami? Rozwiązanie w samouczku wydawało się łatwe - zastanawiam się, czy można to zrobić w bardziej zaawansowany sposób?

Będzie mi bardzo miło pomóc w uzyskaniu tej automatycznej aktualizacji z mojego własnego repozytorium!

(PS: Używam WP w wersji 3.1.3)

Szymon
źródło
Mogę spóźnić się na imprezę, ale możesz znaleźć wtyczkę, którą zbudowałem właśnie do tego: Serwer aktualizacji wtyczek WP
froger.me

Odpowiedzi:

2

Tak, jest to możliwe. Na ten temat poświęcony jest cały rozdział dotyczący rozwoju profesjonalnych wtyczek WordPress . Jeśli jeszcze tego nie zrobiłeś, podnieś kopię. To na pewno pomoże.

EAMann
źródło
Znalazłem wersję PDF tej wersji online, ale to też nie działało dla mnie.
Simon
Działa, jeśli zrobisz to dobrze, zrobiłem to, spójrz na HTTP API, codex.wordpress.org/HTTP_API
Wyck
Właśnie zacząłem od nowa. Do tej pory podłączyłem się do sprawdzania aktualizacji wtyczek za pomocą add_filter("pre_set_site_transient_update_plugins","dne_altapi_check"); Po tym mam funkcję dne_altapi_check, która zawiera print_r("hi");- jednak gdy kliknę przycisk „Sprawdź ponownie” w ramach aktualizacji, to w ogóle nic nie drukuje .. Czy jestem robisz coś złego po podłączeniu do modułu sprawdzania aktualizacji?
Simon
Pamiętam, że ktoś napisał klasę dla personelu aktualizującego wtyczki, ale może znaleźć link do tego postu: /
Mamaduka
1

Istnieje komercyjny menedżer wtyczek i aktualizacji interfejsu API aktualizacji dla WooCommerce, który działa szczególnie, jeśli wtyczka lub motyw nie są hostowane na wordpress.org. Został zaprojektowany w celu dostarczania aktualizacji dla wtyczek i motywów na własnym serwerze. Wtyczka jest przeznaczona dla tych, którzy nie chcą pisać samodzielnie i potrzebują wielu funkcji, a także działających przykładów sprzedawanych wtyczek i motywów.

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

Todd Lahman
źródło
1

Istnieje również schludna usługa na http://wp-updates.com/ - dostajesz jeden motyw lub wtyczkę za darmo. Do Twojej wiadomości - to nie jest moja strona, ale próbowałem już jakiś czas temu i wyglądało całkiem nieźle.

cwd
źródło
Wydaje się miłą usługą, ale nie zauważyłem (prawie na bezpłatnym planie) HTTPS w panelu sterowania ani w komunikacji: ponadto nie znalazłem żadnej kontroli własności podczas sprawdzania aktualizacji (wydaje mi się to bardzo proste Żądanie POST), uważam, że można to ukraść, znając nazwę wtyczki i zgadując. Z przyjemnością bym go użył, gdyby ze względów bezpieczeństwa wydawało się to bardziej profesjonalne.
reallynice
1

W przypadku instalacji w pojedynczej witrynie (nie testowałem jej w wielu witrynach), musisz tylko zaktualizować dwa serwisy zewnętrzne, takie jak github lub gitlab. W poniższym kodzie używam gitlab, ponieważ właśnie tego używam do hostowania mojego kodu. Prawdopodobnie powinienem wyodrębnić części gitlab ...

Pierwszym hakiem, którego musisz użyć, jest pre_set_site_transient_update_themes. To jest filtr, którego używa WordPress, aby ustawić zmienną site_transient, aby pokazywała, czy są dostępne aktualizacje. Użyj tego haka, aby połączyć się ze zdalną wersją i sprawdzić, czy są dostępne aktualizacje. Jeśli tak, zmodyfikuj stan przejściowy, aby WordPress wiedział, że istnieją aktualizacje i mógł wyświetlić powiadomienie użytkownikowi.

Drugi haczyk, którego musisz użyć, to upgrader_source_selection. Ten filtr jest potrzebny, w każdym razie dla gitlab, ponieważ nazwa pobranego folderu nie jest taka sama jak motyw, więc używamy tego haka, aby zmienić nazwę na prawidłową nazwę. Jeśli Twoje zdalne repozytorium zapewnia zip z prawidłową nazwą, to nawet nie potrzebujesz tego haka.

Trzeci, opcjonalny zaczep, którego możesz użyć, to auto_update_themeautomatyczna aktualizacja motywu. W poniższym przykładzie używam tego haka, aby automatycznie zaktualizować tylko ten konkretny motyw.

Ten kod został przetestowany tylko z WordPress 4.9.x. Wymaga 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
źródło