Jak niezawodnie opróżnić przepisy przepisywania na wielu stronach?

20

Załóżmy, że masz wtyczkę, która musi opróżnić reguły przepisywania. Wszystko robisz poprawnie z hakiem aktywacyjnym i późnym spłukiwaniem, więc wszystko jest płynne i kompatybilne.

A potem pewnego pięknego dnia ktoś próbuje uruchomić go na wielu stronach.

Zamiast prostych scenariuszy, takich jak:

  1. Witryna WordPress została utworzona
  2. Wtyczka jest zainstalowana i aktywowana

Masz teraz koszmarne scenariusze, takie jak:

  1. Wtyczka jest zainstalowana i aktywowana przez sieć
  2. Utworzono nową witrynę WordPress (lub sto) w wielu witrynach

Teoretycznie powinien po prostu działać, prawda? W praktyce dzieje się to w spektakularny sposób:

  • $wp_rewrite stan może pochodzić z niewłaściwej strony
  • switch_to_blog() nie śledzi również stanu przepisania
  • „późniejsza” część może się całkowicie wydarzyć na innym blogu
  • wszystkie inne wtyczki, z którymi powinieneś się dobrze bawić, mogą nie być konsekwentnie włączane na różnych stronach

Na przykład możesz zobaczyć ten problem, w jaki sposób próba zrobienia tego od razu wysuwa bezpośrednie linki na głównej stronie za każdym razem, gdy tworzona jest nowa strona .

Więc w jaki sposób wtyczka działałaby niezawodnie opróżniając reguły przepisywania w wielu miejscach :

  1. Kiedy tworzona jest nowa witryna, dla witryny?
  2. Kiedy istniejąca witryna jest aktywowana z nieaktywnej, dla witryny?
  3. Kiedy wtyczka jest aktywowana przez sieć, dla każdej witryny?
  4. Kiedy wtyczka jest wyłączona w sieci, dla każdej witryny?
  5. Być może w innych scenariuszach, które wymagają zmiany przepisywania globalnego kontekstu?
Rarst
źródło

Odpowiedzi:

11

Uwaga: jest to niepełna odpowiedź, która będzie stopniowo rozszerzana


Jedynym niezawodnym sposobem na opróżnienie reguł przepisywania w wielu witrynach, bez potencjalnego zniszczenia struktury bezpośredniego łącza w głównym i / lub innym kontekście blogu (w zależności od tego, jak i co przełączasz się na i z) jest opróżnienie reguł przepisywania w danym kontekście, takim jak ten :

global $wp_rewrite;
$wp_rewrite->init(); //important...
$wp_rewrite->flush_rules();

Powyższe zapewnia, że ​​poprawna struktura bezpośredniego łącza dla danego kontekstu jest pobierana i ustawiana przed zbudowaniem reguł przepisywania i zatwierdzeniem zmian w bazie danych.

Nie dotyczy to pojedynczej witryny, w której kontekst nie ma znaczenia, ponieważ istnieje tylko jeden kontekst.

flush_rewrite_rules()moim zdaniem błędne jest założenie, że zakłada właściwy kontekst, ale nie bierze pod uwagę naszego użycia, switch_to_blogdla którego całkowicie zmienia kontekst i pozostawia nas na niebezpiecznym terytorium, jeśli spróbujemy potencjalnie opróżnić reguły.

Tak wyglądają elementy wewnętrzne flush_rewrite_rules():

function flush_rewrite_rules( $hard = true ) {
    global $wp_rewrite;
    $wp_rewrite->flush_rules( $hard );
}

Nie mogę wymyślić powodu, dla którego nie powinien wyglądać tak:

function flush_rewrite_rules( $hard = true ) {
    global $wp_rewrite;
    $wp_rewrite->init(); //hello....
    $wp_rewrite->flush_rules( $hard );
}

... zwłaszcza gdy weźmiesz pod uwagę, że konstruktor WP_Rewriterobi co? Robi to ...

public function __construct() {
    $this->init();
}

Dotykając pierwszego punktu zainteresowania, aby kontynuować tę linię,

Więc w jaki sposób plugin go o wiarygodnie spłukiwania przepisywania zasad w wielu serwerach :

  • Kiedy tworzona jest nowa witryna, dla witryny?

Spójrzmy na to, co rdzeń WordPress wywoła podczas tego procesu:

  • pierwszy wpmu_create_blog()
  • który następnie wzywa, install_blog()który z kolei wzywapopulate_options()
  • następnie populate_options()ustawia domyślną strukturę bezpośredniego łącza w tabeli opcji
  • po install_blog()biegnie, wp_install_defaults()a następnie zostaje wywołany
  • następnie wp_install_defaults()opróżnia reguły przepisywania nowo utworzonej witryny, zanim ostatecznie przełączy się z powrotem na bieżący blog za pośrednictwem restore_current_blog().

Należy zauważyć, że wp_install_defaults()zasady flush są dokładnie takie, jak zasugerowałem powyżej:

$wp_rewrite->init();
$wp_rewrite->flush_rules();

... ponieważ jest to jedyny sposób, aby upewnić się, że permalink_structurereguły i reguły są budowane dla bieżącego kontekstu.

Również w problemie potwierdzonym w ramach problemu Github powód, dla którego użytkownik doświadczył następującego zachowania:

Kiedy tworzona jest nowa witryna, łamie ona linki bezpośrednie na poziomie postu tylko w witrynie najwyższego poziomu - w większości konfiguracji permalink, ale nie we wszystkich:

Te 2 formaty działają poprawnie.

Domyślnie - działa zgodnie z oczekiwaniami

Dzień i nazwisko - działa zgodnie z oczekiwaniami

... ponieważ główny blog ma strukturę permalink Day & Name /%year%/%monthnum%/%day%/%postname%/, gdy tworzona jest nowa witryna, również /%year%/%monthnum%/%day%/%postname%/domyślnie ma strukturę permalink Day & Name, dlatego żaden znaczący problem nie pojawia się, gdy wtyczka Yoast SEO przepisze od nowa rządzi na shutdownhaku.

Adam
źródło
Brzmi dobrze. Przy instalowaniu nowej witryny irytujące jest to, że nie można zaczepić podczas procesu, tylko po jego zakończeniu. Z tego powodu zasady zostaną dwukrotnie usunięte.
Anton Timmermans
Kończy się czas nagród, więc tutaj punkty za upadek na miecz. :) Jednak wciąż wiele do zrobienia. :(
Rarst
Czy nie można ręcznie ustawić kontekstu $wp_rewrite, aby można było przeglądać i resetować każdą witrynę sieciową? Mam dużą witrynę sieciową, która cierpi na pewne problemy z permalink na niestandardowych wtyczkach. Tworzenie wtyczki, która dodaje crona, wydaje się przesadne, ponieważ zawsze je resetuje. Pętla z niestandardowym adresem URL byłaby idealna, ale nie wiem, jak to zrobić dla wszystkich witryn.
Adam Patterson