      1: <?php
      2:
      3: /**
      4:  * Base class for a simplied Web API access for PHP with emphasis on WordPress.
      5:  *
      6:  * RESTian can be used without WordPress, but its design is WordPress influenced.
      7:  *
      8:  * Uses Exceptions ONLY to designate obvious programming errors. IOW, callers of
      9:  * this client do NOT need to use try {} catch {} because RESTian_Client should
     10:  * only throw exceptions when there code has well understood bugs.
     11:  *
     12:  * @priorart: https://guzzlephp.org/guide/service/service_descriptions.html
     13:  *
     14:  */
     15: abstract class RESTian_Client extends RESTian_Base {
     16:
     17:   /**
     18:    * @var object Enables the caller to attach itself so subclasses can access the caller. Our use case was for the WordPress plugin class.
     19:    */
     20:   var $caller;
     21:
     22:   /**
     23:    * @var array Of RESTian_Services; provides API service specific functionality
     24:    */
     25:   protected $_services = array();
     26:
     27:   /**
     28:    * @var array Of name value pairs that can be used to query an API
     29:    */
     30:   protected $_vars = array();
     31:
     32:   /**
     33:    * @var array Of named var sets
     34:    */
     35:   protected $_var_sets = array();
     36:
     37:   /**
     38:    * @var array Of service/request/response settings
     39:    */
     40:   protected $_settings = array();
     41:
     42:   /**
     43:    * @var array -
     44:    */
     45:   protected $_defaults = array(
     46:     'var'       => array(),
     47:     'services'   => array(),
     48:   );
     49:   /**
     50:    * @var bool Set to true once API is initialized.
     51:    */
     52:   protected $_intialized = false;
     53:   /**
     54:    * @var bool|array Properties needed for credentials
     55:    */
     56:   protected $_credentials = false;
     57:   /**
     58:    * @var bool|array Properties needed for grant
     59:    */
     60:   protected $_grant = false;
     61:   /**
     62:    * @var bool|RESTian_Service
     63:    */
     64:   protected $_auth_service = false;
     65:   /**
     66:    * @var string Description of the client used to make the request. Will default unless set.
     67:    */
     68:   protected $_user_agent;
     69:   /**
     70:    * @var string - The type of authorization, as defined by RESTian.
     71:    *
     72:    * In future might be RESTian-specific 'oauth_2_auth_code', 'oauth_2_password', 'oauth_1a', etc.
     73:    *
     74:    */
     75:   var $auth_type = 'basic_http';
     76:   /**
     77:    * @var RESTian_Service for authenticating  - to be set by subclass.
     78:    */
     79: //  var $auth_service;
     80:   /**
     81:    * @var string Human readable name of the API  - to be set by subclass.
     82:    */
     83:   var $api_name;
     84:   /**
     85:    * @var string The API's base URL - to be set by the subclass calling this classes constructor.
     86:    */
     87:   var $base_url;
     88:   /**
     89:    * @var string The version of the API used - to be set by the subclass calling this classes constructor.
     90:    */
     91:   var $api_version;
     92:   /**
     93:    * @var string
     94:    */
     95:   var $http_agent;
     96:   /**
     97:    * @var bool|callable
     98:    */
     99:   var $cache_callback = false;
    100:   /**
    101:    * @var bool
    102:    */
    103:   var $use_cache = false;
    104:   /**
    105:    * @var RESTian_Request
    106:    */
    107:   var $request;
    108:   /**
    109:    * @var RESTian_Response
    110:    */
    111:   var $response;
    112:
    113:   /**
    114:    * @param object|bool $caller
    115:    */
    116:   function __construct( $caller = false ) {
    117:     $this->caller = $caller;
    118:     /**
    119:      * Set the API Version to be changed every second for development.  If not in development set in subclass.
    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:    * @return string
    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:        * @var RESTian_Auth_Provider_Base $auth
    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:    * @return string
    146:    */
    147:   function get_cachable() {
    148:     return serialize( array(
    149:       'vars' => $this->_vars,
    150:       'services' => $this->_services,
    151:     ));
    152:   }
    153:
    154:   /**
    155:    * @param $cached
    156:    */
    157:   function initialize_from( $cached ) {
    158:     $values = unserialize( $cached );
    159:     $this->_vars = $values['vars'];
    160:     $this->_services = $values['services'];
    161:   }
    162:
    163:   /**
    164:    * Set the grants value.
    165:    *
    166:    * Note: Throws away keys that are not needed.
    167:    *
    168:    * @param $credentials
    169:    */
    170:   function set_credentials( $credentials ) {
    171:     /**
    172:      * Extract just the array elements that are specific to the credentials.
    173:      * @see https://stackoverflow.com/a/4240153/102699
    174:      */
    175:     $this->_credentials = array_intersect_key( $credentials, $this->get_auth_provider()->get_new_credentials() );
    176:   }
    177:
    178:   /**
    179:    * @return array|bool
    180:    */
    181:   function get_credentials() {
    182:     return $this->_credentials;
    183:   }
    184:
    185:   /**
    186:    * Set the grant value.
    187:    *
    188:    * Note: Throws away keys that are not needed.
    189:    *
    190:    * @param $grant
    191:    */
    192:   function set_grant( $grant ) {
    193:     /**
    194:      * Extract just the array elements that are specific to the grant.
    195:      * @see https://stackoverflow.com/a/4240153/102699
    196:      */
    197:     $this->_grant = array_intersect_key( $grant, $this->get_auth_provider()->get_new_grant() );
    198:   }
    199:
    200:   /**
    201:    * Set the grant value but only if not already set.
    202:    *
    203:    * @param $grant
    204:    */
    205:   function maybe_set_grant( $grant ) {
    206:     if ( $grant && ! is_array( $this->_grant ) );
    207:       $this->set_grant( $grant );
    208:   }
    209:
    210:   /**
    211:    * @return array|bool
    212:    */
    213:   function get_grant() {
    214:     return $this->_grant;
    215:   }
    216:   /**
    217:    * Returns true if the grant passed is validated by the auth provider.
    218:    *
    219:    * This does NOT mean we ARE authenticated but that we should ASSUME we are and try doing calls without
    220:    * first authenticating. This functionality is defined because the client (often a WordPress plugin) may
    221:    * have captured auth info from a prior page load where this class did authenticate, but this class is not
    222:    * in control of maintaining that auth info so we can only assume it is correct if the client of this code
    223:    * tells us it is by giving us completed credentials (or maybe some other way we discover as this code evolves
    224:    * base on new use-cases.) Another use-case where our assumption will fail is if the access_key expires or has
    225:    * since been revoked.
    226:    *
    227:    * @param array|bool $grant
    228:    * @return array|bool
    229:    */
    230:   function is_grant( $grant = array() ) {
    231:     return false !== $grant && $this->get_auth_provider()->is_grant( $grant );
    232:   }
    233:   /**
    234:    * Returns true if the contained grant is validated by the auth provider.
    235:    *
    236:    * @return array|bool
    237:    */
    238:   function has_grant() {
    239:     return $this->is_grant( $this->_grant );
    240:   }
    241:   /**
    242:    * @return bool|RESTian_Service
    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:    * @return RESTian_Auth_Provider_Base
    254:    */
    255:   function get_auth_provider() {
    256:     return RESTian::get_new_auth_provider( $this->auth_type, $this );
    257:   }
    258:
    259:   /**
    260:    * Evaluate passed credentials to see if the auth provider considers the credentials to be valid.
    261:    *
    262:    * This does not authenticate, it just makes sure we have credentials that might work. IOW, if username or
    263:    * password are empty for basic auth then clearly we don't have credentials.
    264:    *
    265:    * @param array|bool $credentials
    266:    * @return array|bool
    267:    */
    268:   function is_credentials( $credentials ) {
    269:     /**
    270:      * Request will delegate to auth provider to see if it has credentials.
    271:      */
    272:     return $this->get_auth_provider()->is_credentials( $credentials );
    273:   }
    274:
    275:   /**
    276:    * Retrieves the last error message set by the auth provider
    277:    *
    278:    * @return string
    279:    */
    280:   function get_message() {
    281:     /**
    282:      * Request will delegate to auth provider to return an error message.
    283:      */
    284:     return $this->get_auth_provider()->message;
    285:   }
    286:
    287:   /**
    288:    * Evaluate if the the contained credentials are considered to be valid.
    289:    *
    290:    * This does not authenticate, it just makes sure we have credentials that might work. IOW, if username or
    291:    * password are empty for basic auth then clearly we don't have credentials.
    292:    *
    293:    * @return array|bool
    294:    */
    295:   function has_credentials() {
    296:     /**
    297:      * Request will delegate to auth provider to see if it has credentials.
    298:      */
    299:     return $this->is_credentials( $this->_credentials );
    300:   }
    301:
    302:   /**
    303:    * @param $defaults
    304:    *
    305:    * @return array
    306:    */
    307:   function register_service_defaults( $defaults ) {
    308:     return $this->_register_defaults( 'services', $defaults );
    309:   }
    310:
    311:   /**
    312:    * @return mixed
    313:    */
    314:   function get_service_defaults() {
    315:     return $this->_get_defaults( 'services' );
    316:   }
    317:
    318:   /**
    319:    * @param $defaults
    320:    *
    321:    * @return array
    322:    */
    323:   function register_var_defaults( $defaults ) {
    324:     return $this->_register_defaults( 'vars', $defaults );
    325:   }
    326:
    327:   /**
    328:    * @return mixed
    329:    */
    330:   function get_var_defaults() {
    331:     return $this->_get_defaults( 'vars' );
    332:   }
    333:
    334:   /**
    335:    * @param $type
    336:    * @param $defaults
    337:    *
    338:    * @return array
    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:    * @param $type
    346:    *
    347:    * @return mixed
    348:    */
    349:   function _get_defaults( $type ) {
    350:     return $this->_defaults[$type];
    351:   }
    352:
    353:   /**
    354:    * Allow a subclass to register an API service.
    355:    *
    356:    * @param string $service_name
    357:    * @param array|RESTian_Service $args
    358:    * @return RESTian_Service
    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:    * Allow a subclass to register an API action.
    373:    *
    374:    * @param string $resource_name
    375:    * @param array|RESTian_Service $args
    376:    * @return RESTian_Service
    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:    * Allow a subclass to register an API resource.
    385:    *
    386:    * @param string $resource_name
    387:    * @param array|RESTian_Service $args
    388:    * @return RESTian_Service
    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:    * @param string $var_name
    397:    * @param array $args
    398:    * @throws Exception
    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:    * @param string $var_name
    405:    * @return RESTian_Var
    406:    */
    407:   function get_var( $var_name ) {
    408:     return $this->_vars[$var_name];
    409:   }
    410:   /**
    411:    * @param string $var_set_name
    412:    * @param array $vars
    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:    * @param string $var_set_name
    419:    */
    420:   function get_var_set( $var_set_name ) {
    421:     return $this->_var_sets[$var_set_name];
    422:   }
    423:   /**
    424:    * Returns empty object of created credentials information.
    425:    *
    426:    * Can be overridden by subclass is credentials requirements are custom.
    427:    *
    428:    * @return array
    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:    * Authenticate against the API.
    439:    *
    440:    * @param bool|array $credentials
    441:    * @return RESTian_Response
    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:      * @var RESTian_Auth_Provider_Base
    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:        * @var RESTian_Response $response
    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:    * @param string|RESTian_Service $resource_name
    483:    * @param array $vars
    484:    * @param array|object $args
    485:    * @return object|RESTian_Response
    486:    * @throws Exception
    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:    * @param string|RESTian_Service $resource_name
    498:    * @param array $body
    499:    * @param array|object $args
    500:    * @return object|RESTian_Response
    501:    * @throws Exception
    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:    * @param string|RESTian_Service $action_name
    513:    * @param array $vars
    514:    * @param array|object $args
    515:    * @return object|RESTian_Response
    516:    * @throws Exception
    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:    * @param string|RESTian_Service $service
    528:    * @param string $method HTTP methods 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD' and RESTian method 'DO'
    529:    * @param null|array $vars
    530:    * @param null|array|object $args
    531:    * @return object|RESTian_Response
    532:    * @throws Exception
    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:      * @todo This will need to be updated when we have a use-case where actions require 'POST'
    540:      * @todo ...or maybe we'll evolve RESTian to deprecate actions?
    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:    * @param RESTian_Request $request
    559:    * @return RESTian_Response $response
    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:    * Stub that allows subclass to process request, if needed.
    574:    *
    575:    * @param RESTian_Response $response
    576:    * @param null|array $vars
    577:    * @param null|array $args
    578:    * @return RESTian_Response $response
    579:    */
    580:   function process_response( $response, $vars = array(), $args = array() ) {
    581:     return $response;
    582:   }
    583:   /**
    584:    * Call subclass to register all the services and params.
    585:    *
    586:    * Must subclass.
    587:    */
    588:   function initialize(){
    589:     $this->_subclass_exception( 'must define initialize().' );
    590:   }
    591:   /**
    592:    * Subclass if needed.
    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:        * Call initialize() in the subclass.
    606:        */
    607:       $this->initialize();
    608:       /**
    609:        * Initialize the auth_service property.
    610:        */
    611:       $auth_service = $this->get_service( 'authenticate' );
    612:       if ( ! $auth_service ) {
    613:         /**
    614:          * So the subclass did not create an authenticate service, use default.
    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:    * Override in subclass in the case caching of client serialization is wanted
    627:    */
    628:   function get_cached() {
    629:     return false;
    630:   }
    631:
    632:   /**
    633:    * Override in subclass in the case caching of client serialization is wanted
    634:    */
    635:   function cache( $cachable ) {
    636:   }
    637:   /**
    638:    * Get the service object based on its name
    639:    *
    640:    * @param string|RESTian_Service $service
    641:    * @return bool|RESTian_Service
    642:    * @throws Exception
    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:    * Subclass if needed.
    658:    *
    659:    * @param $error_code
    660:    * @return string
    661:    */
    662:   function get_error_message( $error_code ) {
    663:     return false;
    664:   }
    665:   /**
    666:    * Returns the URL for a given service.
    667:    *
    668:    * Subclass if needed.
    669:    *
    670:    * @param RESTian_Service $service
    671:    * @return bool|string
    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:    * Used to throw an exception when not properly subclassed.
    682:    *
    683:    * @param $message
    684:    * @throws Exception
    685:    */
    686:   protected function _subclass_exception( $message ) {
    687:     throw new Exception( 'Class ' . get_class($this) . ' [subclass of ' . __CLASS__ . '] ' . $message );
    688:   }
    689:
    690:   /**
    691:    * Returns true if a service needs credentials, false if not.
    692:    * Useful for Registration methods that do not require any sort of
    693:    *
    694:    * @param RESTian_Service $service
    695:    *
    696:    * @return bool
    697:    */
    698:   function needs_credentials( $service ) {
    699:     return true;
    700:   }
    701:
    702:   /**
    703:    * Register a settings
    704:    *
    705:    * @param string $settings_name
    706:    * @param array|string $args
    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:    * @param string $settings_name
    714:    *
    715:    * @return bool
    716:    */
    717:   function get_settings( $settings_name ) {
    718:     return isset( $this->_settings[$settings_name] ) ? $this->_settings[$settings_name] : false;
    719:   }
    720:
    721:   /**
    722:    * @param string $settings_name
    723:    *
    724:    * @return bool
    725:    */
    726:   function has_settings( $settings_name ) {
    727:     return isset( $this->_settings[$settings_name] );
    728:   }
    729:
    730:   /**
    731:    * Checks to see if a names resource has been registered.
    732:    *
    733:    * @param $resource_name
    734:    *
    735:    * @return bool
    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:    * @param string $method_name
    744:    * @param array $args
    745:    * @return bool|object|RESTian_Response
    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:        * Add error message in a debug mode saying there is no resource by that name?
    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:    * @param string $email
    764:    *
    765:    * @return bool
    766:    */
    767:   function validate_email( $email ) {
    768:     return filter_var( $email, FILTER_VALIDATE_EMAIL );
    769:   }
    770:
    771:   /**
    772:    * @param string $email
    773:    *
    774:    * @return string
    775:    */
    776:   function sanitize_email( $email ) {
    777:     return filter_var( $email, FILTER_SANITIZE_EMAIL );
    778:   }
    779:
    780:   /**
    781:    * @param string $string
    782:    * @param bool $flags
    783:    *
    784:    * @return string
    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: