{"id":204,"date":"2009-06-05T14:10:27","date_gmt":"2009-06-05T13:10:27","guid":{"rendered":"http:\/\/eriz.pcinside.pl\/weblog\/zdalne-publikowanie-notek-w-wordpressie-xml-rpc-w-php-204.html"},"modified":"2009-06-05T14:10:27","modified_gmt":"2009-06-05T13:10:27","slug":"zdalne-publikowanie-notek-w-wordpressie-xml-rpc-w-php","status":"publish","type":"post","link":"https:\/\/eriz.pcinside.pl\/weblog\/zdalne-publikowanie-notek-w-wordpressie-xml-rpc-w-php-204.html","title":{"rendered":"Zdalne publikowanie notek w WordPressie &#8211; XML-RPC w PHP"},"content":{"rendered":"<p>Jak wygl\u0105da \u017cycie zwyk\u0142ego u\u017cytkownika WordPressa&#8230;? Otwarcie przegl\u0105darki, logowanie, napisanie notki, publikacja. Zaraz, a gdyby np. skorzysta\u0107 w tym celu z jakiej\u015b zewn\u0119trznej aplikacji? Owszem, jest tego w p\u0119czki, nie ma sensu wynajdywanie ko\u0142a na nowo. Jednak protok\u00f3\u0142, z kt\u00f3rego korzystaj\u0105 zewn\u0119trzne aplikacje, mo\u017ce by\u0107 wykorzystany tak\u017ce w naszych bibliotekach oraz z poziomu samego PHP.<\/p>\n<p>Pomys\u0142 na dzisiejszy wpis podsun\u0105\u0142 mi <a href=\"http:\/\/lukjarz.blip.pl\">^lukjarz<\/a>. ;]<\/p>\n<p><!--more--><\/p>\n<h3>zdalne publikowanie?<\/h3>\n<p>Ju\u017c od bardzo dawna w WordPressie zosta\u0142a wprowadzona opcja publikowana przez specjalnie za\u0142o\u017con\u0105 skrzynk\u0119 mailow\u0105. Przyznam szczerze, \u017ce nie przygl\u0105da\u0142em si\u0119 jej szczeg\u00f3\u0142owo, ale g\u0142\u00f3wna idea polega na publikowaniu tre\u015bci ka\u017cdego listu, kt\u00f3ry na ni\u0105 dotrze. Je\u015bliby chcie\u0107 regularnie publikowa\u0107 z poziomu jakiego\u015b wi\u0119kszego skryptu, to jest to jednak rozwi\u0105zanie okr\u0119\u017cne, kt\u00f3re &#8211; w dodatku &#8211; wymaga skorzystania z dodatkowego po\u015brednika. Je\u015bli padnie poczta, to klops -nie da si\u0119 publikowa\u0107 wpis\u00f3w.<\/p>\n<p>Niekt\u00f3rzy szukaj\u0105 jakich\u015b materia\u0142\u00f3w po prostu po terminie <em>API<\/em>. Niestety, w wi\u0119kszo\u015bci wynik\u00f3w s\u0105 opisane funkcje WordPressa dla wtyczek. Owszem, na upartego mo\u017cna by tak\u0105 napisa\u0107 i np. pobiera\u0107 tre\u015b\u0107 z jakiego\u015b pliku co jaki\u015b czas. Tylko po co tak kombinowa\u0107&#8230;? Poza tym &#8211; rozwi\u0105zanie jest bardziej obej\u015bciem, poniewa\u017c mo\u017cna bezpo\u015brednio &#8222;nakaza\u0107&#8221; silnikowi blogowemu publikacj\u0119 notki.<\/p>\n<h3>XML-RPC<\/h3>\n<p>W\u0142a\u015bciwie, to od samego (dobrze pami\u0119tam?) pocz\u0105tku istnienia WordPress zawiera\u0142 odpowiedni modu\u0142 do obs\u0142ugi zapyta\u0144 XML-RPC. Pewnie wielu z Was si\u0119 zastanawia\u0142o, co to za tajemniczy plik <em>xmlrpc.php<\/em> odbiegaj\u0105cy od typowej konwencji nazw <em>wp-co\u015btam<\/em>. Co to jest XML-RPC? Jest to pseudoprotok\u00f3\u0142 dzia\u0142aj\u0105cy po HTTP, kt\u00f3rego sk\u0142adnia jest oparta na XML-u oraz nazwach funkcji obs\u0142uguj\u0105cego silnika. Skrypt korzystaj\u0105cy z odpowiedniej biblioteki jest w stanie pracowa\u0107 jako serwer oraz klient &#8211; nie ma ogranicze\u0144; to wywo\u0142anie oraz spos\u00f3b napisania danej aplikacji okre\u015bla, co i jak ma zosta\u0107 wykonane. Dialog klienta z serwerem mo\u017cna por\u00f3wna\u0107 do zdalnego wywo\u0142ania funkcji z danego j\u0119zyka programowania. Warstwa XML-RPC dba o to, aby odpowiednio zakodowa\u0107 nazw\u0119 metody oraz przesy\u0142ane informacje.<\/p>\n<p><a href=\"http:\/\/codex.wordpress.org\/XML-RPC_Support\">Na jednej ze stron<\/a> <a href=\"http:\/\/codex.wordpress.org\">Codexu<\/a> silnika jest dost\u0119pny rozdzia\u0142 opisuj\u0105cy metody, kt\u00f3re mo\u017cna wywo\u0142a\u0107 za po\u015brednictwem XML-RPC w WordPressie. Tak naprawd\u0119 tw\u00f3rcy postanowili wykorzysta\u0107 kilka popularnych &#8222;dialekt\u00f3w&#8221; w celu zwi\u0119kszenia kompatybilno\u015bci z ju\u017c istniej\u0105cymi aplikacjami\/bibliotekami s\u0142u\u017cacymi do publikacji tre\u015bci bez po\u015brednictwa przegl\u0105darki. Aby w pe\u0142ni wykorzysta\u0107 mo\u017cliwo\u015bci WP, developerzy postanowili utworzy\u0107 dodatkowe funkcje, kt\u00f3rych nie udost\u0119pniaj\u0105 inne silniki. S\u0105 to zazwyczaj funkcje dotycz\u0105ce obs\u0142ugi komentarzy, autor\u00f3w, kategorii, czy metody umo\u017cliwiaj\u0105ce przesy\u0142anie plik\u00f3w. Je\u015bli nazwy metod r\u00f3\u017cni\u0105 si\u0119 tylko nazwami API (inny prefiks), developerzy zalecaj\u0105 korzystanie z funkcji umieszczonych w przestrzeni nazw <em>wp.<\/em>.<\/p>\n<h3>komunikacja<\/h3>\n<p>Owszem, mo\u017cna by by\u0142o bezpo\u015brednio do\u0142\u0105czy\u0107 do skryptu biblioteki WP, ale czy to ma sens? Po co \u015bmieci\u0107 skrypty, niepotrzebnie z\u017cera\u0107 pami\u0119\u0107? Poza tym, nie ma mo\u017cliwo\u015bci dodania wpis\u00f3w na innym fizycznym serwerze. Wi\u0119c idealnym rozwi\u0105zaniem jest XML-RPC.<\/p>\n<p>Najwa\u017cniejszym elementem jest biblioteka, kt\u00f3ra b\u0119dzie kodowa\u0142a dane do formatu \u017c\u0105dania XML-RPC. Mo\u017cna j\u0105 napisa\u0107 samodzielnie (jest dost\u0119pna <a href=\"http:\/\/www.xmlrpc.com\/spec\">specyfikacja formatu<\/a>) albo skorzysta\u0107 z wielu gotowych. PHP posiada natywne rozszerzenie, kt\u00f3re mo\u017cna dokompilowa\u0107, ale jego u\u017cycie jest jednak nieintuicyjne. B\u0119dzie jednak szybsze (gdy\u017c jest cz\u0119\u015bci\u0105 interpretera).<\/p>\n<p>Z racji tego, i\u017c natywne rozszerzenie XML-RPC nie jest wsz\u0119dzie dost\u0119pne, mo\u017cna pos\u0142u\u017cy\u0107 si\u0119 bibliotek\u0105 <a href=\"http:\/\/phpxmlrpc.sourceforge.net\/\">XML-RPC for PHP<\/a>. Jest ona aktualizowana, co w przypadku niekt\u00f3rych jest sporym problemem. Dodatkowo, w paczce znajduje si\u0119 obszerna dokumentacja oraz przyk\u0142ady.<\/p>\n<p>Ja skorzystam z tego, co daje WordPress. W katalogu <em>wp-includes<\/em> znajduje si\u0119 plik <em>class-IXR.php<\/em>. To w\u0142a\u015bnie ona si\u0119 nam przyda. Skupi\u0119 si\u0119 na samej publikacji wpisu, o to g\u0142\u00f3wnie przecie\u017c chodzi. [;<\/p>\n<p>Pierwszym krokiem jest uaktywnienie XML-RPC w WordPressie. Wystarczy otworzy\u0107 <em>opcje<\/em>, <em>publikacja<\/em> i w\u0142\u0105czy\u0107 <em>protoko\u0142y publikowania XML-RPC<\/em>. Zacznijmy od szkieletu naszego prostego skryptu. Sprawdzimy nim, czy nasz skrypt prawid\u0142owo si\u0119 komunikuje z WordPressem:<\/p>\n<p><code lang=\"php\"><?PHP\nrequire 'class-IXR.php';\n\n$q = new IXR_Client('http:\/\/example.org\/xmlrpc.php');\n\nif(!$q->query('demo.sayHello')){<br \/>\n    echo $q->getErrorCode().': '.$q->getErrorMessage();<br \/>\n}<\/p>\n<p>echo $q->getResponse();<br \/>\n?><\/code><\/p>\n<p>Powy\u017cszy kod powinien zwr\u00f3ci\u0107 <em>Hello<\/em>, co oznacza, \u017ce komunikacja z WP przebiega prawid\u0142owo. I teraz kilka s\u0142\u00f3w wyja\u015bnie\u0144, pomimo \u017ce kod do zbyt skomplikowanych nie nale\u017cy. <img src=\"https:\/\/eriz.pcinside.pl\/weblog\/wp-includes\/images\/smilies\/e_wink.png\" alt=\";)\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\" \/> W konstruktorze klasy <em>IXR_Client<\/em> wstawiamy URL do pliku <em>xmlrpc.php<\/em> naszego bloga. G\u0142\u00f3wn\u0105 funkcj\u0105, kt\u00f3ra powoduje wykonanie danego \u017c\u0105dania jest <em>query<\/em>. Jako pierwszy parametr przyjmuje ona nazw\u0119 metody udost\u0119pnianej przez serwer. Pozosta\u0142e (opcjonalne parametry), to jej argumenty. S\u0105 one opisane w dokumentacji, wystarczy je po prostu poda\u0107 po przecinku. Przy wi\u0119kszo\u015bci wywo\u0142a\u0144 funkcji WP b\u0119dziemy podawali co najmniej 4 parametry &#8211; nazw\u0119 metody, identyfikator bloga, login i has\u0142o do panelu. Je\u015bli nie mamy kilku dziennik\u00f3w skonfigurowanych dla jednego skryptu (WordPress Multi User), b\u0119dzie to po prostu dowolna warto\u015b\u0107. List\u0119 blog\u00f3w oraz ich identyfikatory uzyskamy wywo\u0142uj\u0105c <em>wp.getUsersBlogs<\/em>. W\u00f3wczas bez identyfikatora, rzecz jasna. [;<\/p>\n<p>Sprawd\u017amy autoryzacj\u0119, wy\u015bwietlmy kategorie u\u017cywane na blogu. Dane zwr\u00f3cone przez t\u0119 metod\u0119 przydadz\u0105 si\u0119 do wstawiania nowej notki.<\/p>\n<p><code lang=\"php\"><?PHP\nrequire 'class-IXR.php';\n\n$q = new IXR_Client('http:\/\/example.org\/xmlrpc.php');\n\nif(!$q->query('wp.getCategories', 1, 'admin', '*********')){<br \/>\n    echo $q->getErrorCode().': '.$q->getErrorMessage();<br \/>\n}<\/p>\n<p>var_dump($q->getResponse());<br \/>\n?><\/code><\/p>\n<p>W odpowiedzi otrzymamy np. to:<\/p>\n<p><code lang=\"text\">array<br \/>\n  0 =><br \/>\n    array<br \/>\n      'categoryId' => string '1' (length=1)<br \/>\n      'parentId' => string '0' (length=1)<br \/>\n      'description' => string 'Uncategorized' (length=13)<br \/>\n      'categoryName' => string 'Uncategorized' (length=13)<br \/>\n      'htmlUrl' => string 'http:\/\/127.0.0.2\/php\/wordpress\/?cat=1' (length=37)<br \/>\n      'rssUrl' => string 'http:\/\/127.0.0.2\/php\/wordpress?feed=rss2&amp;cat=1' (length=50)<\/code><\/p>\n<h3>prosta publikacja<\/h3>\n<p>Ok, komunikacja dzia\u0142a, nazwy te\u017c mamy, pora na w\u0142a\u015bciw\u0105 publikacj\u0119. Skorzystamy <a href=\"http:\/\/code.google.com\/intl\/pl-PL\/apis\/blogger\/docs\/2.0\/developers_guide_protocol.html\">z protoko\u0142u<\/a> opracowanego na potrzeby Blogger Google&#8217;a.<\/p>\n<p><code lang=\"php\"><?PHP\nrequire 'class-IXR.php';\n\n$q = new IXR_Client('http:\/\/127.0.0.2\/php\/wordpress\/xmlrpc.php');\n\nif(!$q->query('blogger.newPost', 'asd', 1, 'admin', '*******', 'hello World!', true)){<br \/>\n    echo $q->getErrorCode().': '.$q->getErrorMessage();<br \/>\n}<\/p>\n<p>var_dump($q->getResponse());<br \/>\n?><\/code><\/p>\n<p>Parametr przed identyfikatorem bloga, to &#8222;zg\u0142oszenie&#8221; aplikacji. Jest to wymagane tylko dla macierzystej us\u0142ugi i w naszym przypadku mo\u017ce to by\u0107 dowolny ci\u0105g znak\u00f3w. Powy\u017cszy kod dodaje notk\u0119 o tre\u015bci <em>hello World!<\/em>, bez tytu\u0142u i innych metadanych. Aby doda\u0107 tytu\u0142, kategori\u0119, czy ustawi\u0107 zajawk\u0119, skorzystamy z <a href=\"http:\/\/www.xmlrpc.com\/metaWeblogApi\">metaWeblogApi<\/a>, a dok\u0142adniej metody <em>metaWeblog.newPost<\/em>. Je\u015bli chodzi o jej parametry, to wystarcz\u0105 typowe &#8211; nazwa metody, ID bloga, login, has\u0142o, dane notki oraz status wpisu (czy publikowa\u0107, czy zapisa\u0107 jako brudnopis).<\/p>\n<p>Najwa\u017cniejsza jest w tym przypadku konstrukcja, kt\u00f3r\u0105 nazwa\u0142em danymi notki. Nie jest to nic innego, jak tablica asocjacyjna, kt\u00f3ra zawiera kilka kluczy. ;] Struktura posiada prawie identyczn\u0105 konstrukcj\u0119, co pole wpisu w <a href=\"http:\/\/www.rssboard.org\/rss-specification#hrelementsOfLtitemgt\">specyfikacji RSS 2.0<\/a> poszerzone o kilka p\u00f3l. Koniec owijania w bawe\u0142n\u0119, pora publikowa\u0107.<\/p>\n<p><code lang=\"php\"><?PHP\nrequire 'class-IXR.php';\n\n$q = new IXR_Client('http:\/\/127.0.0.2\/php\/wordpress\/xmlrpc.php');\n\n$note = array(\n    'title'             => 'Hello World!',   \/\/tytu\u0142<br \/>\n    'description'        => 'to b\u0119dzie wst\u0119p...',  \/\/zajawka<br \/>\n    'mt_text_more'      => 'tre\u015b\u0107 wpisu',    \/\/tre\u015b\u0107<br \/>\n    'categories'        => array('Uncategorized'),   \/\/nazwy kategorii jako elementy tablicy<br \/>\n    'mt_keywords'       => array('tag1', 'tag2', 'tag'), \/\/ tagi<br \/>\n    \/\/'dateCreated'       => date(DATE_RFC822, mktime(0, 0, 0, 1, 1, 2000)),   \/\/data publikacji wpisu<br \/>\n    \/\/'wp_password'     => 'hasuo',    \/\/has\u0142o wpisu<br \/>\n    \/\/'mt_allow_pings'    => true,  \/\/zezwala\u0107 na pingbacki?<br \/>\n    \/\/'mt_allow_comments' => true,  \/\/a na komentarze?<br \/>\n);<\/p>\n<p>if(!$q->query('metaWeblog.newPost', 1, 'admin', '*********', $note, true)){<br \/>\n    echo $q->getErrorCode().': '.$q->getErrorMessage();<br \/>\n}<\/p>\n<p>var_dump($q->getResponse());<br \/>\n?><\/code><\/p>\n<p>Jak zwykle, metoda <em>getResponse<\/em> po pomy\u015blnym dodaniu notki, zwr\u00f3ci ID wpisu. Wpis zosta\u0142 opublikowany. ;]<\/p>\n<p>PS: niestety, nie uda\u0142o mi si\u0119 zmusi\u0107 WordPressa do ustawienia konkretnej daty publikacji wpisu. Z komunikat\u00f3w wynika, \u017ce jest jaki\u015b b\u0142\u0105d w WordPressie.<\/p>\n<h3>po publikacji<\/h3>\n<p>Przyda\u0142oby si\u0119 jeszcze pobra\u0107 link do notki:<\/p>\n<p><code lang=\"php\"><?PHP\nrequire 'class-IXR.php';\n\n$q = new IXR_Client('http:\/\/127.0.0.2\/php\/wordpress\/xmlrpc.php');\n\nif(!$q->query('metaWeblog.getPost', 3, 'admin', '******')){<br \/>\n    echo $q->getErrorCode().': '.$q->getErrorMessage();<br \/>\n}<\/p>\n<p>var_dump($q->getResponse());<br \/>\n?><\/code><\/p>\n<p>Gdzie <em>3<\/em>, to ID notki. Warto\u015b\u0107 zwr\u00f3cona przez <em>getResponse<\/em> to tablica, kt\u00f3ra zawiera kilka ciekawych informacji. Ale jakich? To ju\u017c zadanie domowe. [;<\/p>\n<p>Podpowiem tylko, \u017ce w celu pobrania bezpo\u015bredniego linka do notki wystarczy:<\/p>\n<p><code lang=\"php\"><?PHP\n$d = $q->getResponse();<br \/>\necho $d['permaLink'];<br \/>\n?><\/code><\/p>\n<h3>epilog<\/h3>\n<p>WordPress jest ciekaw\u0105 platform\u0105 do publikacji r\u00f3\u017cnego rodzaju tre\u015bci. Tak naprawd\u0119, z silnika blogowego zrodzi\u0142 si\u0119 potw\u00f3r, kt\u00f3ry na wielu polach nie ust\u0119puje CMS-om z prawdziwego zdarzenia, takim jak np. Drupal, czy Joomla. Tylko od zestawu wtyczek i inwencji u\u017cytkownika zale\u017cy, co i jak b\u0119dzie publikowane, a WordPress zadba o reszt\u0119.<\/p>\n<p><small>PS. Wiem, \u017ce ostatnio rzadko publikuj\u0119, ale jak ju\u017c <a href=\"http:\/\/eriz.pcinside.pl\/weblog\/jak-powstaje-notka-na-erizs-weblog-197.html\">pisa\u0142em<\/a> &#8211; zmajstrowanie notki nieco czasu zabiera. Na t\u0119 po\u015bwi\u0119ci\u0142em par\u0119 godzin ze wzgl\u0119du na testy oraz w\u0142a\u015bciwie brak rzetelnej dokumentacji protoko\u0142u. Swoj\u0105 drog\u0105, przygotowuj\u0119 co\u015b specjalnego, my\u015bl\u0119 \u017ce warto poczeka\u0107. [;<\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jak wygl\u0105da \u017cycie zwyk\u0142ego u\u017cytkownika WordPressa&#8230;? Otwarcie przegl\u0105darki, logowanie, napisanie notki, publikacja. Zaraz, a gdyby np. skorzysta\u0107 w tym celu z jakiej\u015b zewn\u0119trznej aplikacji? Owszem, jest tego w p\u0119czki, nie ma sensu wynajdywanie ko\u0142a na nowo. Jednak protok\u00f3\u0142, z kt\u00f3rego korzystaj\u0105 zewn\u0119trzne aplikacje, mo\u017ce by\u0107 wykorzystany tak\u017ce w naszych bibliotekach oraz z poziomu samego PHP. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[48,30,74,66,110],"_links":{"self":[{"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/posts\/204"}],"collection":[{"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/comments?post=204"}],"version-history":[{"count":0,"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/posts\/204\/revisions"}],"wp:attachment":[{"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/media?parent=204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/categories?post=204"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eriz.pcinside.pl\/weblog\/wp-json\/wp\/v2\/tags?post=204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}