Uw plug-ins distribueren in GitHub met automatische updates

WordPress heeft het handig gemaakt voor plug-ins om te worden ingezet voor het publiek. Plaats gewoon uw plug-in in de WordPress plug-inrepository en deze kan eenvoudig gevonden worden door mensen binnen hun dashboard.

Waarschijnlijk een van de beste functies van de repository is dat het eenvoudig is om plug-ins vanuit het dashboard bij te werken. Update-meldingen worden weergegeven in het dashboard en het uitvoeren van een update is net zo eenvoudig als klikken op de Update nu knop.

Maar hoe zou het zijn als u de plug-in zelf wilde hosten? De handige update-functie is niet beschikbaar als u uw plug-in huurt buiten de plug-in voor WordPress-plug-ins. Uw gebruikers worden ook niet op de hoogte gebracht van een beschikbare update.

In dit artikel leer je dat je met een beetje creatieve codering je eigen WordPress-plug-ins in GitHub kunt hosten, terwijl je nog steeds de automatische updatefunctie behoudt.

Waarom Host Plugin in GitHub?

Er kunnen een aantal redenen zijn waarom u uw plug-in zou willen hosten buiten de opslagplaats van WordPress plug-ins. Een van de belangrijkste beperkingen die de repository biedt, is dat u uw plug-in als GPLv2 licentieert. Ik zal niet stilstaan ​​bij de details van licenties, maar in een notendop betekent dit dat iedereen uw werk kan delen. Dus als u uw plug-in wilt verkopen, dan is hosting in een privé GitHub-repository nu een optie die u kunt overwegen.

Echter, vanwege de manier waarop WordPress werd gebouwd, zou het hosten van uw plug-in in GitHub dat wel zijn automatische updates uitschakelen voor onze plug-in. Om te begrijpen waarom dit het geval is, moeten we begrijpen hoe WordPress plug-insupdates verwerkt.

U kunt meer leren over de WordPress-repository door hun gedetailleerde pluginrichtlijnen te lezen.

Hoe WordPress plug-ins bijwerkt

Laten we eerst eens kijken hoe WordPress plug-insupdates uitvoert om een ​​beter begrip te krijgen van waarom zelf-gehoste plug-ins geen automatische updates kunnen hebben

WordPress controleert periodiek de WordPress-opslagplaats voor updates van uw geïnstalleerde plug-ins. Het ontvangt een heleboel informatie over elke plug-in, zoals de nieuwste versie en de URL van het pakket van de plug-in. Dit zien we meestal op de beheerpagina van plug-ins wanneer we op de hoogte worden gesteld van een update:

Wanneer we op klikken Bekijk versie x.x details link, WordPress voert nog een zoekopdracht uit in de plug-in repo. Deze keer krijgt het meer gedetailleerde informatie over de plug-in, zoals de beschrijving, het changelog, welke WordPress-versie is getest en nog veel meer. Deze informatie wordt ons getoond in een lightbox:

Ten slotte, wanneer de Update nu link is geklikt, het bijgewerkte plug-in pakket is gedownload en geïnstalleerd.

Dus waarom werken automatische updates niet voor zelf-gehoste plug-ins? Het komt omdat WordPress het probeert te vinden in de WordPress plug-inrepository en het daar niet kan vinden!

Het speelplan

Ons plan is om automatische updates mogelijk te maken met onze door GitHub gehoste plug-in.

Hier is een lijst van wat we moeten doen om het te laten werken:

  • We hebben een manier nodig om plugin-updates in GitHub te implementeren.
  • We moeten de update-meldingen voor de plug-inversie weergeven,
  • Het zou leuk zijn om de details van de plug-in weer te geven wanneer het Bekijk versie x.x details link wordt geklikt.
  • We willen ook de plug-insupdate met succes installeren wanneer de update nu link wordt geklikt,

Hoe het plan uit te voeren

We zullen enkele WordPress-filters gebruiken om ons gameplan te implementeren. Dit zijn:

  • pre_set_site_transient_update_plugins. Dit filter wordt aangeroepen wanneer WordPress probeert te controleren op plug-insupdates.
  • plugins_api. Deze wordt gebruikt wanneer WordPress de updategegevens van de plug-in toont.
  • upgrader_post_install. Ten slotte wordt dit genoemd nadat een plug-in met succes is geïnstalleerd.

We gaan deze filters gebruiken en vervolgens onze gegevens in de resultaten pushen om WordPress te maken denken dat onze plug-in in de WordPress plugin-repository staat. De gegevens die we zullen invoeren komen uit onze GitHub-repo en moeten de gegevens nabootsen die worden gegeven door de plug-inrepository.

Het GitHub-project opzetten

Voordat we verder gaan met coderen, laten we het eerst hebben over GitHub en hoe we het zullen gebruiken om de gegevens te verstrekken die we nodig hebben om WordPress te voeden.

Je hebt een private of een openbare GitHub-repository nodig. Uw repo moet al uw plugin-bestanden bevatten en geen gecomprimeerde kopie van uw plug-in.

We zullen een coole feature van GitHub gebruiken genaamd Releases.

Het goede aan releases is dat het de huidige codebase in de repository krijgt en een downloadbaar zip-bestand maakt voor elke specifieke release. We kunnen WordPress vertellen om dit zipbestand te downloaden bij het updaten van onze plug-in.

Een ander voordeel van Releases is dat we onze plug-in-updategegevens in de release-opmerkingen kunnen opnemen. We kunnen dit vervolgens parseren en weergeven in de lightbox WordPress-shows voor details over plug-upupdates. We kunnen verder gaan en zelfs toestaan ​​dat GitHub wordt afgevinkt voor onze changelog.

Wanneer het tijd is om een ​​update naar onze plug-in te implementeren, volg dan de opmaak in de afbeelding hierboven wanneer u een nieuwe release aanmaakt:

  • Tagnaam: Plugin-versie (alleen het nummer)
  • Release-opmerkingen: De beschrijving van de update
Je kunt meer lezen over GitHub-releases in hun artikel Release Your Software

Onze Updater-klasse maken

Nu is het tijd om onze plug-in te coderen!

Eerst maken we het startpunt voor onze klas:

class BFIGitHubPluginUpdater private $ slug; // plugin slug private $ pluginData; // plugin data private $ gebruikersnaam; // GitHub-gebruikersnaam private $ repo; // GitHub repo naam private $ pluginFile; // __FILE__ van onze plugin private $ githubAPIResult; // bevat gegevens van GitHub private $ accessToken; // GitHub private repo token-functie __construct ($ pluginFile, $ gitHubUsername, $ gitHubProjectName, $ accessToken = ") add_filter (" pre_set_site_transient_update_plugins ", array ($ this," setTransitent ")); add_filter (" plugins_api ", array ($ dit, "setPluginInfo"), 10, 3); add_filter ("upgrader_post_install", array ($ this, "postInstall"), 10, 3); $ this-> pluginFile = $ pluginFile; $ this-> username = $ gitHubUsername ; $ this-> repo = $ gitHubProjectName; $ this-> accessToken = $ accessToken; // Ontvang informatie over onze plug-in van WordPress private function initPluginData () // code here // Ontvang informatie over onze plug-in van GitHub private functie getRepoReleaseInfo () // code hier // Push-in-versie-informatie pushen om de updatemelding publieke functie setTransitent ($ transient) // code hier return $ transient; // Push-in versie-informatie in te voeren in de details lightbox publieke functie setPluginInfo ($ false, $ action, $ response) // code eh terugkeer $ antwoord;  // Voer extra acties uit om onze plug-in public function succesvol te installeren postInstall ($ true, $ hook_extra, $ result) // code here return $ result; 

Dit is de klassenstructuur die we gaan gebruiken. We hebben voornamelijk alle functies gedefinieerd die we gaan gebruiken en hebben onze filterhaken gemaakt. Deze klasse doet niets vanaf het moment, behalve om waarden toe te wijzen aan klasseneigenschappen.

The Constructor Arguments

Om onze klasse uit te voeren, hebben we een paar argumenten nodig:

  • $ pluginFile: We zullen deze klasse uit ons hoofd-invoegtoepassingscript noemen, dit zou de waarde moeten hebben __HET DOSSIER__. Hierna krijgen we later meer informatie over onze plug-in.
  • $ gitHubUsername: Uw GitHub-gebruikersnaam
  • $ gitHubProjectName: Uw GitHub-naam van de repository
  • $ accessToken: Een toegangstoken waarmee we de details van een privé GitHub-repo kunnen bekijken. Als uw project wordt gehost in een openbare GitHub-repo, laat dit dan gewoon leeg.

