如何自行託管 WordPress 外掛 / 佈景主題更新

關於付費外掛的更新部署,我都是透過 Appsero 來完成,其他類似的服務還有 Freemius,如果是免費外掛的話可以直接上架 WordPress(.)org 進行託管,那麼在什麼情境下會需要自行託管呢?

如果你跟我一樣遇到上述服務不適合你的使用情境,又不想為了上架 .org 而花費時間去符合規範,又或者是你希望設計自己的更新流程而不想用別人寫好的框架,那麼這篇文章提及的工具可以作為一個基礎架構,了解整個程式碼的運作邏輯後,可以根據需求再自行客製化,這樣就不用被第三方服務所約束。

我的情境很單純:讓使用者可以在 WordPress 後台外掛頁面更新我所提供的免費外掛。

一、事前準備

需要一個主機空間存放外掛的資訊檔以及新版外掛的 zip 檔,可以使用 Dropbox 或是 Google 雲端硬碟之類的空間,也可以放在自己的伺服器上,我最推薦的是放在 Github,這樣就可以跟版本控管的流程整合。

外掛資訊檔是一個 JSON 格式的文件,範例如下:

{
	"name": "My Plugin",
	"slug": "my-plugin",
	"author": "<a href='https://mydomain.com/my-plugin/'>Author</a>",
	"author_profile": "https://mydomain.com",
	"version": "1.0.1",
	"download_url": "https://mydomain.com/my-plugin.zip",
	"requires": "5.6",
	"tested": "6.2.2",
	"requires_php": "7.4",
	"added": "2021-04-05 00:00:00",
	"last_updated": "2023-06-29 00:00:00",
	"homepage": "https://mydoamin.com",
	"sections": {
	  "description": "My plugin description",
	  "installation": "My plugin installation",
	  "changelog": "<p>v1.0.1</p><p>Change log</p>"
	},
	"banners": {
	  "low": "https://mydomain.com/my-plugin-banner-low.jpg",
	  "high": "https://mydomain.com/my-plugin-banner-high.jpg"
	}
}

這份檔案可以命名為 my-plugin.json 然後放在自己的空間,上傳後的路徑我們會拿來作為取得新版外掛的依據,該資訊檔的關鍵是 version 以及 download_url 這兩個參數。如果要推播新的更新通知,只要把 version 版本號升版即可。

download_url 是新版外掛的下載位置,如果放在 Github 上面的話可以使用 Release 來產出 zip,搭配 Github Actions 還可以自動打包不用手動處理。

二、更新邏輯與相關技術

處理 WordPress 外掛主要有三個勾點,分別是 plugins_apisite_transient_update_plugins 以及 upgrader_process_complete。WordPress 判斷是否有外掛需要更新依賴的是資料庫暫存 Transient API。

wp_options 資料表裡面有一個 _site_transient_update_plugins 欄位,裡面以序列化的方式記錄了所有外掛的相關資訊。其中一個參數叫做 new_version,當 WordPress 讀到我們的外掛版本小於 new_version 時就會觸發更新通知,並且以 package 參數中的網址作為新版外掛的下載連結:

當使用者進入 WordPress 後台的外掛頁或是更新頁時,會觸發 get_transient() 方法,其中勾點 site_transient_update_plugins 就可以拿來修改上面這一堆序列化的內容,具體的邏輯是:

  1. site_transient_update_plugins 裡面取得放在我們主機上的外掛資訊檔 my-plugin.json
  2. 檢查 my-plugin.json 中的 version 是否比目前外掛的版本號高
  3. 是的話取得 my-plugin.json 中的 versiondownload_url 資訊
  4. 改寫 _site_transient_update_pluginsmy-pluginnew_verisonpacekage
  5. 使用者收到外掛的更新通知並點擊更新

簡化過後的程式碼如下:

<?php

add_filter(
	'site_transient_update_plugins',
	function( $transient ) {

		// 步驟一
		$remote = wp_remote_get(
			'https://mydomain.com/my-plugin.json',
			array(
				'timeout' => 60,
				'headers' => array(
					'Accept' => 'application/json',
				),
			)
		);

		if ( is_wp_error( $remote ) || 200 !== wp_remote_retrieve_response_code( $remote ) || empty( wp_remote_retrieve_body( $remote ) ) ) {
			return false;
		}

		$remote = json_decode( wp_remote_retrieve_body( $remote ) );

		// 步驟二
		if ( $remote &&
			version_compare( '1.0.0', $remote->version, '<' ) &&
			version_compare( $remote->requires, get_bloginfo( 'version' ), '<=' ) &&
			version_compare( $remote->requires_php, PHP_VERSION, '<' )
		) {
			// 步驟三&四
			$response              = new \stdClass();
			$response->slug        = 'my-plugin';
			$response->plugin      = 'my-plugin/my-plugin.php';
			$response->new_version = $remote->version;
			$response->package     = $remote->download_url;

			$transient->response[ $response->plugin ] = $response;

		}

		return $transient;

	}
);

需要注意的是步驟二的第二個判斷是 version_compare( '1.0.0', $remote->version, '<' ) 的第一個參數要換成你目前外掛的版本號,通常我會用常數來定義,這樣在更版時就會比較好控制,第三與第四個判斷是檢查使用者的 WordPress 與 PHP 版本,要符合 my-plugin.json 裡面定義的最低版本要求才會收到更新通知。

三、Composer 套件

除了主要的更新機制外,還有顯示新版資訊以及更新檔安裝完成後的處理,完整的程式碼可以參考 Misha Rudrastyh 大大的文章,為了方便使用,我把它加以整理後做成 Composer 套件,使用方法如下:

透過 Composer 進行安裝:

$ composer require oberonlai/wp-updater

使用時建立 Updater 物件並提供三個參數,分別是外掛代稱、目前外掛版本以及外掛資訊檔的下載路徑:

<?php

$updater = new ODS\Updater( array(
	'plugin_slug' => 'my-plugin',
	'version'     => '1.0.0',
	'json_url'    => 'https://mydomain.com/my-plugin.json',
));

另外我還在外掛更新後增加了一個勾點 ods_updater_after_purge,這是讓開發者可以在外掛更新完成後加入一些任務的處理,像是更新資料表、跳出提醒通知等行為,都可以透過該勾點進行處理。

具體用法可以參考 Github 存放庫的說明:https://github.com/oberonlai/wp-updater

有個這個框架後接下來要託管付費外掛也能以此基礎繼續發展下去,像是在外掛下載連結可以帶入序號,當伺服器收到請求後就可以驗證該序號是否由已授權的網站發出的,確認沒問題才能下載,也可以整合私有存放庫讓部署流程更加自動化,這部分待日後實作後再分享出來~

文章標籤composerwp-updater

目錄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

賴俊吾 / Oberon Lai
賴俊吾 / Oberon Lai

現為全職 WordPress 工程師,網站開發經歷 11 年,專攻前端工程與 WordPress 佈景主題、外掛客製化開發

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!

專注於分享 WordPress 開發、接案技巧、專案管理等自由工作者必備知識與心得

© 2024 想點創意科技有限公司

想點創意科技有限公司 | 統一編號 90516823
Designed by Hend Design | 隱私權政策

訂閱電子報

Hi,我是 Oberon,我會固定在每週五早上發送接案心得以及與 WordPress 相關的電子報,同時也會分享一些實用的開發知識,讓你在 WordPress 的接案路上不孤單!