Wtyczki WordPress można rozszerzyć o dodatkowe funkcje, jak pokazują popularne wtyczki, takie jak WooCommerce i Gravity Forms. W artykule „Architektura wtyczki WordPress w celu obsługi rozszerzeń” dowiadujemy się, że istnieją dwa główne sposoby na rozszerzenie wtyczki WordPress:
- Poprzez skonfigurowanie haków (akcji i filtrów) dla wtyczek rozszerzeń w celu wstrzyknięcia własnej funkcjonalności
- Poprzez udostępnianie klas PHP, które wtyczki rozszerzeń mogą dziedziczyć
Pierwsza metoda opiera się bardziej na dokumentacji, szczegółowo opisując dostępne hooki i ich użycie. Druga metoda, przeciwnie, oferuje gotowy do użycia kod dla rozszerzeń, zmniejszając potrzebę obszernej dokumentacji. Jest to korzystne, ponieważ tworzenie dokumentacji wraz z kodem może komplikować zarządzanie wtyczką i jej wydanie.
Bezpośrednie dostarczanie klas PHP skutecznie zastępuje dokumentację kodem. Zamiast uczyć, jak zaimplementować funkcję, wtyczka dostarcza niezbędny kod PHP, upraszczając zadanie dla zewnętrznych programistów.
Przyjrzyjmy się bliżej kilku technikom osiągnięcia tego celu, mając na celu stworzenie ekosystemu integracji wokół naszej wtyczki WordPress.
Definiowanie podstawowych klas PHP wtyczki WordPress
Wtyczka WordPress będzie zawierać klasy PHP przeznaczone do użytku przez wtyczki rozszerzeń. Te klasy PHP mogą nie być używane przez samą główną wtyczkę, ale są udostępniane specjalnie do użytku przez innych.
Zobaczmy, jak to jest implementowane w oprogramowaniu typu open source Gato GraphQL wtyczka.
Klasa AbstractPlugin:
Wtyczka abstrakcyjna reprezentuje wtyczkę zarówno do głównej wtyczki Gato GraphQL, jak i jej rozszerzeń:
abstract class AbstractPlugin implements PluginInterface { protected string $pluginBaseName; protected string $pluginSlug; protected string $pluginName; public function __construct( protected string $pluginFile, protected string $pluginVersion, ?string $pluginName, ) { $this->pluginBaseName = plugin_basename($pluginFile); $this->pluginSlug = dirname($this->pluginBaseName); $this->pluginName = $pluginName ?? $this->pluginBaseName; } public function getPluginName(): string { return $this->pluginName; } public function getPluginBaseName(): string { return $this->pluginBaseName; } public function getPluginSlug(): string { return $this->pluginSlug; } public function getPluginFile(): string { return $this->pluginFile; } public function getPluginVersion(): string { return $this->pluginVersion; } public function getPluginDir(): string { return dirname($this->pluginFile); } public function getPluginURL(): string { return plugin_dir_url($this->pluginFile); } // ... }
Klasa AbstractMainPlugin:
StreszczenieMainPlugin rozszerza AbstractPlugin o główną wtyczkę:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface { public function __construct( string $pluginFile, string $pluginVersion, ?string $pluginName, protected MainPluginInitializationConfigurationInterface $pluginInitializationConfiguration, ) { parent::__construct( $pluginFile, $pluginVersion, $pluginName, ); } // ... }
Klasa AbstractExtension:
Podobnie, StreszczenieRozszerzenie rozszerza AbstractPlugin o wtyczkę rozszerzającą:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface { public function __construct( string $pluginFile, string $pluginVersion, ?string $pluginName, protected ?ExtensionInitializationConfigurationInterface $extensionInitializationConfiguration, ) { parent::__construct( $pluginFile, $pluginVersion, $pluginName, ); } // ... }
Zauważ, że AbstractExtension jest zawarte w głównej wtyczce, zapewniając funkcjonalność do rejestrowania i inicjowania rozszerzenia. Jest jednak używane tylko przez rozszerzenia, a nie przez samą główną wtyczkę.
Klasa AbstractPlugin zawiera współdzielony kod inicjalizacji wywoływany w różnych momentach. Te metody są definiowane na poziomie przodka, ale są wywoływane przez klasy dziedziczące zgodnie z ich cyklami życia.
Główną wtyczkę i rozszerzenia inicjuje się poprzez wykonanie metody setup w odpowiedniej klasie, wywołanej z głównego pliku wtyczki WordPress.
Na przykład w Gato GraphQL odbywa się to w gatographql.php:
$pluginFile = __FILE__; $pluginVersion = '2.4.0'; $pluginName = __('Gato GraphQL', 'gatographql'); PluginApp::getMainPluginManager()->register(new Plugin( $pluginFile, $pluginVersion, $pluginName ))->setup();
metoda konfiguracji:
Na poziomie przodka setup zawiera wspólną logikę między wtyczką a jej rozszerzeniami, taką jak wyrejestrowanie ich, gdy wtyczka jest dezaktywowana. Ta metoda nie jest ostateczna; może zostać zastąpiona przez klasy dziedziczące, aby dodać ich funkcjonalność:
abstract class AbstractPlugin implements PluginInterface { // ... public function setup(): void { register_deactivation_hook( $this->getPluginFile(), $this->deactivate(...) ); } public function deactivate(): void { $this->removePluginVersion(); } private function removePluginVersion(): void { $pluginVersions = get_option('gatographql-plugin-versions', []); unset($pluginVersions[$this->pluginBaseName]); update_option('gatographql-plugin-versions', $pluginVersions); } }
Metoda konfiguracji głównej wtyczki:
Metoda setup głównej wtyczki inicjuje cykl życia aplikacji. Wykonuje funkcjonalność głównej wtyczki za pomocą metod takich jak initialize, configureComponents, configure i boot, i wyzwala odpowiednie haki akcji dla rozszerzeń:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface { public function setup(): void { parent::setup(); add_action('plugins_loaded', function (): void { // 1. Initialize main plugin $this->initialize(); // 2. Initialize extensions do_action('gatographql:initializeExtension'); // 3. Configure main plugin components $this->configureComponents(); // 4. Configure extension components do_action('gatographql:configureExtensionComponents'); // 5. Configure main plugin $this->configure(); // 6. Configure extension do_action('gatographql:configureExtension'); // 7. Boot main plugin $this->boot(); // 8. Boot extension do_action('gatographql:bootExtension'); } // ... } // ... }
Metoda konfiguracji rozszerzenia:
Klasa AbstractExtension wykonuje swoją logikę na odpowiednich hakach:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface { // ... final public function setup(): void { parent::setup(); add_action('plugins_loaded', function (): void { // 2. Initialize extensions add_action( 'gatographql:initializeExtension', $this->initialize(...) ); // 4. Configure extension components add_action( 'gatographql:configureExtensionComponents', $this->configureComponents(...) ); // 6. Configure extension add_action( 'gatographql:configureExtension', $this->configure(...) ); // 8. Boot extension add_action( 'gatographql:bootExtension', $this->boot(...) ); }, 20); } }
Metody initialize, configureComponents, configure i boot są wspólne dla głównej wtyczki i rozszerzeń i mogą współdzielić logikę. Ta współdzielona logika jest przechowywana w klasie AbstractPlugin.
Na przykład metoda configure konfiguruje wtyczkę lub rozszerzenia, wywołując callPluginInitializationConfiguration, która ma różne implementacje dla głównej wtyczki i rozszerzeń i jest zdefiniowana jako abstract, oraz getModuleClassConfiguration, która zapewnia domyślne zachowanie, ale w razie potrzeby można je zastąpić:
abstract class AbstractPlugin implements PluginInterface { // ... public function configure(): void { $this->callPluginInitializationConfiguration(); $appLoader = App::getAppLoader(); $appLoader->addModuleClassConfiguration($this->getModuleClassConfiguration()); } abstract protected function callPluginInitializationConfiguration(): void; /** * @return array,mixed> [key]: Module class, [value]: Configuration */ public function getModuleClassConfiguration(): array { return []; } }
Główna wtyczka zapewnia implementację dla callPluginInitializationConfiguration:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface { // ... protected function callPluginInitializationConfiguration(): void { $this->pluginInitializationConfiguration->initialize(); } }
Podobnie klasa rozszerzenia zapewnia jego implementację:
abstract class AbstractExtension extends AbstractPlugin implements ExtensionInterface { // ... protected function callPluginInitializationConfiguration(): void { $this->extensionInitializationConfiguration?->initialize(); } }
Metody initialize, configureComponents i boot są zdefiniowane na poziomie przodka i można je zastąpić, dziedzicząc klasy:
abstract class AbstractPlugin implements PluginInterface { // ... public function initialize(): void { $moduleClasses = $this->getModuleClassesToInitialize(); App::getAppLoader()->addModuleClassesToInitialize($moduleClasses); } /** * @return array> List of `Module` class to initialize */ abstract protected function getModuleClassesToInitialize(): array; public function configureComponents(): void { $classNamespace = ClassHelpers::getClassPSR4Namespace(get_called_class()); $moduleClass = $classNamespace . '\\Module'; App::getModule($moduleClass)->setPluginFolder(dirname($this->pluginFile)); } public function boot(): void { // By default, do nothing } }
Wszystkie metody można zastąpić za pomocą AbstractMainPlugin lub AbstractExtension, aby rozszerzyć je o ich własne, niestandardowe funkcjonalności.
W przypadku głównej wtyczki metoda konfiguracji usuwa również całą pamięć podręczną z instancji WordPressa, gdy wtyczka lub dowolne z jej rozszerzeń jest aktywowane lub dezaktywowane:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface { public function setup(): void { parent::setup(); // ... // Main-plugin specific methods add_action( 'activate_plugin', function (string $pluginFile): void { $this->maybeRegenerateContainerWhenPluginActivatedOrDeactivated($pluginFile); } ); add_action( 'deactivate_plugin', function (string $pluginFile): void { $this->maybeRegenerateContainerWhenPluginActivatedOrDeactivated($pluginFile); } ); } public function maybeRegenerateContainerWhenPluginActivatedOrDeactivated(string $pluginFile): void { // Removed code for simplicity } // ... }
Podobnie metoda deactivate usuwa pamięć podręczną, a rozruch wykonuje dodatkowe haki akcji tylko dla głównej wtyczki:
abstract class AbstractMainPlugin extends AbstractPlugin implements MainPluginInterface { public function deactivate(): void { parent::deactivate(); $this->removeTimestamps(); } protected function removeTimestamps(): void { $userSettingsManager = UserSettingsManagerFacade::getInstance(); $userSettingsManager->removeTimestamps(); } public function boot(): void { parent::boot(); add_filter( 'admin_body_class', function (string $classes): string { $extensions = PluginApp::getExtensionManager()->getExtensions(); $commercialExtensionActivatedLicenseObjectProperties = SettingsHelpers::getCommercialExtensionActivatedLicenseObjectProperties(); foreach ($extensions as $extension) { $extensionCommercialExtensionActivatedLicenseObjectProperties = $commercialExtensionActivatedLicenseObjectProperties[$extension->getPluginSlug()] ?? null; if ($extensionCommercialExtensionActivatedLicenseObjectProperties === null) { continue; } return $classes . ' is-gatographql-customer'; } return $classes; } ); } }
Ze wszystkich przedstawionych powyżej kodów jasno wynika, że podczas projektowania i kodowania wtyczki WordPress musimy brać pod uwagę potrzeby jej rozszerzeń i w miarę możliwości ponownie wykorzystywać kod w nich zawarty. Implementacja solidnych wzorców programowania obiektowego (takich jak SOLIDNY zasady) pomagają osiągnąć ten cel, dzięki czemu baza kodu jest łatwa w utrzymaniu w długiej perspektywie.
Deklarowanie i sprawdzanie zależności wersji
Ponieważ rozszerzenie dziedziczy po klasie PHP dostarczonej przez wtyczkę, kluczowe jest sprawdzenie, czy wymagana wersja wtyczki jest obecna. Niewykonanie tego może spowodować konflikty, które spowodują wyłączenie witryny.
Na przykład, jeśli klasa AbstractExtension zostanie zaktualizowana o zmiany powodujące przerwy w działaniu i zostanie wydana wersja główna 4.0.0 z poprzedniej 3.4.0, załadowanie rozszerzenia bez sprawdzenia wersji może spowodować błąd PHP, uniemożliwiając załadowanie WordPressa.
Aby tego uniknąć, rozszerzenie musi sprawdzić, czy zainstalowana wtyczka ma wersję 3.xx. Po zainstalowaniu wersji 4.0.0 rozszerzenie zostanie wyłączone, co zapobiegnie występowaniu błędów.
Rozszerzenie może wykonać tę walidację, korzystając z następującej logiki, wykonywanej w haku plugins_loaded (ponieważ do tego czasu zostanie załadowana główna wtyczka) w główny plik wtyczki rozszerzeniaTa logika uzyskuje dostęp do Menedżer rozszerzeń Klasa, która jest zawarta w głównej wtyczce do zarządzania rozszerzeniami:
/** * Create and set-up the extension */ add_action( 'plugins_loaded', function (): void { /** * Extension's name and version. * * Use a stability suffix as supported by Composer. */ $extensionVersion = '1.1.0'; $extensionName = __('Gato GraphQL - Extension Template'); /** * The minimum version required from the Gato GraphQL plugin * to activate the extension. */ $gatoGraphQLPluginVersionConstraint="^1.0"; /** * Validate Gato GraphQL is active */ if (!class_exists(\GatoGraphQL\GatoGraphQL\Plugin::class)) { add_action('admin_notices', function () use ($extensionName) { printf( '', sprintf( __('Plugin %s is not installed or activated. Without it, plugin %s will not be loaded.'), __('Gato GraphQL'), $extensionName ) ); }); return; } $extensionManager = \GatoGraphQL\GatoGraphQL\PluginApp::getExtensionManager(); if (!$extensionManager->assertIsValid( GatoGraphQLExtension::class, $extensionVersion, $extensionName, $gatoGraphQLPluginVersionConstraint )) { return; } // Load Composer’s autoloader require_once(__DIR__ . '/vendor/autoload.php'); // Create and set-up the extension instance $extensionManager->register(new GatoGraphQLExtension( __FILE__, $extensionVersion, $extensionName, ))->setup(); } );
Zwróć uwagę, jak rozszerzenie deklaruje zależność od ograniczenia wersji ^1.0 głównej wtyczki (używając Ograniczenia wersji kompozytora). Dlatego po zainstalowaniu wersji 2.0.0 Gato GraphQL rozszerzenie nie zostanie aktywowane.
Ograniczenie wersji jest sprawdzane za pomocą metody ExtensionManager::assertIsValid, która wywołuje metodę Semver::satisfies (dostarczoną przez pakiet kompozytor/semver):
use Composer\Semver\Semver; class ExtensionManager extends AbstractPluginManager { /** * Validate that the required version of the Gato GraphQL for WP plugin is installed. * * If the assertion fails, it prints an error on the WP admin and returns false * * @param string|null $mainPluginVersionConstraint the semver version constraint required for the plugin (eg: "^1.0" means >=1.0.0 and <2.0.0) */ public function assertIsValid( string $extensionClass, string $extensionVersion, ?string $extensionName = null, ?string $mainPluginVersionConstraint = null, ): bool { $mainPlugin = \GatoGraphQL\GatoGraphQL\PluginApp::getMainPluginManager()->getPlugin(); $mainPluginVersion = $mainPlugin->getPluginVersion(); if ( $mainPluginVersionConstraint !== null && !Semver::satisfies( $mainPluginVersion, $mainPluginVersionConstraint ) ) { $this->printAdminNoticeErrorMessage( sprintf( __('Extension or bundle %s requires plugin %s to satisfy version constraint %s, but the current version %s does not. The extension or bundle has not been loaded.', 'gatographql'), $extensionName ?? $extensionClass, $mainPlugin->getPluginName(), $mainPluginVersionConstraint, $mainPlugin->getPluginVersion(), ) ); return false; } return true; } protected function printAdminNoticeErrorMessage(string $errorMessage): void { \add_action('admin_notices', function () use ($errorMessage): void { $adminNotice_safe = sprintf( '', $errorMessage ); echo $adminNotice_safe; }); } }
Uruchamianie testów integracyjnych na serwerze WordPress
Aby ułatwić zewnętrznym deweloperom tworzenie rozszerzeń dla Twoich wtyczek, udostępnij im narzędzia do tworzenia i testowania, w tym przepływy pracy dla procesów ciągłej integracji i ciągłego dostarczania (CI/CD).
Podczas tworzenia każdy może łatwo uruchomić serwer WWW za pomocą DevKinsta, zainstalować wtyczkę, dla której koduje rozszerzenie, i natychmiast sprawdzić, czy rozszerzenie jest zgodne z wtyczką.
Aby zautomatyzować testowanie podczas CI/CD, musimy mieć serwer WWW dostępny przez sieć dla usługi CI/CD. Usługi takie jak InstaWP mogą utworzyć witrynę typu sandbox z zainstalowanym WordPressem w tym celu.
Jeśli baza kodu rozszerzenia jest hostowana w GitHub, programiści mogą używać GitHub Actions do uruchamiania testów integracyjnych względem usługi InstaWP. Poniższy przepływ pracy instaluje rozszerzenie na stronie testowej InstaWP (obok najnowszej stabilnej wersji głównej wtyczki), a następnie uruchamia testy integracyjne:
name: Integration tests (InstaWP) on: workflow_run: workflows: [Generate plugins] types: - completed jobs: provide_data: if: ${{ github.event.workflow_run.conclusion == 'success' }} name: Retrieve the GitHub Action artifact URLs to install in InstaWP runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: php-version: 8.1 coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: "ramsey/composer-install@v2" - name: Retrieve artifact URLs from GitHub workflow uses: actions/github-script@v6 id: artifact-url with: script: | const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: context.payload.workflow_run.id, }); const artifactURLs = allArtifacts.data.artifacts.map((artifact) => { return artifact.url.replace('https://api.github.com/repos', 'https://nightly.link') + '.zip' }).concat([ "https://downloads.wordpress.org/plugin/gatographql.latest-stable.zip" ]); return artifactURLs.join(','); result-encoding: string - name: Artifact URL for InstaWP run: echo "Artifact URL for InstaWP - ${{ steps.artifact-url.outputs.result }}" shell: bash outputs: artifact_url: ${{ steps.artifact-url.outputs.result }} process: needs: provide_data name: Launch InstaWP site from template 'integration-tests' and execute integration tests against it runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: php-version: 8.1 coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: "ramsey/composer-install@v2" - name: Create InstaWP instance uses: instawp/wordpress-testing-automation@main id: create-instawp with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} INSTAWP_TOKEN: ${{ secrets.INSTAWP_TOKEN }} INSTAWP_TEMPLATE_SLUG: "integration-tests" REPO_ID: 25 INSTAWP_ACTION: create-site-template ARTIFACT_URL: ${{ needs.provide_data.outputs.artifact_url }} - name: InstaWP instance URL run: echo "InstaWP instance URL - ${{ steps.create-instawp.outputs.instawp_url }}" shell: bash - name: Extract InstaWP domain id: extract-instawp-domain run: | instawp_domain="$(echo "${{ steps.create-instawp.outputs.instawp_url }}" | sed -e s#https://##)" echo "instawp-domain=$(echo $instawp_domain)" >> $GITHUB_OUTPUT - name: Run tests run: | INTEGRATION_TESTS_WEBSERVER_DOMAIN=${{ steps.extract-instawp-domain.outputs.instawp-domain }} \ INTEGRATION_TESTS_AUTHENTICATED_ADMIN_USER_USERNAME=${{ steps.create-instawp.outputs.iwp_wp_username }} \ INTEGRATION_TESTS_AUTHENTICATED_ADMIN_USER_PASSWORD=${{ steps.create-instawp.outputs.iwp_wp_password }} \ vendor/bin/phpunit --filter=Integration - name: Destroy InstaWP instance uses: instawp/wordpress-testing-automation@main id: destroy-instawp if: ${{ always() }} with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} INSTAWP_TOKEN: ${{ secrets.INSTAWP_TOKEN }} INSTAWP_TEMPLATE_SLUG: "integration-tests" REPO_ID: 25 INSTAWP_ACTION: destroy-site
Ten przepływ pracy umożliwia dostęp do .zamek błyskawiczny plik przez Nocny linkusługa umożliwiająca dostęp do artefaktu z poziomu GitHub bez konieczności logowania, co upraszcza konfigurację InstaWP.
Wydanie wtyczki rozszerzenia
Możemy udostępnić narzędzia ułatwiające udostępnianie rozszerzeń, automatyzując procedury w jak największym stopniu.
Ten Konstruktor Monorepo jest biblioteką do zarządzania dowolnym projektem PHP, w tym wtyczką WordPress. Dostarcza polecenie monorepo-builder release do wydania wersji projektu, zwiększając albo główny, albo poboczny, albo poprawkowy komponent wersji zgodnie z wersjonowanie semantyczne.
To polecenie wykonuje serię pracownicy zwalniającyktóre są klasami PHP wykonującymi określoną logikę. Domyślne procesy robocze obejmują jeden, który tworzy tag git z nową wersją i drugi, który przesyła tag do zdalnego repozytorium. Niestandardowe procesy robocze można wstrzykiwać przed, po lub pomiędzy tymi krokami.
Pracownicy wersji są konfigurowani za pomocą pliku konfiguracyjnego:
use Symplify\MonorepoBuilder\Config\MBConfig; use Symplify\MonorepoBuilder\Release\ReleaseWorker\AddTagToChangelogReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushNextDevReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushTagReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\SetCurrentMutualDependenciesReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\SetNextMutualDependenciesReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\UpdateBranchAliasReleaseWorker; use Symplify\MonorepoBuilder\Release\ReleaseWorker\UpdateReplaceReleaseWorker; return static function (MBConfig $mbConfig): void { // release workers - in order to execute $mbConfig->workers([ UpdateReplaceReleaseWorker::class, SetCurrentMutualDependenciesReleaseWorker::class, AddTagToChangelogReleaseWorker::class, TagVersionReleaseWorker::class, PushTagReleaseWorker::class, SetNextMutualDependenciesReleaseWorker::class, UpdateBranchAliasReleaseWorker::class, PushNextDevReleaseWorker::class, ]); };
Możemy dostarczyć niestandardowych pracowników wydań, aby rozszerzyć proces wydawania dostosowany do potrzeb wtyczki WordPress. Na przykład, InjectStableTagVersionInPluginReadmeFileReleaseWorker ustawia nową wersję jako wpis „Tag stabilny” w rozszerzenie przeczytaj mnie.txt plik:
use Nette\Utils\Strings; use PharIo\Version\Version; use Symplify\SmartFileSystem\SmartFileInfo; use Symplify\SmartFileSystem\SmartFileSystem; class InjectStableTagVersionInPluginReadmeFileReleaseWorker implements ReleaseWorkerInterface { public function __construct( // This class is provided by the Monorepo Builder private SmartFileSystem $smartFileSystem, ) { } public function getDescription(Version $version): string { return 'Have the "Stable tag" point to the new version in the plugin\'s readme.txt file'; } public function work(Version $version): void { $replacements = [ '/Stable tag:\s+[a-z0-9.-]+/' => 'Stable tag: ' . $version->getVersionString(), ]; $this->replaceContentInFiles(['/readme.txt'], $replacements); } /** * @param string[] $files * @param array $regexPatternReplacements regex pattern to search, and its replacement */ protected function replaceContentInFiles(array $files, array $regexPatternReplacements): void { foreach ($files as $file) { $fileContent = $this->smartFileSystem->readFile($file); foreach ($regexPatternReplacements as $regexPattern => $replacement) { $fileContent = Strings::replace($fileContent, $regexPattern, $replacement); } $this->smartFileSystem->dumpFile($file, $fileContent); } } }
Dodając InjectStableTagVersionInPluginReadmeFileReleaseWorker do listy konfiguracji, za każdym razem, gdy wykonujesz polecenie wydania monorepo-builder w celu wydania nowej wersji wtyczki, „znacznik Stable” w rozszerzeniu przeczytaj mnie.txt plik zostanie automatycznie zaktualizowany.
Publikowanie wtyczki rozszerzenia w katalogu WP.org
Możemy również rozpowszechnić przepływ pracy, który pomoże w wydaniu rozszerzenia Katalog wtyczek WordPressPodczas oznaczania projektu w zdalnym repozytorium, następujący przepływ pracy opublikuje wtyczkę rozszerzenia WordPress w katalogu:
# See: https://github.com/10up/action-wordpress-plugin-deploy#deploy-on-pushing-a-new-tag name: Deploy to WordPress.org Plugin Directory (SVN) on: push: tags: - "*" jobs: tag: name: New tag runs-on: ubuntu-latest steps: - uses: actions/checkout@master - name: WordPress Plugin Deploy uses: 10up/action-wordpress-plugin-deploy@stable env: SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} SVN_USERNAME: ${{ secrets.SVN_USERNAME }} SLUG: ${{ secrets.SLUG }}
Ten przepływ pracy wykorzystuje 10up/action-wordpress-plugin-wdrażanie akcja, która pobiera kod z repozytorium Git i przesyła go do repozytorium SVN WordPress.org, upraszczając całą operację.
Streszczenie
Tworząc rozszerzalną wtyczkę do WordPressa, naszym celem jest maksymalne ułatwienie jej rozszerzania przez zewnętrznych programistów, maksymalizując w ten sposób szanse na stworzenie dynamicznego ekosystemu wokół naszych wtyczek.
Podczas gdy obszerna dokumentacja może pomóc programistom w rozszerzaniu wtyczki, jeszcze skuteczniejszym podejściem jest dostarczenie niezbędnego kodu PHP oraz narzędzi do tworzenia, testowania i udostępniania rozszerzeń.
Dzięki dołączeniu dodatkowego kodu potrzebnego rozszerzeniom bezpośrednio do naszej wtyczki, upraszczamy proces dla programistów.
Czy planujesz uczynić swoją wtyczkę WordPress rozszerzalną? Daj nam znać w sekcji komentarzy.
Oszczędź czas i koszty, a także zmaksymalizuj wydajność witryny dzięki integracjom na poziomie przedsiębiorstwa o wartości ponad 300 USD zawartym w każdym planie Managed WordPress. Obejmuje to wysokowydajną sieć CDN, ochronę przed atakami DDoS, ochronę przed złośliwym oprogramowaniem i hakowaniem, buforowanie brzegowe i najszybsze maszyny CPU Google. Zacznij bez długoterminowych umów, wspomaganych migracji i 30-dniowej gwarancji zwrotu pieniędzy.
Zapoznaj się z naszymi planami lub porozmawiaj z przedstawicielem handlowym, aby znaleźć plan odpowiedni dla siebie.
Leonardo Losoviz
Leo pisze o innowacyjnych trendach w rozwoju stron internetowych, głównie dotyczących PHP, WordPress i GraphQL. Można go znaleźć na leoloso I twitter.com/losoviz.