Laten we nu de functies van onze klas vullen met wat code.

Je kunt meer leren over het maken van toegangstokens vanuit GitHub-hulp. U kunt ook lezen hoe de GitHub-API werkt.

De initPluginData Functie

Dit is de eenvoudigste functie in onze klas. We hebben de plug van de plug-in en andere informatie in de rest van het script nodig, dus we zetten de nodige oproepen in een handige functie.

$ this-> slug = plugin_basename ($ this-> pluginFile); $ this-> pluginData = get_plugin_data ($ this-> pluginFile);

De getRepoReleaseInfo Functie

Deze functie heeft alles te maken met communiceren met GitHub om onze release-informatie te krijgen. We zullen de GitHub API gebruiken om details te krijgen over onze nieuwste release. Bewaar vervolgens alles wat we in onze githubAPIResult eigendom voor toekomstige verwerking.

De pre_set_site_transient_update_plugins filter wordt twee keer aangeroepen door WordPress, een keer wanneer het controleert op plug-insupdates en vervolgens nog een nadat het resultaten heeft opgeleverd. Omdat we deze functie in dat filter gebruiken, zouden we de GitHub API twee keer ondervragen. We hoeven slechts één keer informatie van GitHub te ontvangen:

// Doe dit slechts één keer als (! Empty ($ this-> githubAPIResult)) return; 

Vervolgens zullen we de GitHub API gebruiken om informatie te krijgen over onze releases:

// Query de GitHub API $ url = "https://api.github.com/repos/$this->username/$this->repo/ releases"; // We hebben de toegangstoken nodig voor privéreposities als (! Empty ($ this-> accessToken)) $ url = add_query_arg (array ("access_token" => $ this-> accessToken), $ url);  // Verkrijg de resultaten $ this-> githubAPIResult = wp_remote_retrieve_body (wp_remote_get ($ url)); if (! empty ($ this-> githubAPIResult)) $ this-> githubAPIResult = @json_decode ($ this-> githubAPIResult); 

Ten slotte bewaren we alleen de gegevens voor de laatste release van de plug-in:

// Gebruik alleen de nieuwste release if (is_array ($ this-> githubAPIResult)) $ this-> githubAPIResult = $ this-> githubAPIResult [0]; 

Nu kunnen we onze plugin-gegevens ophalen van GitHub. We zullen deze gegevens ontleden in de volgende functies.

De setTransitent Functie

Deze functie wordt aangeroepen wanneer WordPress controleert op updates voor plug-ins. Het is onze taak om onze GitHub-releasegegevens te gebruiken om informatie te bieden voor onze plug-inupdate.

Het eerste wat we doen is controleren of WordPress al eerder op plug-insupdates heeft gecontroleerd. Als dit het geval is, hoeven we de rest van de functie niet opnieuw uit te voeren.

// Als we de plugin-gegevens eerder hebben gecontroleerd, controleer dan niet of (leeg ($ transient-> checked)) return $ transient; 

Vervolgens krijgen we de plugin-informatie die we gaan gebruiken:

// Haal plug-in en GitHub-release-informatie $ this-> initPluginData (); $ This-> getRepoReleaseInfo ();

Nadat we deze twee functies hebben aangeroepen, kunnen we de versie van onze lokale plug-in controleren aan de hand van de versie (de naam van de tag) in GitHub. We kunnen PHP's handig gebruiken version_compare functie om de twee waarden te vergelijken:

// Controleer de versies als we een update moeten doen $ doUpdate = version_compare ($ this-> githubAPIResult-> tag_name, $ transient-> checked [$ this-> slug]);

Ten slotte is er een update voor plug-ins beschikbaar. We moeten de beheerder vragen om een ​​updatemelding weer te geven. We doen dit door de $ voorbijgaande variabele met onze bijgewerkte plugin-informatie.

