1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: abstract class RESTian_Client extends RESTian_Base {
16:
17: 18: 19:
20: var $caller;
21:
22: 23: 24:
25: protected $_services = array();
26:
27: 28: 29:
30: protected $_vars = array();
31:
32: 33: 34:
35: protected $_var_sets = array();
36:
37: 38: 39:
40: protected $_settings = array();
41:
42: 43: 44:
45: protected $_defaults = array(
46: 'var' => array(),
47: 'services' => array(),
48: );
49: 50: 51:
52: protected $_intialized = false;
53: 54: 55:
56: protected $_credentials = false;
57: 58: 59:
60: protected $_grant = false;
61: 62: 63:
64: protected $_auth_service = false;
65: 66: 67:
68: protected $_user_agent;
69: 70: 71: 72: 73: 74:
75: var $auth_type = 'basic_http';
76: 77: 78:
79:
80: 81: 82:
83: var $api_name;
84: 85: 86:
87: var $base_url;
88: 89: 90:
91: var $api_version;
92: 93: 94:
95: var $http_agent;
96: 97: 98:
99: var $cache_callback = false;
100: 101: 102:
103: var $use_cache = false;
104: 105: 106:
107: var $request;
108: 109: 110:
111: var $response;
112:
113: 114: 115:
116: function __construct( $caller = false ) {
117: $this->caller = $caller;
118: 119: 120:
121: $this->api_version = date( DATE_ISO8601, time() );
122: $this->http_agent = defined( 'WP_CONTENT_DIR') && function_exists( 'wp_remote_get' ) ? 'wordpress' : 'php_curl';
123: }
124:
125: 126: 127:
128: function get_user_agent() {
129: if ( ! $this->_user_agent ) {
130: $this->_user_agent = str_replace( '_', ' ', get_class( $this ) );
131: if ( false === strpos( $this->_user_agent, 'Client' ) )
132: $this->_user_agent .= " Client";
133: $this->_user_agent .= ' [uses RESTian for PHP]';
134:
135: 136: 137:
138: $auth_provider = $this->get_auth_provider();
139: if ( $auth_provider->auth_version )
140: $this->_user_agent .= " v{$auth_provider->auth_version}";
141: }
142: return $this->_user_agent;
143: }
144: 145: 146:
147: function get_cachable() {
148: return serialize( array(
149: 'vars' => $this->_vars,
150: 'services' => $this->_services,
151: ));
152: }
153:
154: 155: 156:
157: function initialize_from( $cached ) {
158: $values = unserialize( $cached );
159: $this->_vars = $values['vars'];
160: $this->_services = $values['services'];
161: }
162:
163: 164: 165: 166: 167: 168: 169:
170: function set_credentials( $credentials ) {
171: 172: 173: 174:
175: $this->_credentials = array_intersect_key( $credentials, $this->get_auth_provider()->get_new_credentials() );
176: }
177:
178: 179: 180:
181: function get_credentials() {
182: return $this->_credentials;
183: }
184:
185: 186: 187: 188: 189: 190: 191:
192: function set_grant( $grant ) {
193: 194: 195: 196:
197: $this->_grant = array_intersect_key( $grant, $this->get_auth_provider()->get_new_grant() );
198: }
199:
200: 201: 202: 203: 204:
205: function maybe_set_grant( $grant ) {
206: if ( $grant && ! is_array( $this->_grant ) );
207: $this->set_grant( $grant );
208: }
209:
210: 211: 212:
213: function get_grant() {
214: return $this->_grant;
215: }
216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229:
230: function is_grant( $grant = array() ) {
231: return false !== $grant && $this->get_auth_provider()->is_grant( $grant );
232: }
233: 234: 235: 236: 237:
238: function has_grant() {
239: return $this->is_grant( $this->_grant );
240: }
241: 242: 243:
244: function get_auth_service() {
245: $this->initialize_client();
246: if ( ! $this->_auth_service ) {
247: $this->_auth_service = $this->get_service( 'authenticate' );
248: }
249: return $this->_auth_service;
250: }
251:
252: 253: 254:
255: function get_auth_provider() {
256: return RESTian::get_new_auth_provider( $this->auth_type, $this );
257: }
258:
259: 260: 261: 262: 263: 264: 265: 266: 267:
268: function is_credentials( $credentials ) {
269: 270: 271:
272: return $this->get_auth_provider()->is_credentials( $credentials );
273: }
274:
275: 276: 277: 278: 279:
280: function get_message() {
281: 282: 283:
284: return $this->get_auth_provider()->message;
285: }
286:
287: 288: 289: 290: 291: 292: 293: 294:
295: function has_credentials() {
296: 297: 298:
299: return $this->is_credentials( $this->_credentials );
300: }
301:
302: 303: 304: 305: 306:
307: function register_service_defaults( $defaults ) {
308: return $this->_register_defaults( 'services', $defaults );
309: }
310:
311: 312: 313:
314: function get_service_defaults() {
315: return $this->_get_defaults( 'services' );
316: }
317:
318: 319: 320: 321: 322:
323: function register_var_defaults( $defaults ) {
324: return $this->_register_defaults( 'vars', $defaults );
325: }
326:
327: 328: 329:
330: function get_var_defaults() {
331: return $this->_get_defaults( 'vars' );
332: }
333:
334: 335: 336: 337: 338: 339:
340: function _register_defaults( $type, $defaults ) {
341: return $this->_defaults[$type] = array_merge( $this->_defaults[$type], RESTian::parse_args( $defaults ) );
342: }
343:
344: 345: 346: 347: 348:
349: function _get_defaults( $type ) {
350: return $this->_defaults[$type];
351: }
352:
353: 354: 355: 356: 357: 358: 359:
360: function register_service( $service_name, $args ) {
361:
362: if ( is_a( $args, 'RESTian_Service' ) ) {
363: $args->service_name = $service_name;
364: $service = $args;
365: } else {
366: $service = new RESTian_Service( $service_name, $this, RESTian::parse_args( $args ) );
367: }
368: $this->_services[$service_name] = $service;
369: return $service;
370: }
371: 372: 373: 374: 375: 376: 377:
378: function register_action( $resource_name, $args ) {
379: $args = RESTian::parse_args( $args );
380: $args['service_type'] = 'action';
381: return $this->register_service( $resource_name, $args );
382: }
383: 384: 385: 386: 387: 388: 389:
390: function register_resource( $resource_name, $args = array() ) {
391: $args = RESTian::parse_args( $args );
392: $args['service_type'] = 'resource';
393: return $this->register_service( $resource_name, $args );
394: }
395: 396: 397: 398: 399:
400: function register_var( $var_name, $args = array() ) {
401: $this->_vars[$var_name] = new RESTian_Var( $var_name, RESTian::parse_args( $args ) );
402: }
403: 404: 405: 406:
407: function get_var( $var_name ) {
408: return $this->_vars[$var_name];
409: }
410: 411: 412: 413:
414: function register_var_set( $var_set_name, $vars = array() ) {
415: $this->_var_sets[$var_set_name] = RESTian::parse_string( $vars );
416: }
417: 418: 419:
420: function get_var_set( $var_set_name ) {
421: return $this->_var_sets[$var_set_name];
422: }
423: 424: 425: 426: 427: 428: 429:
430: function get_new_credentials() {
431: $credentials = $this->get_auth_provider()->get_new_credentials();
432: if ( ! $credentials )
433: $credentials = array();
434: return $credentials;
435: }
436:
437: 438: 439: 440: 441: 442:
443: function authenticate( $credentials = false ) {
444: if ( ! $credentials )
445: $credentials = $this->_credentials;
446:
447: if ( ! $this->_credentials )
448: $this->_credentials = $credentials;
449:
450: $this->_auth_service = $this->get_auth_service();
451:
452: 453: 454:
455: $auth_provider = $this->get_auth_provider();
456:
457: $this->request = new RESTian_Request( null, array(
458: 'credentials' => $credentials,
459: 'service' => $this->_auth_service,
460: ));
461:
462: if ( ! $this->is_credentials( $credentials ) ) {
463: $response = new RESTian_Response( array(
464: 'request' => $this->request,
465: ));
466: $response->set_error( 'NO_AUTH', 'Credentials not provided. Please enter your credentials.' );
467: } else {
468: 469: 470:
471: $response = $this->make_request( $this->request );
472: $response->authenticated = $auth_provider->authenticated( $response );
473: if( ! $response->authenticated ) {
474: $response->set_error( 'BAD_AUTH', $auth_provider->message );
475: } else {
476: $auth_provider->capture_grant( $response );
477: }
478: }
479: return $response;
480: }
481: 482: 483: 484: 485: 486: 487:
488: function get_resource( $resource_name, $vars = null, $args = null ) {
489: $service = $this->get_service( $resource_name );
490: if ( 'resource' != $service->service_type ) {
491: throw new Exception( 'Service type must be "resource" to use get_resource(). Consider using call_service() or invoke_action() instead.' );
492: }
493: $this->response = $this->call_service( $service, 'GET', $vars, $args );
494: return $this->response;
495: }
496: 497: 498: 499: 500: 501: 502:
503: function post_resource( $resource_name, $body = null, $args = null ) {
504: $service = $this->get_service( $resource_name );
505: if ( 'resource' != $service->service_type ) {
506: throw new Exception( 'Service type must be "resource" to use post_resource(). Consider using call_service() or invoke_action() instead.' );
507: }
508: $this->response = $this->call_service( $service, 'POST', $vars, $args );
509: return $this->response;
510: }
511: 512: 513: 514: 515: 516: 517:
518: function invoke_action( $action_name, $vars = null, $args = null ) {
519: $service = $this->get_service( $action_name );
520: if ( 'action' != $service->service_type ) {
521: throw new Exception( 'Service type must be "action" to use invoke_action(). Consider using call_service() or get_resource() instead.' );
522: }
523: $this->response = $this->call_service( $service, 'DO', $vars, $args );
524: return $this->response;
525: }
526: 527: 528: 529: 530: 531: 532: 533:
534: function call_service( $service, $method = 'GET', $vars = null, $args = null ) {
535: $this->initialize_client();
536: $args['service'] = is_object( $service ) ? $service : $this->get_service( $service );
537: $request = new RESTian_Request( $vars, $args );
538: 539: 540: 541:
542: $request->http_method = 'DO' == $method ? 'GET' : $method;
543:
544: if ( isset( $args['credentials'] ) ) {
545: $this->_credentials = $args['credentials'];
546: }
547: $request->set_credentials( $this->_credentials );
548:
549: if ( isset( $args['grant'] ) ) {
550: $this->_grant = $args['grant'];
551: }
552: $request->set_grant( $this->_grant );
553:
554: return $this->process_response( $this->make_request( $request ), $vars, $args );
555: }
556:
557: 558: 559: 560:
561: function make_request( $request ) {
562: $auth_provider = $this->get_auth_provider();
563: $auth_provider->prepare_request( $request );
564: $this->do_action( 'prepare_request', $request );
565: if ( method_exists( $auth_provider, 'make_request' ) ) {
566: $response = $auth_provider->make_request( $request );
567: } else {
568: $response = $request->make_request();
569: }
570: return $response;
571: }
572: 573: 574: 575: 576: 577: 578: 579:
580: function process_response( $response, $vars = array(), $args = array() ) {
581: return $response;
582: }
583: 584: 585: 586: 587:
588: function initialize(){
589: $this->_subclass_exception( 'must define initialize().' );
590: }
591: 592: 593: 594:
595: function initialize_client() {
596: if ( $this->_intialized )
597: return;
598: $this->_intialized = true;
599:
600: $cached = $this->cache_callback ? call_user_func( $this->cache_callback, $this ) : false;
601: if ( $cached ) {
602: $this->initialize_from( $cached );
603: } else {
604: 605: 606:
607: $this->initialize();
608: 609: 610:
611: $auth_service = $this->get_service( 'authenticate' );
612: if ( ! $auth_service ) {
613: 614: 615:
616: $auth_service = new RESTian_Service( 'authenticate', $this, array(
617: 'path' => '/authenticate',
618: ));
619: $this->register_service( 'authenticate', $auth_service );
620: }
621: if ( $this->cache_callback )
622: call_user_func( $this->cache_callback, $this, $this->get_cachable() );
623: }
624: }
625: 626: 627:
628: function get_cached() {
629: return false;
630: }
631:
632: 633: 634:
635: function cache( $cachable ) {
636: }
637: 638: 639: 640: 641: 642: 643:
644: function get_service( $service ) {
645: if ( ! is_a( $service, 'RESTian_Service' ) ) {
646: $this->initialize_client();
647: if ( ! isset( $this->_services[$service] ) ) {
648: $service = false;
649: } else {
650: $service = $this->_services[$service];
651: $service->context = $this;
652: }
653: }
654: return $service;
655: }
656: 657: 658: 659: 660: 661:
662: function get_error_message( $error_code ) {
663: return false;
664: }
665: 666: 667: 668: 669: 670: 671: 672:
673: function get_service_url( $service ) {
674: if ( is_string( $service ) )
675: $service = $this->get_service( $service );
676: $service_url = rtrim( $this->base_url, '/' ) . '/' . ltrim( $service->path, '/' );
677: return $service_url;
678: }
679:
680: 681: 682: 683: 684: 685:
686: protected function _subclass_exception( $message ) {
687: throw new Exception( 'Class ' . get_class($this) . ' [subclass of ' . __CLASS__ . '] ' . $message );
688: }
689:
690: 691: 692: 693: 694: 695: 696: 697:
698: function needs_credentials( $service ) {
699: return true;
700: }
701:
702: 703: 704: 705: 706: 707:
708: function register_settings( $settings_name, $args ) {
709: $this->_settings[$settings_name] = new RESTian_Settings( $settings_name, RESTian::parse_args( $args ) );
710: }
711:
712: 713: 714: 715: 716:
717: function get_settings( $settings_name ) {
718: return isset( $this->_settings[$settings_name] ) ? $this->_settings[$settings_name] : false;
719: }
720:
721: 722: 723: 724: 725:
726: function has_settings( $settings_name ) {
727: return isset( $this->_settings[$settings_name] );
728: }
729:
730: 731: 732: 733: 734: 735: 736:
737: function has_resource( $resource_name ) {
738: $service = $this->get_service( $resource_name );
739: return $service && 'resource' == $service->service_type;
740: }
741:
742: 743: 744: 745: 746:
747: function __call( $method_name, $args ) {
748: $result = false;
749: $resource_name = preg_replace( '#^get_(.*)$#', '$1', $method_name );
750: if ( ! $this->has_resource( $resource_name ) ) {
751: 752: 753:
754: } else {
755: array_unshift( $args, $resource_name );
756: $response = call_user_func_array( array( $this, 'get_resource' ), $args );
757: $result = ! $response->is_error() ? $response->data : false;
758: }
759: return $result;
760: }
761:
762: 763: 764: 765: 766:
767: function validate_email( $email ) {
768: return filter_var( $email, FILTER_VALIDATE_EMAIL );
769: }
770:
771: 772: 773: 774: 775:
776: function sanitize_email( $email ) {
777: return filter_var( $email, FILTER_SANITIZE_EMAIL );
778: }
779:
780: 781: 782: 783: 784: 785:
786: function sanitize_string( $string, $flags = false ) {
787: if ( ! $flags )
788: $flags = FILTER_FLAG_ENCODE_LOW | FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP;
789: return filter_var( $string, FILTER_SANITIZE_STRING, $flags );
790: }
791:
792: }
793:
794: