Как создать новый пост с фотографией, прикрепленной в WordPress, используя XMLRPC?
Кто-нибудь знает, как создать новый пост с фотографией, прикрепленной в WordPress, используя XMLRPC?
Я могу создать новое сообщение и загрузить новое изображение отдельно, но похоже, что нет возможности прикрепить загруженное фото к созданному сообщению?
Ниже приведены коды, которые я сейчас использую.
<?php
DEFINE('WP_XMLRPC_URL', 'http://www.blog.com/xmlrpc.php');
DEFINE('WP_USERNAME', 'username');
DEFINE('WP_PASSWORD', 'password');
require_once("./IXR_Library.php");
$rpc = new IXR_Client(WP_XMLRPC_URL);
$status = $rpc->query("system.listMethods"); // method name
if(!$status){
print "Error (".$rpc->getErrorCode().") : ";
print $rpc->getErrorMessage()."\n";
exit;
}
$content['post_type'] = 'post'; // post title
$content['title'] = 'Post Title '.date("F j, Y, g:i a"); // post title
$content['categories'] = array($response[1]['categoryName']); // psot categories
$content['description'] = '<p>Hello World!</p>'; // post body
$content['mt_keywords'] = 'tag keyword 1, tag keyword 2, tag keyword 3'; // post tags
$content['mt_allow_comments'] = 1; // allow comments
$content['mt_allow_pings'] = 1; // allow pings
$content['custom_fields'] = array(array('key'=>'Key Name', 'value'=>'Value One')); // custom fields
$publishBool = true;
if(!$rpc->query('metaWeblog.newPost', '', WP_USERNAME, WP_PASSWORD, $content, $publishBool)){
die('An error occurred - '.$rpc->getErrorCode().":".$rpc->getErrorMessage());
}
$postID = $rpc->getResponse();
echo 'POST ID: '.$postID.'<br/>';
if($postID){ // if post has successfully created
$fs = filesize(dirname(__FILE__).'/image.jpg');
$file = fopen(dirname(__FILE__).'/image.jpg', 'rb');
$filedata = fread($file, $fs);
fclose($file);
$data = array(
'name' => 'image.jpg',
'type' => 'image/jpg',
'bits' => new IXR_Base64($filedata),
false // overwrite
);
$status = $rpc->query(
'metaWeblog.newMediaObject',
$postID,
WP_USERNAME,
WP_PASSWORD,
$data
);
echo print_r($rpc->getResponse()); // Array ( [file] => image.jpg [url] => http://www.blog.com/wp-content/uploads/2011/09/image.jpg [type] => image/jpg )
}
?>
6 ответов
Я принимал участие в сайтах WordPress (мой нынешний работодатель использует 3 из них) и ежедневно публиковал материалы, и в целом я вынудил меня использовать то, что я делаю лучше всего - скрипты!
Они основаны на PHP, быстрые и простые в использовании и развертывании. А безопасность? Просто используйте.htaccess, чтобы обеспечить его.
Согласно исследованию, XMLRPC, когда дело доходит до файлов, - это одна вещь, которую WordPress действительно сосет. Загрузив файл, вы не сможете связать это вложение с конкретным сообщением! Я знаю, это раздражает.
Поэтому я решил выяснить это для себя. Мне потребовалась неделя, чтобы разобраться. Вам потребуется 100% контроль над вашим издательским клиентом, совместимым с XMLRPC, иначе это ничего не значит для вас!
Вам понадобится из вашей установки WordPress:
- class-IXR.php, расположенный в /wp-admin/ включает в себя
- class-wp-xmlrpc-server.php, расположенный в / wp-includes
class-IXR.php понадобится, если вы создадите свой собственный инструмент для публикации сообщений, как я. У них есть правильно работающий кодер base64. Не доверяйте тому, что поставляется с PHP.
Вы также должны иметь некоторый опыт программирования, чтобы иметь отношение к этому. Я постараюсь быть более ясным.
Изменить class-wp-xmlrpc-server.php
- Загрузите это на свой компьютер через ftp. Сделайте резервную копию на всякий случай.
- Откройте файл в текстовом редакторе. Если он не отформатирован, (как правило, это должны быть разрывы каретки Unix-типа, которые они используют), откройте его в другом месте или используйте что-то вроде ultraedit.
- Обратите внимание на
mw_newMediaObject
функция. Это наша цель. Небольшое примечание здесь; WordPress заимствует функциональность у блоггера и movabletype. Хотя WordPress также имеет уникальные наборы классов для xmlrpc, они предпочитают сохранять функциональность общей, чтобы они работали независимо от используемой платформы. - Ищите функцию
mw_newMediaObject($args)
, Как правило, это должно быть в строке 2948. Обратите внимание на строку состояния вашего текстового редактора, чтобы узнать, в каком номере строки вы находитесь. Если вы не можете найти его до сих пор, найдите его, используя функцию поиска / поиска вашего текстового редактора. Прокрутите немного вниз, и у вас должно получиться что-то похожее на это:
$name = sanitize_file_name( $data['name'] ); $type = $data['type']; $bits = $data['bits'];
После переменной $ name мы добавим что-нибудь. Увидеть ниже.
$name = sanitize_file_name( $data['name'] ); $post = $data['post']; //the post ID to attach to. $type = $data['type']; $bits = $data['bits'];
Обратите внимание на новую переменную $ post. Это означает, что всякий раз, когда вы будете отправлять новый запрос на загрузку файла, вам будет доступен аргумент "post".
Как найти номер вашего поста, зависит от того, как вы добавляете посты с помощью xmlrpc-совместимого клиента. Как правило, вы должны получить это в результате публикации. Это числовое значение.
После того как вы отредактировали вышесказанное, пришло время перейти к строке 3000.
// Construct the attachment array // attach to post_id 0 $post_id = 0; $attachment = array( 'post_title' => $name, 'post_content' => '', 'post_type' => 'attachment', 'post_parent' => $post_id, 'post_mime_type' => $type, 'guid' => $upload[ 'url' ] );
Так вот почему ни одно изображение не связано ни с одним сообщением! По умолчанию это всегда 0 для аргумента post_parent! Это больше не будет так.
// Construct the attachment array // attach to post_id 0 $post_id = $post; $attachment = array( 'post_title' => $name, 'post_content' => '', 'post_type' => 'attachment', 'post_parent' => $post_id, 'post_mime_type' => $type, 'guid' => $upload[ 'url' ] );
$ post_id теперь принимает значение $post, полученное из запроса xmlrpc. Как только это будет зафиксировано во вложении, оно будет связано с любым сообщением, которое вы пожелаете!
Это можно улучшить. Может быть назначено значение по умолчанию, чтобы все не нарушалось, если значение не введено. Хотя со своей стороны я установил значение по умолчанию на своем клиенте, и никто, кроме меня, не обращается к интерфейсу XMLRPC.
После внесения изменений сохраните файл и повторно загрузите его по тому же пути, по которому вы его нашли. Опять же, обязательно делайте резервные копии.
Остерегайтесь обновлений WordPress, которые влияют на этот модуль. Если это произойдет, вам нужно повторно применить это редактирование снова!
Включите class-IXR.php в ваш редактор PHP-типов. Если вы используете что-то еще, я не могу вам помочь.:(
Надеюсь, что это помогает некоторым людям.
Когда вы публикуете, WordPress будет сканировать сообщения на наличие IMG-тегов. Если WP находит изображение, оно загружается в его медиатеку. Если в теле есть изображение, оно будет автоматически прикреплено к сообщению.
В основном вы должны:
- опубликовать СМИ (изображение) в первую очередь
- Захватите его URL
- включите URL-адрес изображения с тегом IMG в текст вашего сообщения.
- затем создайте пост
Вот пример кода. Требуется обработка ошибок и дополнительная документация.
$admin ="***";
$userid ="****";
$xmlrpc = 'http://localhost/web/blog/xmlrpc.php';
include '../blog/wp-includes/class-IXR.php';
$client = new IXR_Client($xmlrpc);
$author = "test";
$title = "Test Posting";
$categories = "chess,coolbeans";
$body = "This is only a test disregard </br>";
$tempImagesfolder = "tempImages";
$img = "1338494719chessBoard.jpg";
$attachImage = uploadImage($tempImagesfolder,$img);
$body .= "<img src='$attachImage' width='256' height='256' /></a>";
createPost($title,$body,$categories,$author);
/*
*/
function createPost($title,$body,$categories,$author){
global $username, $password,$client;
$authorID = findAuthor($author); //lookup id of author
/*$categories is a list seperated by ,*/
$cats = preg_split('/,/', $categories, -1, PREG_SPLIT_NO_EMPTY);
foreach ($cats as $key => $data){
createCategory($data,"","");
}
//$time = time();
//$time += 86400;
$data = array(
'title' => $title,
'description' => $body,
'dateCreated' => (new IXR_Date(time())),
//'dateCreated' => (new IXR_Date($time)), //publish in the future
'mt_allow_comments' => 0, // 1 to allow comments
'mt_allow_pings' => 0,// 1 to allow trackbacks
'categories' => $cats,
'wp_author_id' => $authorID //id of the author if set
);
$published = 0; // 0 - draft, 1 - published
$res = $client->query('metaWeblog.newPost', '', $username, $password, $data, $published);
}
/*
*/
function uploadImage($tempImagesfolder,$img){
global $username, $password,$client;
$filename = $tempImagesfolder ."/" . $img;
$fs = filesize($filename);
$file = fopen($filename, 'rb');
$filedata = fread($file, $fs);
fclose($file);
$data = array(
'name' => $img,
'type' => 'image/jpg',
'bits' => new IXR_Base64($filedata),
false //overwrite
);
$res = $client->query('wp.uploadFile',1,$username, $password,$data);
$returnInfo = $client->getResponse();
return $returnInfo['url']; //return the url of the posted Image
}
/*
*/
function findAuthor($author){
global $username, $password,$client;
$client->query('wp.getAuthors ', 0, $username, $password);
$authors = $client->getResponse();
foreach ($authors as $key => $data){
// echo $authors[$key]['user_login'] . $authors[$key]['user_id'] ."</br>";
if($authors[$key]['user_login'] == $author){
return $authors[$key]['user_id'];
}
}
return "not found";
}
/*
*/
function createCategory($catName,$catSlug,$catDescription){
global $username, $password,$client;
$res = $client->query('wp.newCategory', '', $username, $password,
array(
'name' => $catName,
'slug' => $catSlug,
'parent_id' => 0,
'description' => $catDescription
)
);
}
Вот пример кода для вложения изображения из пути, не поддерживаемого WordPress (wp-content)
<?php
function attach_wordpress_images($productpicture,$newid)
{
include('../../../../wp-load.php');
$upload_dir = wp_upload_dir();
$dirr = $upload_dir['path'].'/';
$filename = $dirr . $productpicture;
# print "the path is : $filename \n";
# print "Filnamn: $filename \n";
$uploads = wp_upload_dir(); // Array of key => value pairs
# echo $uploads['basedir'] . '<br />';
$productpicture = str_replace('/uploads','',$productpicture);
$localfile = $uploads['basedir'] .'/' .$productpicture;
# echo "Local path = $localfile \n";
if (!file_exists($filename))
{
echo "hittade inte $filename !";
die ("no image for flaska $id $newid !");
}
if (!copy($filename, $localfile))
{
wp_delete_post($newid);
echo "Failed to copy the file $filename to $localfile ";
die("Failed to copy the file $filename to $localfile ");
}
$wp_filetype = wp_check_filetype(basename($localfile), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($localfile)),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $localfile, $newid );
// you must first include the image.php file
// for the function wp_generate_attachment_metadata() to work
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $localfile );
wp_update_attachment_metadata( $attach_id, $attach_data );
}
?>
После вызова метода metaWeblog.newMediaObject
нам нужно отредактировать запись изображения в базе данных, чтобы добавить родителя (ранее созданный пост с metaWeblog.newPost
).
Если мы попробуем с metaWeblog.editPost
выдает ошибку 401, которая указывает, что
// Use wp.editPost to edit post types other than post and page.
if ( ! in_array( $postdata[ 'post_type' ], array( 'post', 'page' ) ) )
return new IXR_Error( 401, __( 'Invalid post type' ) );
Решение состоит в том, чтобы позвонить wp.editPost
, который принимает следующие аргументы:
$blog_id = (int) $args[0];
$username = $args[1];
$password = $args[2];
$post_id = (int) $args[3];
$content_struct = $args[4];
Итак, сразу после newMediaObject
, мы делаем:
$status = $rpc->query(
'metaWeblog.newMediaObject',
$postID,
WP_USERNAME,
WP_PASSWORD,
$data
);
$response = $rpc->getResponse();
if( isset($response['id']) ) {
// ATTACH IMAGE TO POST
$image['post_parent'] = $postID;
if( !$rpc->query('wp.editPost', '1', WP_USERNAME, WP_PASSWORD, $response['id'], $image)) {
die( 'An error occurred - ' . $rpc->getErrorCode() . ":" . $rpc->getErrorMessage() );
}
echo 'image: ' . $rpc->getResponse();
// SET FEATURED IMAGE
$updatePost['custom_fields'] = array( array( 'key' => '_thumbnail_id', 'value' => $response['id'] ) );
if( !$rpc->query( 'metaWeblog.editPost', $postID, WP_USERNAME, WP_PASSWORD, $updatePost, $publishBool ) ) {
die( 'An error occurred - ' . $rpc->getErrorCode() . ":" . $rpc->getErrorMessage() );
}
echo 'update: ' . $rpc->getResponse();
}
Я использовал Incutio XML-RPC Library для PHP для тестирования, а остальная часть кода точно такая же, как в вопросе.
Начиная с Wordpress 3.5, newmediaobject теперь распознает хак практически естественным образом.
больше не нужно взламывать class-wp-xmlrpc-server.php.
Вместо этого ваш xml-rpc клиент должен отправить номер записи в переменную с именем post_id. (Раньше это была просто переменная 'post')
Надеюсь, это поможет кому-то.
Я должен был сделать это несколько месяцев назад. Это возможно, но не только потому, что это нахально и недокументировано. Мне пришлось копаться в источнике WordPress, чтобы понять это. То, что я написал тогда:
Одной вещью, которая была абсолютно недокументирована, был способ прикрепить изображение к сообщению. После некоторых копаний я обнаружил метод attach_uploads(), который wordpress вызывает каждый раз, когда сообщение создается или редактируется через xml-rpc. Он выполняет поиск по списку неприкрепленных медиа-объектов и проверяет, содержит ли новая / отредактированная запись ссылку на них. Так как я пытался прикрепить изображения, чтобы их могла использовать галерея темы, я не обязательно хотел связывать изображения с постом, а также не хотел редактировать WordPress. В итоге я включил ссылку на изображение в html-комментарий. - danieru.com
Как я и сказал, грязный, но я искал все выше и ниже лучшего метода, и я уверен, что ничего не существует.