// Werk de transient bij met onze bijgewerkte plug-ingegevens als ($ doUpdate == 1) $ package = $ this-> githubAPIResult-> zipball_url; // Neem het toegangstoken op voor privé GitHub-repos als (! Empty ($ this-> accessToken)) $ package = add_query_arg (array ("access_token" => $ this-> accessToken), $ package);  $ obj = nieuwe stdClass (); $ obj-> slug = $ this-> slug; $ obj-> new_version = $ this-> githubAPIResult-> tag_name; $ obj-> url = $ this-> pluginData ["PluginURI"]; $ obj-> pakket = $ pakket; $ transient-> response [$ this-> slug] = $ obj;  return $ transient;

Nadat deze functie onze GitHub-informatie verwerkt, kan onze beheerder meldingen weergeven op de beheerpagina van de plug-in:

De setPluginInfo Functie

Het doel van deze functie is om informatie te verzamelen over de bijgewerkte plug-in uit de release-opmerkingen. Al deze informatie wordt weergegeven in een lightbox wanneer de Bekijk versie x.x details link wordt geklikt.

Laten we eerst onze plugin-informatie ophalen:

// Haal plug-in en GitHub-release-informatie $ this-> initPluginData (); $ This-> getRepoReleaseInfo ();

Vervolgens controleren we of het tijd is om iets weer te geven. We kunnen controleren of we proberen informatie voor onze huidige plug-in te laden door de naaktslak:

// Als niets wordt gevonden, doe niets als (leeg ($ antwoord-> naaktslak) || $ antwoord-> slug! = $ This-> slug) return false; 

Om onze plug-in gegevens weer te geven, moeten we onze plug-in informatie handmatig toevoegen aan de $ response variabele, normaal zou deze variabele worden gevuld met de resultaten van de WordPress plug-inrepository:

// Voeg onze plugininformatie toe $ response-> last_updated = $ this-> githubAPIResult-> published_at; $ response-> slug = $ this-> slug; $ response-> plugin_name = $ this-> pluginData ["Name"]; $ response-> version = $ this-> githubAPIResult-> tag_name; $ response-> author = $ this-> pluginData ["AuthorName"]; $ response-> homepage = $ this-> pluginData ["PluginURI"]; // Dit is ons download zipbestand voor downloads $ downloadLink = $ this-> githubAPIResult-> zipball_url; // Neem de toegangstoken op voor privé GitHub-repos als (! Empty ($ this-> accessToken)) $ downloadLink = add_query_arg (array ("access_token" => $ this-> accessToken), $ downloadLink);  $ response-> download_link = $ downloadLink;

Tot nu toe hebben we onze plug-in gegevens toegevoegd, maar we hebben onze release-opmerkingen nog niet geparseerd uit onze GitHub-release. Laten we eens kijken wat we hebben in onze release-opmerkingen:

In de release-opmerkingen hebben we drie details over onze release gespecificeerd: onze changelog, gevolgd door de minimaal vereiste WordPress-versie en vervolgens de nieuwste WordPress-versie waarin de plug-in is getest. We gaan deze tekst analyseren en deze waarden extraheren.

Omdat we onze plug-in in GitHub hosten, zou het fijn zijn als we de mogelijkheid hebben om GitHub-prijsvermindering te gebruiken in onze release-informatie. Ik ga een PHP-klasse gebruiken genaamd ParseDown om de markdown-tekst naar HTML te converteren:

// We gaan de GitHub markdown release-opmerkingen analyseren, inclusief de parser require_once (plugin_dir_path (__FILE__). "Parsedown.php");

We gaan ook tabbladen maken in de lightbox om het in overeenstemming te brengen met hoe de door WordPress repository gehoste plug-ins hun informatie weergeven. De ene is voor de plugin-beschrijving en de andere is voor onze changelog:

// Maak tabbladen in de lightbox $ response-> sections = array ('description' => $ this-> pluginData ["Description"], 'changelog' => class_exists ("Parsedown")? Parsedown :: instance () - > ontleed ($ this-> githubAPIResult-> body): $ this-> githubAPIResult-> body);

Eindelijk gaan we de waarden ophalen voor de vereist en getest:

