1package WordPress::XMLRPC;
2use warnings;
3use strict;
4use Carp;
5use Data::Dumper;
6use Scalar::Util qw(looks_like_number);
7use vars qw($VERSION $DEBUG);
8$VERSION = sprintf "%d.%02d", q$Revision: 2.12 $ =~ /(\d+)/g;
9
10# WP XML-RPC API METHOD LIST
11# All the following methods are in the standard API https://codex.wordpress.org/XML-RPC_WordPress_API
12#
13# WP API METHOD			MODULE METHOD		RELEVANT OBSELETE METHOD	SINCE
14# wp.getPost 			getPost			getPage 				3.4
15# wp.getPosts			-			getRecentPosts,getPages,getPageList	3.4
16# wp.newPost			newPost			newPage					3.4
17# wp.editPost			editPost		editPage				3.4
18# wp.deletePost			deletePost							3.4
19# wp.getPostType		-								3.4
20# wp.getPostTypes		-								3.4
21# wp.getPostFormats		-								3.4
22# wp.getPostStatusList		getPostStatusList	getPageStatusList 			3.4
23# wp.getTaxonomy		-			getCategories,getTags			3.4
24# wp.getTaxonomies		-								3.4
25# wp.getTerm			-								3.4
26# wp.getTerms			-								3.4
27# wp.newTerm			-			newCategory				3.4
28# wp.editTerm			-								3.4
29# wp.deleteTerm			-			deleteCategory				3.4
30# wp.getMediaItem		-								3.1
31# wp.getMediaLibrary		-								3.1
32# wp.uploadFile			uploadFile							3.1
33# wp.getCommentCount		getCommentCount							2.7
34# wp.getComment			getComment							2.7
35# wp.getComments		getComments							2.7
36# wp.newComment			newComment							2.7
37# wp.editComment		editComment							2.7
38# wp.deleteComment		deleteComment							2.7
39# wp.getCommentStatusList	getCommentStatusList						2.7
40# wp.getOptions			getOptions 							2.6
41# wp.setOptions			setOptions 							2.6
42# wp.getUsersBlogs		getUsersBlogs 							2.something
43# wp.getUser			getUser								3.5
44# wp.getUsers			getUsers							3.5
45# wp.getProfile			-								3.5
46# wp.editProfile		-								3.5
47# wp.getAuthors			getAuthors							2.something
48#
49# WP ADDITIONAL METHOD LIST
50# These methods are in the internal WP API that is not normally available over XML-RPC. They can be
51# individually enabled using the plug-in at https://github.com/realflash/extended-xmlrpc-api
52# wp_insert_user		createUser
53# add_user_meta			addUserMeta
54# get_user_meta			getUserMeta
55
56sub new {
57   my ($class,$self) = @_;
58   $self||={};
59   bless $self, $class;
60   return $self;
61}
62
63sub proxy {
64   my $self = shift;
65   my $val = shift;
66   if( defined $val ){
67      $self->{proxy} = $val;
68   }
69	defined $self->{proxy} or carp("missing 'proxy'".  (caller(1))[3]);
70
71   return $self->{proxy};
72}
73
74sub username {
75   my $self = shift;
76   my $val = shift;
77   if( defined $val ){
78      $self->{username} = $val;
79   }
80	defined $self->{username} or carp("missing 'username'".  (caller(1))[3]);
81
82   return $self->{username};
83}
84
85sub password {
86   my $self = shift;
87   my $val = shift;
88   if( defined $val ){
89      $self->{password} = $val;
90   }
91	defined $self->{password} or carp("missing 'username'". (caller(1))[3]);
92
93   return $self->{password};
94}
95
96sub blog_id {
97   my $self = shift;
98   my $val = shift;
99   if( defined $val ){
100      $val=~/^\d+$/ or croak('argument must be digits');
101      $self->{blog_id} = $val;
102   }
103   $self->{blog_id} ||= 1;
104   return $self->{blog_id};
105}
106
107# post and page use 'publish' variable
108sub publish {
109   my ($self,$val) = @_;
110   $self->{publish} = $val if defined $val;
111   defined $self->{publish} or $self->{publish} = 1;
112   return $self->{publish};
113}
114
115sub server {
116   my $self = shift;
117   unless( $self->{server} ){
118      $self->proxy or confess('missing proxy');
119      require XMLRPC::Lite;
120
121      $self->{server} ||= XMLRPC::Lite->proxy( $self->proxy );
122   }
123   return $self->{server};
124}
125
126sub _call_has_fault {
127   my $self = shift;
128   my $call = shift;
129   defined $call or confess('no call passed');
130   my $err = $call->fault or return 0;
131
132   #my $from = caller();
133   #my($package, $filename, $line, $subroutine, $hasargs,
134   #   $wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(1);
135
136   my $_err;
137   for my $k( keys %$err ){
138
139      $_err.= sprintf "# %s() - ERROR %s, %s\n",
140         (caller(1))[3], # sub name
141         $k, # error label, from XMLRPC::Simple call
142         $err->{$k}, # error text
143         ;
144   }
145   $self->errstr($_err);
146
147   return $self->errstr;
148}
149
150sub errstr {
151   my ($self,$val) = @_;
152   $self->{errstr} = $val if defined $val;
153   ($self->{errstr} and $DEBUG) and Carp::cluck($self->{errstr});
154   return $self->{errstr};
155}
156
157sub _process_response
158{
159	my $self = shift;
160	my $response = shift;
161
162	my $err = $self->_call_has_fault($response);
163	if ($err)
164	{
165		return { error => $err, result => undef };
166	}
167	my $result = $response->result;
168	defined $result	or die('no result');
169
170	return { error => undef, result => $response->result };
171}
172
173sub _is_number { $_[0]=~/^\d+$/ ? $_[0] : confess("Argument '$_[0] ' is not number") }
174sub _is_href { ($_[0] and (ref $_[0]) and (ref $_[0] eq 'HASH')) ? $_[0] : confess("Expected argument to be hashref/struct") }
175
176# helper for uploading media..
177
178sub abs_path_to_media_object_data {
179   my $abs_path = shift;
180
181   -f $abs_path or Carp::cluck("not on disk: $abs_path") and return;
182
183   my $data;
184
185   $data->{name} = get_file_name($abs_path) or die('cant get filename');
186   $data->{type} = get_mime_type($abs_path) or die("cant get mime type");
187   $data->{bits} = get_file_bits($abs_path) or die('cant get file bits');
188
189   return $data;
190
191   # optionally we can request other files to get mime on
192   sub get_mime_type {
193      my $abs = shift;
194      $abs or confess('missing arg');
195      require File::Type;
196      my $ft = new File::Type;
197      my $type = $ft->mime_type($abs) or die('missing mime');
198      return $type;
199   }
200
201   sub get_file_bits {
202      my $abs_path = shift;
203      $abs_path or die;
204      # from http://search.cpan.org/~gaas/MIME-Base64-3.07/Base64.pm
205      require MIME::Base64;
206
207      open(FILE, $abs_path) or die($!);
208      my $bits;
209      my $buffer;
210      while( read(FILE, $buffer, (60*57)) ) {
211         $bits.= $buffer;
212      }
213
214      return $bits;
215   }
216
217   sub get_file_name {
218      my $string = shift;
219      $string or croak('missing path');
220
221      $string=~s/^.+\/+|\/+$//g;
222      return $string;
223   }
224
225}
226
227# XML RPC METHODS
228
229# OBSELETE
230# xmlrpc.php: function wp_getPage
231# sub getPage {
232	# my $self = shift;
233	# my $blog_id = $self->blog_id;
234	# my $page_id = shift;
235	# my $username = $self->username;
236	# my $password = $self->password;
237
238	# $page_id or confess('missing page id');
239
240	# my $call = $self->server->call(
241		# 'wp.getPage',
242		# $blog_id,
243		# $page_id,
244		# $username,
245		# $password,
246	# );
247
248	# if ( $self->_call_has_fault($call)){
249		# return;
250	# }
251
252	# my $result = $call->result;
253	# defined $result
254		# or die('no result');
255
256	# return $result;
257# }
258
259# OBSELETE
260# # xmlrpc.php: function wp_getPages
261# sub getPages {
262	# my $self = shift;
263	# my $blog_id = $self->blog_id;
264	# my $username = $self->username;
265	# my $password = $self->password;
266
267
268	# my $call = $self->server->call(
269		# 'wp.getPages',
270		# $blog_id,
271		# $username,
272		# $password,
273	# );
274
275	# if ( $self->_call_has_fault($call)){
276		# return;
277	# }
278
279	# my $result = $call->result;
280	# defined $result
281		# or die('no result');
282
283	# return $result;
284# }
285
286# OBSELETE
287# # xmlrpc.php: function wp_newPage
288# sub newPage {
289	# my $self = shift;
290   # my $blog_id = $self->blog_id;
291   # my $username = $self->username;
292   # my $password = $self->password;
293	# my $page = shift;
294
295	# defined $page or confess('missing page arg');
296   # ref $page eq 'HASH' or croak('arg is not hash ref');
297
298	# my $publish = shift;
299	# unless (defined $publish) {
300		# $publish = $self->publish;
301	# }
302
303
304
305	# my $call = $self->server->call(
306		# 'wp.newPage',
307      # $blog_id, # ignored
308      # $username, # i had missed these!!!
309      # $password,
310		# $page,
311		# $publish,
312	# );
313
314	# if ( $self->_call_has_fault($call)){
315		# return;
316	# }
317
318	# my $result = $call->result;
319	# defined $result
320		# or die('no result');
321
322	# return $result;
323# }
324
325
326# OBSELETE
327# # xmlrpc.php: function wp_deletePage
328# sub deletePage {
329	# my $self       = shift;
330	# my $blog_id    = $self->blog_id;
331	# my $username   = $self->username;
332	# my $password   = $self->password;
333	# my $page_id    = shift;
334
335	# defined $page_id or confess('missing page id arg');
336
337
338	# my $call = $self->server->call(
339		# 'wp.deletePage',
340		# $blog_id,
341		# $username,
342		# $password,
343		# $page_id,
344	# );
345
346	# if ( $self->_call_has_fault($call)){
347		# return;
348	# }
349
350	# my $result = $call->result;
351	# defined $result
352		# or die('no result');
353
354	# return $result;
355# }
356
357
358# OBSELETE
359# # xmlrpc.php: function wp_editPage
360# sub editPage {
361	# my $self    = shift;
362   # my($blog_id, $page_id, $content, $publish);
363	# $blog_id    = $self->blog_id;
364
365   # # the following hack is a workaround for getting args as one of:
366   # # $id, $content, $publish
367   # # $content, $publish
368   # # $content
369   # # $id, $content
370
371   # # i know.. this is a very ugly hack
372   # my $_arg_1 = shift;
373   # if ($_arg_1=~/^\d+$/){
374      # $page_id=$_arg_1;
375      # $content = shift;
376      # $publish = shift;
377
378	   # (defined $content and ( ref $content ) and ( ref $content eq 'HASH' ))
379         # or confess('content arg is not hash ref');
380   # }
381
382   # else {
383      # $content = $_arg_1;
384      # $publish = shift;
385      # ( defined $content and (ref $content) and (ref $content eq 'HASH'))
386         # or confess('content arg is not hash ref');
387
388      # $page_id = $content->{page_id}
389         # or confess("missing page_id in content hashref");
390   # }
391
392
393
394   # my $password   = $self->password;
395   # my $username   = $self->username;
396
397
398   # ( defined $page_id and $page_id=~/^\d+$/ )
399      # or confess('missing page id arg');
400
401
402	# unless (defined $publish) {
403		# $publish = $self->publish;
404	# }
405
406
407	# my $call = $self->server->call(
408		# 'wp.editPage',
409		# $blog_id,
410      # $page_id,
411      # $username,
412      # $password,
413		# $content,
414		# $publish,
415	# );
416
417	# if ( $self->_call_has_fault($call)){
418		# return;
419	# }
420
421	# my $result = $call->result;
422	# defined $result
423		# or die('no result');
424
425	# return $result;
426# }
427
428
429# OBSELETE
430# # xmlrpc.php: function wp_getPageList
431# sub getPageList {
432	# my $self = shift;
433	# my $blog_id = $self->blog_id;
434	# my $username = $self->username;
435	# my $password = $self->password;
436
437
438	# my $call = $self->server->call(
439		# 'wp.getPageList',
440		# $blog_id,
441		# $username,
442		# $password,
443	# );
444
445	# if ( $self->_call_has_fault($call)){
446		# return;
447	# }
448
449	# my $result = $call->result;
450	# defined $result
451		# or die('no result');
452
453	# return $result;
454# }
455
456# xmlrpc.php: function wp_getAuthors
457sub getAuthors {
458	my $self = shift;
459	my $blog_id = $self->blog_id;
460	my $username = $self->username;
461	my $password = $self->password;
462
463
464	my $call = $self->server->call(
465		'wp.getAuthors',
466		$blog_id,
467		$username,
468		$password,
469	);
470
471	return $self->_process_response($call);
472}
473
474
475#
476# OBSELETE
477# xmlrpc.php: function wp_newCategory
478# sub newCategory {
479	# my $self = shift;
480	# my $blog_id = $self->blog_id;
481	# my $username = $self->username;
482	# my $password = $self->password;
483	# my $category = shift;
484   # (ref $category and ref $category eq 'HASH')
485      # or croak("category must be a hash ref");
486
487   # $category->{name} or confess('missing name in category struct');
488
489
490   # ### $category
491
492	# defined $category or confess('missing category string');
493
494	# my $call = $self->server->call(
495		# 'wp.newCategory',
496		# $blog_id,
497		# $username,
498		# $password,
499		# $category,
500	# );
501
502	# if ( $self->_call_has_fault($call)){
503		# return;
504	# }
505
506	# my $result = $call->result;
507	# defined $result
508		# or die('no result');
509
510	# return $result;
511# }
512
513# xmlrpc.php: function wp_suggestCategories
514# sub suggestCategories {
515	# my $self = shift;
516	# my $blog_id = $self->blog_id;
517	# my $username = $self->username;
518	# my $password = $self->password;
519	# my $category = shift;
520	# my $max_results = shift; # optional
521
522
523
524	# my $call = $self->server->call(
525		# 'wp.suggestCategories',
526		# $blog_id,
527		# $username,
528		# $password,
529		# $category,
530		# $max_results,
531	# );
532
533	# if ( $self->_call_has_fault($call)){
534		# return;
535	# }
536
537	# my $result = $call->result;
538	# defined $result
539		# or die('no result');
540
541	# return $result;
542# }
543
544
545
546
547
548# OBSELETE
549# xmlrpc.php: function mw_newMediaObject
550# *uploadFile = \&newMediaObject;
551# sub newMediaObject {
552	# my $self = shift;
553	# my $blog_id = $self->blog_id;
554	# my $data = shift;
555
556   # defined $data or confess('missing data hash ref arg');
557   # ref $data eq 'HASH' or croak('arg is not hash ref');
558
559	# my $call = $self->server->call(
560		# 'metaWeblog.newMediaObject',
561		# $blog_id,
562      # $self->username,
563      # $self->password,
564		# $data,
565	# );
566
567	# if ( $self->_call_has_fault($call)){
568		# return;
569	# }
570
571	# my $result = $call->result;
572	# defined $result
573		# or die('no result');
574
575	# return $result;
576# }
577
578
579
580# xmlrpc.php: function mw_newPost
581sub newPost {
582	my $self = shift;
583	my $blog_id = $self->blog_id;
584	my $user_login = $self->username;
585	my $user_pass = $self->password;
586	my $content_struct = shift;
587	my $publish = shift;
588	unless (defined $publish) {
589		$publish = $self->publish;
590	}
591   defined $content_struct or confess('missing post hash ref arg');
592   ref $content_struct eq 'HASH' or croak('arg is not hash ref');
593
594	my $call = $self->server->call(
595		'metaWeblog.newPost',
596		$blog_id,
597		$user_login,
598		$user_pass,
599		$content_struct,
600		$publish,
601	);
602
603	return $self->_process_response($call);
604}
605
606# xmlrpc.php: function mw_editPost
607sub editPost {
608	my $self = shift;
609	my $post_id = shift;
610	my $user_login = $self->username;
611	my $user_pass = $self->password;
612	my $content_struct = shift;
613	my $publish = shift;
614	unless (defined $publish) {
615		$publish = $self->publish;
616	}
617
618	defined $post_id or confess('missing post id');
619	defined $content_struct or confess('missing content struct hash ref arg');
620   ref $content_struct eq 'HASH' or croak('arg is not hash ref');
621
622	my $call = $self->server->call(
623		'metaWeblog.editPost',
624		$post_id,
625		$user_login,
626		$user_pass,
627		$content_struct,
628		$publish,
629	);
630
631	return $self->_process_response($call);
632}
633
634# xmlrpc.php: function mw_getPost
635sub getPost {
636	my $self = shift;
637	my $post_id = shift;
638	my $user_login = $self->username;
639	my $user_pass = $self->password;
640   defined $post_id or confess('missing post id arg');
641
642
643	my $call = $self->server->call(
644		'metaWeblog.getPost',
645		$post_id,
646		$user_login,
647		$user_pass,
648	);
649
650	return $self->_process_response($call);
651}
652
653
654# OBSELETE
655# xmlrpc.php: function mw_getRecentPosts
656# sub getRecentPosts {
657	# my $self = shift;
658	# my $blog_id = $self->blog_id;
659	# my $user_login = $self->username;
660	# my $user_pass = $self->password;
661	# my $num_posts = shift;
662
663
664	# my $call = $self->server->call(
665		# 'metaWeblog.getRecentPosts',
666		# $blog_id,
667		# $user_login,
668		# $user_pass,
669		# $num_posts,
670	# );
671
672	# if ( $self->_call_has_fault($call)){
673		# return;
674	# }
675
676	# my $result = $call->result;
677	# defined $result
678		# or die('no result');
679
680	# return $result;
681# }
682
683
684# OBSELETE
685# xmlrpc.php: function mw_getCategories
686# sub getCategories {
687	# my $self = shift;
688	# my $blog_id = $self->blog_id;
689	# my $user_login = $self->username;
690	# my $user_pass = $self->password;
691
692
693	# my $call = $self->server->call(
694		# 'metaWeblog.getCategories',
695		# $blog_id,
696		# $user_login,
697		# $user_pass,
698	# );
699
700	# if ( $self->_call_has_fault($call)){
701		# return;
702	# }
703
704	# my $result = $call->result;
705	# defined $result
706		# or die('no result');
707
708	# return $result;
709# }
710
711
712# OBSELETE
713# # this nextone doesn't really exist.. this is a hack ..
714# # this is not keeping in par with xmlrpc.php but.. shikes..
715# sub getCategory {
716   # my $self = shift;
717   # my $id = shift;
718   # $id or croak('missing id argument');
719
720   # # get all categorise
721
722   # my @cat = grep { $_->{categoryId} == $id } @{$self->getCategories};
723
724   # @cat and scalar @cat
725      # or $self->errstr("Category id $id not found.")
726      # and return;
727
728   # return $cat[0];
729# }
730
731
732
733
734# xmlrpc.php: function blogger_deletePost
735sub deletePost {
736	my $self = shift;
737   my $blog_id = $self->blog_id;
738	my $post_id = shift;
739	my $user_login = $self->username;
740	my $user_pass = $self->password;
741	my $publish = shift;
742	unless (defined $publish) {
743		$publish = $self->publish;
744	}
745
746	defined $post_id or confess('missing post id');
747
748	my $call = $self->server->call(
749		'metaWeblog.deletePost',
750      $blog_id, #ignored
751		$post_id,
752		$user_login,
753		$user_pass,
754		$publish,
755	);
756
757	return $self->_process_response($call);
758}
759
760
761# OBSELETE
762# xmlrpc.php: function blogger_getTemplate
763# sub getTemplate { # TODO this fails, why????
764	# my $self = shift;
765	# my $blog_id = $self->blog_id;
766	# my $user_login = $self->username;
767	# my $user_pass = $self->password;
768	# my $template = shift;
769
770	# defined $template or confess('missing template string');
771   # ### $template
772   # ### $blog_id
773   # ### $user_login
774   # ### $user_pass
775	# my $call = $self->server->call(
776		# 'metaWeblog.getTemplate',
777		# $blog_id,
778		# $user_login,
779		# $user_pass,
780		# $template,
781	# );
782
783	# if ( $self->_call_has_fault($call)){
784		# return;
785	# }
786
787	# my $result = $call->result;
788	# defined $result
789		# or die('no result');
790
791	# return $result;
792# }
793
794# # xmlrpc.php: function blogger_setTemplate
795# sub setTemplate {
796	# my $self = shift;
797	# my $blog_id = $self->blog_id;
798	# my $user_login = $self->username;
799	# my $user_pass = $self->password;
800	# my $content = shift;
801	# my $template = shift;
802
803	# defined $template or confess('missing template string arg');
804	# defined $content or confess('missing content hash ref arg');
805   # ref $content eq 'HASH' or croak('arg is not hash ref');
806
807	# my $call = $self->server->call(
808		# 'metaWeblog.setTemplate',
809		# $blog_id,
810		# $user_login,
811		# $user_pass,
812		# $content,
813		# $template,
814	# );
815
816	# if ( $self->_call_has_fault($call)){
817		# return;
818	# }
819
820	# my $result = $call->result;
821	# defined $result
822		# or die('no result');
823
824	# return $result;
825# }
826
827# xmlrpc.php: function blogger_getUsersBlogs
828sub getUsersBlogs {
829	my $self = shift;
830	my $user_login = $self->username;
831	my $user_pass = $self->password;
832
833
834	my $call = $self->server->call(
835		'metaWeblog.getUsersBlogs',
836      $self->blog_id, # ignored
837		$user_login,
838		$user_pass,
839	);
840
841	return $self->_process_response($call);
842}
843
844# OBSELETE
845# xmlrpc.php: function wp_deleteCategory
846# sub deleteCategory {
847	# my $self = shift;
848	# my $blog_id = $self->blog_id;
849	# my $username = $self->username;
850	# my $password = $self->password;
851	# my $category_id = shift;
852   # _is_number($category_id);
853
854	# my $call = $self->server->call(
855		# 'wp.deleteCategory',
856		# $blog_id,
857		# $username,
858		# $password,
859		# $category_id,
860	# );
861
862	# if ( $self->_call_has_fault($call) ){
863		# return;
864	# }
865
866	# my $result = $call->result;
867	# defined $result
868		# or die('no result');
869
870	# return $result;
871# }
872
873# xmlrpc.php: function wp_deleteComment
874sub deleteComment {
875	my $self = shift;
876	my $blog_id = $self->blog_id;
877	my $username = $self->username;
878	my $password = $self->password;
879	my $comment_id = shift;
880   _is_number($comment_id);
881
882	my $call = $self->server->call(
883		'wp.deleteComment',
884		$blog_id,
885		$username,
886		$password,
887		$comment_id,
888	);
889
890	return $self->_process_response($call);
891}
892
893# xmlrpc.php: function wp_editComment
894sub editComment {
895	my $self = shift;
896	my $blog_id = $self->blog_id;
897	my $username = $self->username;
898	my $password = $self->password;
899	my $comment_id = shift;
900   _is_number($comment_id);
901
902	my $content_struct = shift;
903   _is_href($content_struct);
904
905	my $call = $self->server->call(
906		'wp.editComment',
907		$blog_id,
908		$username,
909		$password,
910		$comment_id,
911		$content_struct,
912	);
913
914	return $self->_process_response($call);
915}
916
917
918# xmlrpc.php: function wp_getComment
919sub getComment {
920	my $self = shift;
921	my $blog_id = $self->blog_id;
922	my $username = $self->username;
923	my $password = $self->password;
924	my $comment_id = shift;
925   _is_number($comment_id);
926
927	my $call = $self->server->call(
928		'wp.getComment',
929		$blog_id,
930		$username,
931		$password,
932		$comment_id,
933	);
934
935	return $self->_process_response($call);
936}
937
938# xmlrpc.php: function wp_getCommentCount
939sub getCommentCount {
940	my $self = shift;
941	my $blog_id = $self->blog_id;
942	my $username = $self->username;
943	my $password = $self->password;
944	my $post_id = shift;
945   _is_number($post_id);
946
947	my $call = $self->server->call(
948		'wp.getCommentCount',
949		$blog_id,
950		$username,
951		$password,
952		$post_id,
953	);
954
955	return $self->_process_response($call);
956}
957
958
959# xmlrpc.php: function wp_getCommentStatusList
960sub getCommentStatusList {
961	my $self = shift;
962	my $blog_id = $self->blog_id;
963	my $username = $self->username;
964	my $password = $self->password;
965
966	my $call = $self->server->call(
967		'wp.getCommentStatusList',
968		$blog_id,
969		$username,
970		$password,
971	);
972
973	return $self->_process_response($call);
974}
975
976
977# xmlrpc.php: function wp_getComments
978sub getComments {
979	my $self = shift;
980	my $blog_id = $self->blog_id;
981	my $username = $self->username;
982	my $password = $self->password;
983	my $struct = shift;
984   _is_href($struct);
985
986	my $call = $self->server->call(
987		'wp.getComments',
988		$blog_id,
989		$username,
990		$password,
991		$struct,
992	);
993
994	return $self->_process_response($call);
995}
996
997
998# xmlrpc.php: function wp_getOptions
999sub getOptions {
1000	my $self = shift;
1001	my $blog_id = $self->blog_id;
1002	my $username = $self->username;
1003	my $password = $self->password;
1004	my $options = shift;
1005
1006	my $call = $self->server->call(
1007		'wp.getOptions',
1008		$blog_id,
1009		$username,
1010		$password,
1011		$options,
1012	);
1013
1014   $call or warn("no call");
1015
1016	return $self->_process_response($call);
1017}
1018
1019
1020
1021# OBSELETE
1022# xmlrpc.php: function wp_getPageStatusList
1023# sub getPageStatusList {
1024	# my $self = shift;
1025	# my $blog_id = $self->blog_id;
1026	# my $username = $self->username;
1027	# my $password = $self->password;
1028
1029	# my $call = $self->server->call(
1030		# 'wp.getPageStatusList',
1031		# $blog_id,
1032		# $username,
1033		# $password,
1034	# );
1035
1036	# if ( $self->_call_has_fault($call) ){
1037		# return;
1038	# }
1039
1040	# my $result = $call->result;
1041	# defined $result
1042		# or die('no result');
1043
1044	# return $result;
1045# }
1046
1047
1048# # OBSELETE
1049# # xmlrpc.php: function wp_getPageTemplates
1050# sub getPageTemplates {
1051	# my $self = shift;
1052	# my $blog_id = $self->blog_id;
1053	# my $username = $self->username;
1054	# my $password = $self->password;
1055
1056	# my $call = $self->server->call(
1057		# 'wp.getPageTemplates',
1058		# $blog_id,
1059		# $username,
1060		# $password,
1061	# );
1062
1063	# if ($self->_call_has_fault($call)){
1064		# return;
1065	# }
1066
1067	# my $result = $call->result;
1068	# defined $result
1069		# or die('no result');
1070
1071	# return $result;
1072# }
1073
1074
1075
1076# xmlrpc.php: function wp_getPostStatusList
1077sub getPostStatusList {
1078	my $self = shift;
1079	my $blog_id = $self->blog_id;
1080	my $username = $self->username;
1081	my $password = $self->password;
1082
1083	my $call = $self->server->call(
1084		'wp.getPostStatusList',
1085		$blog_id,
1086		$username,
1087		$password,
1088	);
1089
1090	return $self->_process_response($call);
1091}
1092
1093#
1094# OBSELETE
1095# # xmlrpc.php: function wp_getTags
1096# sub getTags {
1097	# my $self = shift;
1098	# my $blog_id = $self->blog_id;
1099	# my $username = $self->username;
1100	# my $password = $self->password;
1101
1102	# my $call = $self->server->call(
1103		# 'wp.getTags',
1104		# $blog_id,
1105		# $username,
1106		# $password,
1107	# );
1108
1109	# if ($self->_call_has_fault($call)){
1110		# return;
1111	# }
1112
1113	# my $result = $call->result;
1114	# defined $result
1115		# or die('no result');
1116
1117	# return $result;
1118# }
1119
1120
1121# xmlrpc.php: function wp_newComment
1122sub newComment {
1123	my $self = shift;
1124	my $blog_id = $self->blog_id;
1125	my $username = $self->username;
1126	my $password = $self->password;
1127	my $post = shift;
1128	my $content_struct = shift;
1129   _is_href($content_struct);
1130
1131	my $call = $self->server->call(
1132		'wp.newComment',
1133		$blog_id,
1134		$username,
1135		$password,
1136		$post,
1137		$content_struct,
1138	);
1139
1140	return $self->_process_response($call);
1141}
1142
1143
1144# xmlrpc.php: function wp_setOptions
1145sub setOptions {
1146	my $self = shift;
1147	my $blog_id = $self->blog_id;
1148	my $username = $self->username;
1149	my $password = $self->password;
1150	my $options = shift;
1151
1152	my $call = $self->server->call(
1153		'wp.setOptions',
1154		$blog_id,
1155		$username,
1156		$password,
1157		$options,
1158	);
1159
1160	return $self->_process_response($call);
1161}
1162
1163# TESTED FROM HERE
1164
1165sub getUser {
1166	my $self = shift;
1167	my $blog_id = $self->blog_id;
1168	my $username = $self->username;
1169	my $password = $self->password;
1170	my $args = shift;
1171	my $user_id = $args->{'id'};
1172	my $fields = $args->{'fields'};
1173
1174	defined $user_id or confess("Argument 'id' is missing");
1175	_is_number($user_id);
1176
1177	$fields = undef unless defined($fields);
1178	croak("Argument 'fields' is not an array reference") if defined($fields) and ref $fields ne 'ARRAY';
1179
1180	my $call = $self->server->call(
1181		'wp.getUser',
1182		$blog_id,
1183		$username,
1184		$password,
1185		$user_id,
1186		$fields
1187	);
1188
1189	return $self->_process_response($call);
1190}
1191
1192sub getUsers {
1193	my $self = shift;
1194	my $blog_id = $self->blog_id;
1195	my $username = $self->username;
1196	my $password = $self->password;
1197	my $args = shift;
1198	my $filter = $args->{'filter'};
1199	my $fields = $args->{'fields'};
1200
1201	$fields = undef unless defined($fields);
1202	croak("Argument 'fields' is not an array reference") if defined($fields) and ref $fields ne 'ARRAY';
1203	$filter = undef unless defined($filter);
1204	croak("Argument 'filter' is not a hash reference") if defined($filter) and ref $filter ne 'HASH';
1205
1206	my $call = $self->server->call(
1207		'wp.getUsers',
1208		$blog_id,
1209		$username,
1210		$password,
1211		$filter,
1212		$fields
1213	);
1214
1215	return $self->_process_response($call);
1216}
1217
1218sub createUser
1219{
1220	my $self = shift;
1221	my $username = $self->username;
1222	my $password = $self->password;
1223	my $user = shift;
1224
1225	# Check arguments
1226	$user = undef unless defined($user);
1227	croak('Missing argument - hash reference of user information') unless defined($user);
1228	croak('Argument is not a hash reference') unless ref $user eq 'HASH';
1229	croak('User information must contain user_login') unless defined($user->{'user_login'});
1230	croak('User information must contain user_email') unless defined($user->{'user_email'});
1231	croak('User information must contain user_password') unless defined($user->{'user_pass'});
1232
1233	# Manipulate arguments
1234	$user->{'role'} = lc($user->{'role'}) if defined($user->{'role'});	# otherwise they don't match with real WP roles
1235
1236	my $call = $self->server->call(
1237		'wpext.callWpMethod',
1238		$username,
1239		$password,
1240		'wp_insert_user',
1241		$user
1242	);
1243
1244	return $self->_process_response($call);
1245}
1246
1247sub addUserMeta
1248{
1249	my $self = shift;
1250	my $username = $self->username;
1251	my $password = $self->password;
1252	my $meta = shift;
1253
1254	# Check arguments
1255	$meta = undef unless defined($meta);
1256	croak('Missing argument - hash reference of user meta') unless defined($meta);
1257	croak('Argument is not a hash reference') unless ref $meta eq 'HASH';
1258	croak('User information must contain user_id') unless defined($meta->{'user_id'});
1259	croak('user_id isn\'t a number') unless looks_like_number($meta->{'user_id'});
1260	croak('User information must contain meta_key') unless defined($meta->{'meta_key'});
1261	croak('User information must contain meta_value') unless defined($meta->{'meta_value'});
1262	$meta->{'unique'} = 'false' unless defined($meta->{'unique'});
1263	croak('Unique should be "true" or "false"') unless ($meta->{'unique'} eq "true" || $meta->{'unique'} eq "false");
1264
1265	my $call = $self->server->call(
1266		'wpext.callWpMethod',
1267		$username,
1268		$password,
1269		'add_user_meta',
1270		$meta->{'user_id'}, $meta->{'meta_key'}, $meta->{'meta_value'}, $meta->{'unique'}
1271	);
1272
1273	return $self->_process_response($call);
1274}
1275
1276sub getUserMeta
1277{
1278	my $self = shift;
1279	my $username = $self->username;
1280	my $password = $self->password;
1281	my $meta = shift;
1282
1283	# Check arguments
1284	$meta = undef unless defined($meta);
1285	croak('Missing argument - hash reference of user meta requirements') unless defined($meta);
1286	croak('Argument is not a hash reference') unless ref $meta eq 'HASH';
1287	croak('User information must contain user_id') unless defined($meta->{'user_id'});
1288	croak('user_id isn\'t a number') unless looks_like_number($meta->{'user_id'});
1289	$meta->{'meta_key'} = '' unless defined($meta->{'meta_key'});
1290	$meta->{'single'} = 'false' unless defined($meta->{'single'});
1291	croak('Single should be "true" or "false"') unless ($meta->{'single'} eq "true" || $meta->{'single'} eq "false");
1292
1293	my $call = $self->server->call(
1294		'wpext.callWpMethod',
1295		$username,
1296		$password,
1297		'get_user_meta',
1298		$meta->{'user_id'}, $meta->{'meta_key'}, $meta->{'single'}
1299	);
1300
1301	return $self->_process_response($call);
1302}
1303__END__
1304# lib/WordPress/XMLRPC.pod
1305