25#include "movabletype_p.h"
28#include <kxmlrpcclient/client.h>
32#include <KLocalizedString>
35#include <QtCore/QStringList>
40 :
MetaWeblog( server, *new MovableTypePrivate, parent )
59 return QLatin1String(
"Movable Type" );
66 QList<QVariant> args( d->defaultArgs(
blogId() ) );
67 args << QVariant( number );
68 d->mXmlRpcClient->call(
69 QLatin1String(
"metaWeblog.getRecentPosts"), args,
70 this, SLOT(slotListRecentPosts(QList<QVariant>,QVariant)),
71 this, SLOT(slotError(
int,QString,QVariant)),
80 args << QVariant( post->
postId() );
81 unsigned int i = d->mCallCounter++;
82 d->mCallMap[ i ] = post;
83 d->mXmlRpcClient->call(
84 QLatin1String(
"mt.getTrackbackPings"), args,
85 this, SLOT(slotListTrackbackPings(QList<QVariant>,QVariant)),
86 this, SLOT(slotError(
int,QString,QVariant)),
95 if ( d->mCategoriesList.isEmpty() &&
97 d->mFetchPostCache << post;
98 if ( d->mFetchPostCache.count() ) {
105 this, SLOT(slotTriggerFetchPost()) );
122 if ( d->mCategoriesList.isEmpty() &&
124 kDebug() <<
"No categories in the cache yet. Have to fetch them first.";
125 d->mCreatePostCache << post;
127 this, SLOT(slotTriggerCreatePost()) );
135 if ( d->mSilentCreationList.contains( post ) ) {
136 kDebug() <<
"Post already in mSilentCreationList, this *should* never happen!";
138 d->mSilentCreationList << post;
158 if ( d->mCategoriesList.isEmpty() &&
160 kDebug() <<
"No categories in the cache yet. Have to fetch them first.";
161 d->mModifyPostCache << post;
163 this, SLOT(slotTriggerModifyPost()) );
171void MovableTypePrivate::slotTriggerCreatePost()
176 q->disconnect( q, SIGNAL(listedCategories(QList<QMap<QString,QString> >)),
177 q, SLOT(slotTriggerCreatePost()) );
179 QList<BlogPost*>::Iterator it = mCreatePostCache.begin();
180 QList<BlogPost*>::Iterator end = mCreatePostCache.end();
181 for ( ; it != end; it++ ) {
182 q->createPost( *it );
184 mCreatePostCache.clear();
187void MovableTypePrivate::slotTriggerModifyPost()
192 q->disconnect( q, SIGNAL(listedCategories(QList<QMap<QString,QString> >)),
193 q, SLOT(slotTriggerModifyPost()) );
195 QList<BlogPost*>::Iterator it = mModifyPostCache.begin();
196 QList<BlogPost*>::Iterator end = mModifyPostCache.end();
197 for ( ; it != end; it++ ) {
198 q->modifyPost( *it );
200 mModifyPostCache.clear();
203void MovableTypePrivate::slotTriggerFetchPost()
208 q->disconnect( q, SIGNAL(listedCategories(QList<QMap<QString,QString> >)),
209 q, SLOT(slotTriggerFetchPost()) );
210 QList<BlogPost*>::Iterator it = mFetchPostCache.begin();
211 QList<BlogPost*>::Iterator end = mFetchPostCache.end();
212 for ( ; it != end; it++ ) {
215 mFetchPostCache.clear();
218MovableTypePrivate::MovableTypePrivate()
223MovableTypePrivate::~MovableTypePrivate()
228void MovableTypePrivate::slotCreatePost(
const QList<QVariant> &result,
const QVariant &
id )
234 mCallMap.remove(
id.toInt() );
239 kDebug () <<
"TOP:" << result[0].typeName();
240 if ( result[0].type() != QVariant::String &&
241 result[0].type() != QVariant::Int ) {
242 kError() <<
"Could not read the postId, not a string or an integer.";
244 i18n(
"Could not read the postId, not a string or an integer." ),
249 if ( result[0].type() == QVariant::String ) {
250 serverID = result[0].toString();
252 if ( result[0].type() == QVariant::Int ) {
253 serverID = QString::fromLatin1(
"%1" ).arg( result[0].toInt() );
256 if ( mSilentCreationList.contains( post ) )
259 setPostCategories( post, !post->
isPrivate() );
261 kDebug() <<
"emitting createdPost()"
262 <<
"for title: \"" << post->
title()
263 <<
"\" server id: " << serverID;
265 emit q->createdPost( post );
269void MovableTypePrivate::slotFetchPost(
const QList<QVariant> &result,
const QVariant &
id )
275 mCallMap.remove(
id.toInt() );
279 kDebug () <<
"TOP:" << result[0].typeName();
280 if ( result[0].type() == QVariant::Map &&
281 readPostFromMap( post, result[0].toMap() ) ) {
283 kError() <<
"Could not fetch post out of the result from the server.";
284 post->
setError( i18n(
"Could not fetch post out of the result from the server." ) );
287 i18n(
"Could not fetch post out of the result from the server." ), post );
290 QList<QVariant> args( defaultArgs( post->
postId() ) );
291 unsigned int i= mCallCounter++;
292 mCallMap[ i ] = post;
294 QLatin1String(
"mt.getPostCategories"), args,
295 q, SLOT(slotGetPostCategories(QList<QVariant>,QVariant)),
296 q, SLOT(slotError(
int,QString,QVariant)),
299 kDebug() <<
"Emitting fetchedPost()";
301 emit q->fetchedPost( post );
305void MovableTypePrivate::slotModifyPost(
const QList<QVariant> &result,
const QVariant &
id )
311 mCallMap.remove(
id.toInt() );
315 kDebug() <<
"TOP:" << result[0].typeName();
316 if ( result[0].type() != QVariant::Bool &&
317 result[0].type() != QVariant::Int ) {
318 kError() <<
"Could not read the result, not a boolean.";
320 i18n(
"Could not read the result, not a boolean." ),
324 if ( mSilentCreationList.contains( post ) ) {
326 mSilentCreationList.removeOne( post );
327 emit q->createdPost( post );
330 setPostCategories( post,
false );
335void MovableTypePrivate::setPostCategories(
BlogPost *post,
bool publishAfterCategories )
340 unsigned int i = mCallCounter++;
341 mCallMap[ i ] = post;
342 mPublishAfterCategories[ i ] = publishAfterCategories;
343 QList<QVariant> catList;
344 QList<QVariant> args( defaultArgs( post->
postId() ) );
348 for (
int j = 0; j < categories.count(); j++ ) {
349 for (
int k = 0; k < mCategoriesList.count(); k++ ) {
350 if ( mCategoriesList[k][QLatin1String(
"name")] == categories[j] ) {
351 kDebug() <<
"Matched category with name: " << categories[ j ] <<
" and id: " << mCategoriesList[ k ][ QLatin1String(
"categoryId") ];
352 QMap<QString,QVariant> category;
355 category[QLatin1String(
"categoryId")] = mCategoriesList[k][QLatin1String(
"categoryId")].toInt();
356 catList << QVariant( category );
359 if ( k == mCategoriesList.count() ) {
360 kDebug() <<
"Couldn't find categoryId for: " << categories[j];
364 args << QVariant( catList );
367 QLatin1String(
"mt.setPostCategories"), args,
368 q, SLOT(slotSetPostCategories(QList<QVariant>,QVariant)),
369 q, SLOT(slotError(
int,QString,QVariant)),
373void MovableTypePrivate::slotGetPostCategories(
const QList<QVariant>& result,
const QVariant&
id)
380 mCallMap.remove( i );
382 if ( result[ 0 ].type() != QVariant::List ) {
383 kError() <<
"Could not read the result, not a list. Category fetching failed! We will still emit fetched post now.";
385 i18n(
"Could not read the result - is not a list. Category fetching failed." ), post );
388 emit q->fetchedPost( post );
390 QList<QVariant> categoryList = result[ 0 ].toList();
391 QList<QString> newCatList;
392 QList<QVariant>::ConstIterator it = categoryList.constBegin();
393 QList<QVariant>::ConstIterator end = categoryList.constEnd();
394 for ( ; it != end; it++ ) {
395 newCatList << ( *it ).toMap()[ QLatin1String(
"categoryName") ].toString();
397 kDebug() <<
"categories list: " << newCatList;
400 emit q->fetchedPost( post );
404void MovableTypePrivate::slotSetPostCategories(
const QList<QVariant>& result,
const QVariant&
id)
411 bool publish = mPublishAfterCategories[ i ];
412 mCallMap.remove( i );
413 mPublishAfterCategories.remove( i );
415 if ( result[0].type() != QVariant::Bool ) {
416 kError() <<
"Could not read the result, not a boolean. Category setting failed! We will still publish if now if necessary. ";
418 i18n(
"Could not read the result - is not a boolean value. Category setting failed. Will still publish now if necessary." ),
425 q->modifyPost( post );
430 if ( mSilentCreationList.contains( post ) ) {
431 kDebug() <<
"emitting createdPost() for title: \""
432 << post->
title() <<
"\"";
434 mSilentCreationList.removeOne( post );
435 emit q->createdPost( post );
437 kDebug() <<
"emitting modifiedPost() for title: \""
438 << post->
title() <<
"\"";
440 emit q->modifiedPost( post );
445QList<QVariant> MovableTypePrivate::defaultArgs(
const QString &
id )
448 QList<QVariant> args;
449 if ( !
id.isEmpty() ) {
450 args << QVariant(
id );
452 args << QVariant( q->username() )
453 << QVariant( q->password() );
457bool MovableTypePrivate::readPostFromMap(
BlogPost *post,
const QMap<QString, QVariant> &postInfo )
461 kDebug() <<
"readPostFromMap()";
465 QStringList mapkeys = postInfo.keys();
466 kDebug() << endl <<
"Keys:" << mapkeys.join( QLatin1String(
", ") );
470 KDateTime( postInfo[QLatin1String(
"dateCreated")].toDateTime(), KDateTime::UTC );
471 if ( dt.isValid() && !dt.isNull() ) {
476 KDateTime( postInfo[QLatin1String(
"lastModified")].toDateTime(), KDateTime::UTC );
477 if ( dt.isValid() && !dt.isNull() ) {
481 post->
setPostId( postInfo[QLatin1String(
"postid")].toString().isEmpty() ? postInfo[QLatin1String(
"postId")].toString() :
482 postInfo[QLatin1String(
"postid")].toString() );
484 QString title( postInfo[QLatin1String(
"title")].toString() );
485 QString description( postInfo[QLatin1String(
"description")].toString() );
486 QStringList categoryIdList = postInfo[QLatin1String(
"categories")].toStringList();
487 QStringList categories;
490 for (
int i = 0; i < categoryIdList.count(); i++ ) {
491 for (
int k = 0; k < mCategoriesList.count(); k++ ) {
492 if ( mCategoriesList[ k ][ QLatin1String(
"name") ] == categoryIdList[ i ] ) {
493 categories << mCategoriesList[ k ][ QLatin1String(
"name") ];
494 }
else if ( mCategoriesList[ k ][ QLatin1String(
"categoryId") ] == categoryIdList[ i ]) {
495 categories << mCategoriesList[ k ][ QLatin1String(
"name") ];
502 post->
setSlug( postInfo[QLatin1String(
"wp_slug")].toString() );
506 post->
setCommentAllowed( (
bool)postInfo[QLatin1String(
"mt_allow_comments")].toInt() );
508 post->
setSummary( postInfo[QLatin1String(
"mt_excerpt")].toString() );
509 post->
setTags( postInfo[QLatin1String(
"mt_keywords")].toStringList() );
510 post->
setLink( postInfo[QLatin1String(
"link")].toString() );
511 post->
setPermaLink( postInfo[QLatin1String(
"permaLink")].toString() );
512 QString postStatus = postInfo[QLatin1String(
"post_status")].toString();
513 if ( postStatus != QLatin1String(
"publish") &&
514 !postStatus.isEmpty() ) {
522 if ( !categories.isEmpty() ) {
523 kDebug() <<
"Categories:" << categories;
529void MovableTypePrivate::slotListTrackBackPings(
530 const QList<QVariant> &result,
const QVariant &
id )
533 kDebug() <<
"slotTrackbackPings()";
534 BlogPost *post = mCallMap[
id.toInt() ];
535 mCallMap.remove(
id.toInt() );
536 QList<QMap<QString,QString> > trackBackList;
537 if ( result[0].type() != QVariant::List ) {
538 kError() <<
"Could not fetch list of trackback pings out of the"
539 <<
"result from the server.";
541 i18n(
"Could not fetch list of trackback pings out of the "
542 "result from the server." ) );
545 const QList<QVariant> trackBackReceived = result[0].toList();
546 QList<QVariant>::ConstIterator it = trackBackReceived.begin();
547 QList<QVariant>::ConstIterator end = trackBackReceived.end();
548 for ( ; it != end; ++it ) {
549 QMap<QString,QString> tping;
550 kDebug() <<
"MIDDLE:" << ( *it ).typeName();
551 const QMap<QString, QVariant> trackBackInfo = ( *it ).toMap();
552 tping[ QLatin1String(
"title") ] = trackBackInfo[ QLatin1String(
"pingTitle")].toString();
553 tping[ QLatin1String(
"url") ] = trackBackInfo[ QLatin1String(
"pingURL")].toString();
554 tping[ QLatin1String(
"ip") ] = trackBackInfo[ QLatin1String(
"pingIP")].toString();
555 trackBackList << tping;
557 kDebug() <<
"Emitting listedTrackBackPings()";
558 emit q->listedTrackBackPings( post, trackBackList );
561bool MovableTypePrivate::readArgsFromPost( QList<QVariant> *args,
const BlogPost &post )
569 QMap<QString, QVariant> map;
570 map[QLatin1String(
"categories")] = post.
categories();
571 map[QLatin1String(
"description")] = post.
content();
575 map[QLatin1String(
"title")] = post.
title();
576 map[QLatin1String(
"dateCreated")] = post.
creationDateTime().dateTime().toUTC();
579 map[QLatin1String(
"mt_excerpt")] = post.
summary();
580 map[QLatin1String(
"mt_keywords")] = post.
tags().join( QLatin1String(
",") );
587#include "moc_movabletype.cpp"
A class that represents a blog post on the server.
void setSlug(const QString &slug)
Sets the Wordpress slug property! (will use to set post's permalink) Currently just wordpress support...
KDateTime creationDateTime() const
Returns the creation date time.
QString summary() const
Returns the summary.
bool isPrivate() const
Returns if the post is published or not.
void setPostId(const QString &postId)
Sets the post id value.
void setCategories(const QStringList &categories)
Sets the categories.
void setPermaLink(const KUrl &permalink) const
Set the perma link path.
void setTrackBackAllowed(bool allowTrackBacks)
Set whether track back should be allowed.
void setStatus(Status status)
Sets the status.
void setCreationDateTime(const KDateTime &datetime)
Sets the creation time.
void setContent(const QString &content)
Sets the content.
bool isCommentAllowed() const
Returns whether comments should be allowed.
QString content() const
Returns the content.
void setSummary(const QString &summary)
Set the summary.
void setLink(const KUrl &link) const
Set the link path.
QStringList tags() const
Returns the tags list as a QStringList.
QString title() const
Returns the title.
void setError(const QString &error)
Sets the error.
QStringList categories() const
Returns the categories.
void setCommentAllowed(bool commentAllowed)
Set whether comments should be allowed.
void setTags(const QStringList &tags)
Set the tags list.
QString additionalContent() const
Returns the additional content, (mt_text_more of MovableType API)
QString postId() const
Returns the postId.
void setAdditionalContent(const QString &additionalContent)
Sets the additional content, (mt_text_more of MovableType API)
@ Created
Status of a successfully created post.
@ Fetched
Status of a successfully fetched post.
@ Error
Status when an error on the server side occurred.
@ Modified
Status of a successfully modified post.
bool isTrackBackAllowed() const
Returns whether track back should be allowed.
void setTitle(const QString &title)
Sets the title.
void setPrivate(bool privatePost)
Sets the post to private viewings only.
void setModificationDateTime(const KDateTime &datetime)
Sets the modification time.
@ ParsingError
A parsing error.
virtual void modifyPost(KBlog::BlogPost *post)=0
Modify an existing blog post on the server.
virtual void fetchPost(KBlog::BlogPost *post)=0
Fetch a blog post from the server with a specific ID.
QString blogId() const
Returns the unique ID for the specific blog on the server.
virtual void createPost(KBlog::BlogPost *post)=0
Create a new blog post on the server.
A class that can be used for access to MetaWeblog blogs.
virtual void listCategories()
List the categories of the blog.
void listedCategories(const QList< QMap< QString, QString > > &categories)
This signal is emitted when the last category of the listCategories() job has been fetched.
A class that can be used for access to Movable Type blogs.
virtual void listTrackBackPings(KBlog::BlogPost *post)
Get the list of trackback pings from the server.
MovableType(const KUrl &server, QObject *parent=0)
Create an object for Movable Type.
QString interfaceName() const
Returns the of the inherited object.
void modifyPost(KBlog::BlogPost *post)
Modify a post on server.
void listRecentPosts(int number)
List recent posts on the server.
virtual ~MovableType()
Destroy the object.
void fetchPost(KBlog::BlogPost *post)
Fetch a post from the server.
void createPost(KBlog::BlogPost *post)
Create a new post on server.
This file is part of the for accessing Blog Servers and defines the MovableType class.
Namespace for blog related classes.