// Krijgt de vereiste versie van WP indien beschikbaar $ overeenkomt = null; preg_match ("/requires:\s([\d\.]+)/i", $ this-> githubAPIResult-> body, $ matches); if (! empty ($ matches)) if (is_array ($ matches)) if (count ($ matches)> 1) $ response-> vereist = $ matches [1];  // Krijgt de geteste versie van WP indien beschikbaar $ overeenkomt = null; preg_match ("/tested:\s([\d\.]+)/i", $ this-> githubAPIResult-> body, $ matches); if (! empty ($ matches)) if (is_array ($ matches)) if (count ($ matches)> 1) $ response-> tested = $ matches [1];  antwoord $ antwoord;

De postinstall Functie

Deze laatste functie zullen we behandelen met het uitvoeren van aanvullende processen die we nodig hebben om onze plug-in volledig te installeren nadat deze is gedownload.

Wanneer u een release voor onze GitHub-repo maakt, wordt er automatisch een zipbestand voor die specifieke release gemaakt. De bestandsnaam voor het zipbestand wordt door GitHub met het formaat gegenereerd reponame-tagname.zip. Dit bevat ook een map waarin onze plugin-bestanden zich bevinden. Evenzo volgt de mapnaam hiervan ook het formaat reponame-tagname.

Normaal gesproken, als WordPress een plug-insarchief downloadt en uitpakt, verandert de mapnaam van de plug-in niet. Als de map van de plug-in is mijn-awesome-plugin, na het verwijderen van de oude plugin-bestanden en het uitpakken van de bijgewerkte versie, wordt je directory nog steeds genoemd mijn-awesome-plugin. Maar aangezien GitHub elke keer als we een release ontplooien de directorynaam van onze plug-in verandert, kan WordPress onze plug-in niet vinden. Het zou het nog steeds kunnen installeren, maar het kan het niet opnieuw activeren. We kunnen dit probleem oplossen door de nieuwe map een nieuwe naam te geven die overeenkomt met de oude.

Eerste ding eerst:

// Haal plug-in informatie $ this-> initPluginData ();

Vervolgens moeten we controleren of onze plug-in momenteel is geactiveerd, zodat we deze achteraf opnieuw kunnen activeren:

// Onthoud dat onze plugin eerder geactiveerd was $ wasActivated = is_plugin_active ($ this-> slug);

Nu hernoemen we onze bijgewerkte plugin-map zodat deze overeenkomt met de oude. We gebruiken de functie verhuizing hier, maar omdat we dezelfde directory specificeren, zou het hetzelfde zijn als het hernoemen ervan:

// Aangezien we worden gehost in GitHub, zou onze plugin-map een dirname van // reponame-tagname hebben, verander deze in onze originele: global $ wp_filesystem; $ pluginFolder = WP_PLUGIN_DIR. DIRECTORY_SEPARATOR. dirname ($ this-> slug); $ wp_filesystem-> move ($ result ['destination'], $ pluginFolder); $ result ['destination'] = $ pluginFolder;

De laatste stap zou zijn om de plug-in opnieuw te activeren:

// Activeer plug-in indien nodig als ($ wasActivated) $ activate = activate_plugin ($ this-> slug);  return $ resultaat;

Bellen naar onze GitHub Updater-klasse

Nu de klas klaar is, hoeven we alleen nog maar het bestand in ons hoofdplugin-bestand te bellen:

require_once ('BFIGitHubPluginUploader.php'); if (is_admin ()) nieuwe BFIGitHubPluginUpdater (__FILE__, 'myGitHubUsername', "Repo-Name"); 

Het uitproberen

Dat is het! Neem deze klasse gewoon op en noem hem in uw plug-in, en hij zou automatisch naar updates moeten zoeken.

Om te testen of het werkt, maakt u een nieuwe release voor uw GitHub-repo en volgt u de eerder genoemde richtlijnen:

Nadat u uw release hebt gemaakt, kunt u WordPress dwingen om naar updates te zoeken door op de knop Vernieuwen in de beheerbalk te klikken.

Conclusie

Ik hoop dat je iets hebt geleerd over hoe WordPress werkt en hoe het hele proces van het updaten van plug-ins wordt uitgevoerd. U kunt het volledige script downloaden van de downloadlinks bovenaan dit artikel.

Ik hoop dat je dit artikel leuk vond. Ik stel elke feedback, opmerkingen en suggesties zeer op prijs. Deel je gedachten hieronder!