{"id":228695,"date":"2022-10-31T10:17:00","date_gmt":"2022-10-31T07:17:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228695"},"modified":"2022-11-09T03:53:09","modified_gmt":"2022-11-09T00:53:09","slug":"utrzymywanie-statusu-posta-podczas-aktualizacji-posta-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/utrzymywanie-statusu-posta-podczas-aktualizacji-posta-wordpress\/","title":{"rendered":"Utrzymywanie statusu posta podczas aktualizacji posta WordPress"},"content":{"rendered":"\n<p>W\u0142a\u015bnie sko\u0144czy\u0142em funkcj\u0119 dla projektu, kt\u00f3ra u\u017cywa kombinacji niestandardowych typ\u00f3w post\u00f3w, importu danych i aktualizacji istniej\u0105cych post\u00f3w podczas usuwania u\u017cytkownika (lub zestawu u\u017cytkownik\u00f3w).<\/p>\n<p>Jest jednak jeden problem:<\/p>\n<p>Powiedzmy, \u017ce masz post, kt\u00f3ry jest aktualnie opublikowany (to znaczy, \u017ce \u201epost_status&quot; jest ustawiony na \u201epublish&#8221;), ale kiedy aktualizujesz post przez wp_update_post, jego atrybut post_status jest ustawiony na \u201eprzysz\u0142o\u015b\u0107&#8221;.<\/p>\n<p>W s\u0142owach porz\u0105dkowych, za ka\u017cdym razem, gdy programowo aktualizujesz wpis, stan wpisu jest ustawiany na \u201eZaplanowany&#8221; (zgodnie z interfejsem u\u017cytkownika) i \u201eprzysz\u0142y&#8221; (zgodnie z kolumn\u0105 bazy danych).<\/p>\n<p>Wi\u0119c co daje?<\/p>\n<h2>Status postu podczas aktualizacji<\/h2>\n<p>Og\u00f3lnie rzecz bior\u0105c, nie jestem fanem tego, aby co\u015b dzia\u0142a\u0142o, dowiadywania si\u0119, \u017ce to dzia\u0142a, i przechodzenia do nast\u0119pnego zadania, chyba \u017ce rozumiem dok\u0142adnie, dlaczego to nie dzia\u0142a\u0142o [zgodnie z oczekiwaniami] w pierwszej kolejno\u015bci.<\/p>\n<p>Nie oznacza to, \u017ce nie ma sytuacji, w kt\u00f3rych ograniczenia spowodowa\u0142y to zjawisko (przynajmniej w godzinach pracy). Ale je\u015bli jest p\u00f3\u0142noc, naprawiam b\u0142\u0105d, a potem nie jestem do ko\u0144ca pewien, czy rozumiem, dlaczego najwyra\u017aniej zosta\u0142 zepsuty w pierwszej kolejno\u015bci, r\u00f3wnie dobrze mog\u0119 nie spa\u0107 i zrozumie\u0107 to dobrze?<\/p>\n<p>Przypomina to programistyczn\u0105 wersj\u0119 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Sunk_cost#Loss_aversion_and_the_sunk_cost_fallacy\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sunk cost bias<\/a>.<\/p>\n<p>W ka\u017cdym razie, jak opisano powy\u017cej, oto sedno problemu:<\/p>\n<ol>\n<li>Dany post istnieje w WordPressie.<\/li>\n<li>Po usuni\u0119ciu u\u017cytkownika system sprawdza, czy w danym po\u015bcie istnieje okre\u015blona tre\u015b\u0107, a je\u015bli tak, usuwa j\u0105.<\/li>\n<li>Post jest nast\u0119pnie aktualizowany za pomoc\u0105 funkcji API WordPress.<\/li>\n<\/ol>\n<p>Wszystko dzia\u0142a \u015bwietnie, z wyj\u0105tkiem problemu: za ka\u017cdym razem, gdy post jest programowo aktualizowany, oznacza to status posta jako \u201eprzysz\u0142y&#8221; w bazie danych, ostatecznie ustawiaj\u0105c element wiersza posta w\u00a0 widoku <strong>Wszystkie posty<\/strong> jako \u201eZaplanowany&#8221;.<\/p>\n<h3>Dwa rozwi\u0105zania<\/h3>\n<p>Istniej\u0105 dwa sposoby rozwi\u0105zania tego problemu:<\/p>\n<ol>\n<li>Uruchom szybkie zapytanie bezpo\u015brednio w bazie danych, aby rozwi\u0105za\u0107 problem.<\/li>\n<li>Zaktualizuj argumenty posta, aby u\u017cywa\u0142y w\u0142a\u015bciwego czasu w GMT (wi\u0119cej o tym za chwil\u0119).<\/li>\n<\/ol>\n<p>Je\u015bli zdecydujesz si\u0119 na pierwsze rozwi\u0105zanie, upewnij si\u0119, \u017ce korzystasz z funkcji przygotowania i wykonujesz zapytanie <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-00-direct-database-query-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">po zwr\u00f3ceniu funkcji aktualizacji<\/a>.<\/p>\n<pre><code>&lt;?php\n\n\/\/ First, update the post using the available WordPress API.\nwp_update_post( $post );\n\n\/**\n * If the post status attribute of the post that was just updated\n * maintains the 'publish' post setatus, then manually update the \n * database column.\n *\/\nif ('publish' === $post-&gt;post_status) {\n\n    global $wpdb;\n    $wpdb-&gt;query(\n        $wpdb-&gt;prepare(\n            \"\n            UPDATE $wpdb-&gt;posts\n            SET post_status = '%s'\n            WHERE ID = %d\n            \",\n            'publish',\n            $post-&gt;ID) );\n}\n<\/code><\/pre>\n<p>Je\u015bli zdecydujesz si\u0119 na drugie rozwi\u0105zanie, zaktualizuj jawnie w\u0142a\u015bciwo\u015bci obiektu post przed przekazaniem go <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-01-maintain-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">do funkcji aktualizacji<\/a>.<\/p>\n<pre><code>&lt;?php\n\n$event_post-&gt;post_date_gmt = gmdate( 'Y-m-d H:i:s', $event_post-&gt;post_date_gmt );\nwp_update_post( $event_post );\n<\/code><\/pre>\n<p>Nie m\u00f3wi\u0119, \u017ce podczas pracy nad projektem nie ma miejsca na \u017cadne z tych rozwi\u0105za\u0144, ale pozostaje pytanie:<\/p>\n<p>Dlaczego WordPress zaznacza post zaplanowany na przysz\u0142o\u015b\u0107, gdy post, przed przej\u015bciem przez procedur\u0119 aktualizacji, mia\u0142 zosta\u0107 opublikowany?<\/p>\n<p>A je\u015bli nie znasz pozosta\u0142ych argument\u00f3w, kt\u00f3re s\u0105 przekazywane do WordPressa podczas aktualizacji posta, wy\u015bledzenie go zajmie troch\u0119 czasu.<\/p>\n<h2>Zrozumienie problemu<\/h2>\n<p>Aby unikn\u0105\u0107 pisania bezpo\u015bredniego zapytania do bazy danych, decyduj\u0119 si\u0119 na drugie rozwi\u0105zanie, poniewa\u017c jest ono czystsze (chocia\u017c nie czyni go mniej myl\u0105cym).<\/p>\n<p>Aby dowiedzie\u0107 si\u0119, dlaczego tak si\u0119 dzieje, mo\u017cesz poprosi\u0107 innego programist\u0119 lub debugowa\u0107 kod. Bior\u0105c pod uwag\u0119, \u017ce pracowa\u0142em nad tym p\u00f3\u017ano w nocy, zdecydowa\u0142em si\u0119 na to drugie.<\/p>\n<p>Uruchamianie debugera i \u015bledzenie kodu przez post.php.<\/p>\n<p>Nie zamierzam omawia\u0107 wszystkich punkt\u00f3w przerwania i zegark\u00f3w, kt\u00f3re ustawi\u0142em, wi\u0119c postaram si\u0119, aby by\u0142o to jak najbardziej zwi\u0119z\u0142e.<\/p>\n<p>Po pierwsze, gdy kod zostanie uruchomiony przez funkcj\u0119 <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_update_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_update_post<\/a>, napotka <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-02-update-post-conditional-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ten blok kodu<\/a> :<\/p>\n<pre><code>&lt;?php\n\nif ('attachment' !== $post_type) {\n    if ('publish' == $post_status) {\n        $now = gmdate('Y-m-d H:i:59');\n        if (mysql2date('U', $post_date_gmt, false) &gt; mysql2date('U', $now, false)) {\n            $post_status = 'future';\n        }\n    } elseif ('future' == $post_status) {\n        $now = gmdate('Y-m-d H:i:59');\n        if (mysql2date('U', $post_date_gmt, false) &lt;= mysql2date('U', $now, false)) {\n            $post_status = 'publish';\n        }\n    }\n}\n<\/code><\/pre>\n<p>Zwr\u00f3\u0107 uwag\u0119, \u017ce w warunku nie pracujemy z za\u0142\u0105cznikiem i pracujemy ze statusem posta \u201eopublikuj&#8221;. Wi\u0119c uderzymy w pierwszy warunek w ramach zewn\u0119trznego warunku (troch\u0119 myl\u0105ce, prawda?).<\/p>\n<p>Teraz istnieje zmienna $post_status, kt\u00f3ra utrzymuje warto\u015b\u0107 publikowania, ale nie jest przypisana do \u017cadnej konkretnej w\u0142a\u015bciwo\u015bci bie\u017c\u0105cego posta. Je\u015bli b\u0119dziesz kontynuowa\u0107 \u015bledzenie kodu, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-03-apply-filters-post-status-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">natkniesz si\u0119 na nast\u0119pny wiersz<\/a> :<\/p>\n<pre><code>&lt;?php\n\n$post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr) ), $postarr );\n<\/code><\/pre>\n<p>Tutaj zobaczysz, \u017ce pracuje on z zestawem kluczy tablicowych zawartych w zmiennej $postarr. Ta zmienna jest u\u017cywana wcze\u015bniej w kodzie (zobacz j\u0105 <a href=\"https:\/\/core.trac.wordpress.org\/browser\/tags\/4.7\/src\/wp-includes\/post.php#L3137\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">tutaj<\/a> na Tracu). A je\u015bli przyjrzysz si\u0119 uwa\u017cnie, zobaczysz, \u017ce najpierw sprawdza, czy w\u0142a\u015bciwo\u015b\u0107 post_date_gmt jest pusta lub czy jest wyzerowana.<\/p>\n<p>A poniewa\u017c tak nie jest, u\u017cyje warto\u015bci okre\u015blonej we w\u0142a\u015bciwo\u015bci <a href=\"https:\/\/gist.github.com\/tommcfarlin\/3de0a26bbddc867f88a82def270a483b#file-04-post-date-gmt-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">, gdy pocz\u0105tkowo wywo\u0142ali\u015bmy funkcj\u0119<\/a> :<\/p>\n<pre><code>&lt;?php\n\nif (empty( $postarr['post_date_gmt']) || '0000-00-00 00:00:00' == $postarr['post_date_gmt']) {\n        if (! in_array( $post_status, array( 'draft', 'pending', 'auto-draft') )) {\n            $post_date_gmt = get_gmt_from_date( $post_date );\n        } else {\n            $post_date_gmt = '0000-00-00 00:00:00';\n        }\n    } else {\n        $post_date_gmt = $postarr['post_date_gmt'];\n    }\n<\/code><\/pre>\n<p>Czeka\u0107.<\/p>\n<p>Po co wraca\u0107 do funkcji, gdy kod ju\u017c j\u0105 przekroczy\u0142? Taka jest natura debugowania. Czasami widzisz zmienne i nie my\u015blisz o nich, tylko po to, by zobaczy\u0107, \u017ce s\u0105 u\u017cywane, ustawiane, manipulowane, \u0142\u0105czone lub cokolwiek innego w dalszej cz\u0119\u015bci kodu.<\/p>\n<p>Taka jest rzeczywisto\u015b\u0107.<\/p>\n<p>Ale tak czy inaczej, z tego powodu w\u0142a\u015bciwo\u015b\u0107 zachowa warto\u015b\u0107, kt\u00f3r\u0105 podali\u015bmy przed wywo\u0142aniem funkcji aktualizacji. Zwykle b\u0119dzie to ta sama warto\u015b\u0107, co przy uruchomieniu funkcji, ale mog\u0105 si\u0119 zdarzy\u0107 sytuacje, w kt\u00f3rych chcesz, powiedzmy, skasowa\u0107 post.<\/p>\n<p>I to jest podstawa do u\u017cywania <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/wp_delete_post\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_delete_post<\/a>. Ale ma te\u017c swoje zastrze\u017cenia, szczeg\u00f3lnie w przypadku niestandardowych typ\u00f3w post\u00f3w.<\/p>\n<p>To jednak trafia do innego postu.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Utrzymanie statusu posta podczas aktualizacji posta WordPress mo\u017ce mie\u0107 nieoczekiwane rezultaty. Dlatego i jak w\u0142a\u015bciwie nim zarz\u0105dza\u0107.<\/p>\n","protected":false},"author":1,"featured_media":223663,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,897,805,845,866],"tags":[1169],"class_list":["post-228695","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-kod","category-php-7","category-samouczki","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/228695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=228695"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/228695\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/223663"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=228695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=228695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=228695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}