Overview

Namespaces

  • None
  • PHP

Classes

  • RESTian
  • RESTian_Application_Json_Parser
  • RESTian_Application_Serialized_Php_Parser
  • RESTian_Application_Xml_Parser
  • RESTian_Auth_Provider_Base
  • RESTian_Base
  • RESTian_Basic_Http_Auth_Provider
  • RESTian_Client
  • RESTian_Http_Agent_Base
  • RESTian_Not_Applicable_Provider
  • RESTian_Parser_Base
  • RESTian_Php_Curl_Http_Agent
  • RESTian_Request
  • RESTian_Response
  • RESTian_Service
  • RESTian_Settings
  • RESTian_Text_Csv_Parser
  • RESTian_Text_Html_Parser
  • RESTian_Text_Plain_Parser
  • RESTian_Var
  • RESTian_WordPress_Http_Agent
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  • Download
  1: <?php
  2: 
  3: define( 'RESTIAN_VER', '0.4.0' );
  4: define( 'RESTIAN_DIR', dirname( __FILE__ ) );
  5: 
  6: require(RESTIAN_DIR . '/core-classes/class-base.php');
  7: require(RESTIAN_DIR . '/core-classes/class-client.php');
  8: require(RESTIAN_DIR . '/core-classes/class-request.php');
  9: require(RESTIAN_DIR . '/core-classes/class-response.php');
 10: require(RESTIAN_DIR . '/core-classes/class-var.php');
 11: require(RESTIAN_DIR . '/core-classes/class-service.php');
 12: require(RESTIAN_DIR . '/core-classes/class-settings.php');
 13: 
 14: require(RESTIAN_DIR . '/base-classes/class-http-agent.php');
 15: require(RESTIAN_DIR . '/base-classes/class-auth-provider.php');
 16: require(RESTIAN_DIR . '/base-classes/class-parser.php');
 17: 
 18: /**
 19:  *
 20:  */
 21: class RESTian {
 22:   protected static $_clients = array();
 23:   protected static $_auth_providers = array();
 24:   protected static $_parsers = array();
 25:   protected static $_http_agents = array();
 26:   protected static $_filters = array();
 27: 
 28:   /**
 29:    * @param $client_name
 30:    * @param string|array $client If string then the class name of the RESTian client. If array, $args to find it.
 31:    *
 32:    * @notes $client_name can be any of the following format:
 33:    *
 34:    *   'local_short_code' - If all code it local
 35:    *   'github_user_name/github_repo_name' - If code is on GitHub, master branch latest commit (not smart)
 36:    *   'github_user_name/github_repo_name/tag_name' - If code is on GitHub, tagged commit
 37:    *   'repo_host/user_name/repo_name' - If code is on GitHub or BitBucket, master branch latest commit (not smart)
 38:    *   'repo_host/user_name/repo_name/tag_name' - If code is on GitHub or BitBucket, tagged commit
 39:    *
 40:    *  'repo_host' => 'github.com' or 'bitbucket.org'
 41:    *
 42:    */
 43:   static function register_client( $client_name, $client ) {
 44:     self::$_clients[$client_name] = $client;
 45:   }
 46: 
 47:   /**
 48:    * @param $client_name
 49:    */
 50:   static function get_new_client( $client_name ) {
 51:   }
 52: 
 53:   /**
 54:    * Registers a result parser class based on the mime type.
 55:    *
 56:    * @see: https://www.iana.org/assignments/media-types/index.html
 57:    *
 58:    * @param string $content_type valid mime type of RESTian shortcut (xml,json,html,plain,csv)
 59:    * @param bool|string $class_name Name of class that defines this Parser
 60:    * @param bool|string $filepath Full local file path for the file containing the class.
 61:    */
 62:   static function register_parser( $content_type, $class_name = false, $filepath = false ) {
 63:     $content_type = self::expand_content_type( $content_type );
 64:     /**
 65:      * Hardcode the predefined parser types this way because it appears this is most performant approach
 66:      * and most efficient use of memory vs. pre-registering them.
 67:      * Predefined types ignore class_name and filepath.
 68:      */
 69:     $internal = true;
 70:     switch ( $content_type ) {
 71:       case 'application/xml':
 72:         $parser = array(
 73:           'class_name'=> 'RESTian_Application_Xml_Parser',
 74:           'filepath'   => RESTIAN_DIR . '/parsers/application-xml-parser.php',
 75:         );
 76:         break;
 77:       case 'application/json':
 78:         $parser = array(
 79:           'class_name'=> 'RESTian_Application_Json_Parser',
 80:           'filepath'   => RESTIAN_DIR . '/parsers/application-json-parser.php',
 81:         );
 82:         break;
 83:       case 'text/plain':
 84:         $parser = array(
 85:           'class_name'=> 'RESTian_Text_Plain_Parser',
 86:           'filepath'   => RESTIAN_DIR . '/parsers/text-plain-parser.php',
 87:         );
 88:         break;
 89:       case 'text/html':
 90:         $parser = array(
 91:           'class_name'=> 'RESTian_Text_Html_Parser',
 92:           'filepath'   => RESTIAN_DIR . '/parsers/text-html-parser.php',
 93:         );
 94:         break;
 95:       case 'text/csv':
 96:         $parser = array(
 97:           'class_name'=> 'RESTian_Text_Csv_Parser',
 98:           'filepath'   => RESTIAN_DIR . '/parsers/text-csv-parser.php',
 99:         );
100:         break;
101:       case 'application/vnd.php.serialized':
102:         $parser = array(
103:           'class_name'=> 'RESTian_Application_Serialized_Php_Parser',
104:           'filepath'   => RESTIAN_DIR . '/parsers/application-serialized-php.php',
105:         );
106:         break;
107: 
108:       default:
109:         $internal = false;
110:         /**
111:          * Or if an externally defined auth parser, do this:
112:          */
113:         $parser = array(
114:           'class_name'=> $class_name,
115:           'filepath'   => $filepath,
116:         );
117:         break;
118:     }
119:     if ( $internal )
120:       if ( $class_name ) {
121:         $parser['class_name'] = $class_name;
122: 
123:       if ( $filepath )
124:         $parser['filepath'] = $filepath;
125:     }
126:     $parser['content_type'] = $content_type;
127:     self::$_parsers[$content_type] = $parser;
128:   }
129:   /**
130:    * Constructs a new Parser instance
131:    *
132:    * @param string $content_type
133:    * @param RESTian_Request $request
134:    * @param RESTian_Response $response
135:    * @param array $args
136:    * @return RESTian_Parser
137:    */
138:   static function get_new_parser( $content_type, $request, $response, $args = array() ) {
139:     if ( ! isset( self::$_parsers[$content_type] ) ) {
140:       self::register_parser( $content_type );
141:     }
142:     $parser = self::$_parsers[$content_type];
143:     if ( isset( $parser['class_name'] ) && isset( $parser['filepath'] ) && file_exists( $parser['filepath'] ) ) {
144:       require_once( $parser['filepath'] );
145:       $class_name = $parser['class_name'];
146:     }
147:     if ( isset( $class_name ) && class_exists( $class_name ) ) {
148:       $parser = new $class_name( $request, $response );
149:     } else {
150:       $response->set_error( 'NO_PARSER', sprintf( 'There is no parser registered for content type %s.', $content_type ) );
151:       $parser = false;
152:     }
153:     return $parser;
154:   }
155:   /**
156:    * Registers an Auth Provider type
157:    *
158:    * @param string $provider_type RESTian-specific type of Auth Provider
159:    * @param bool|string $class_name Name of class that defines this Auth Provider
160:    * @param bool|string $filepath Full local file path for the file containing the class.
161:    */
162:   static function register_auth_provider( $provider_type, $class_name = false, $filepath = false ) {
163:     /**
164:      * Hardcode the predefined provider types this way because it appears this is most performant approach
165:      * and most efficient use of memory vs. pre-registering them.
166:      * Predefined types ignore class_name and filepath.
167:      */
168:     $internal = true;
169:     switch ( $provider_type ) {
170:       case 'n/a':
171:         $provider = array(
172:           'class_name'=> 'RESTian_Not_Applicable_Provider',
173:           'filepath'   => RESTIAN_DIR . '/auth-providers/not-applicable-auth-provider.php',
174:         );
175:         break;
176:       case 'basic_http':
177:         $provider = array(
178:           'class_name'=> 'RESTian_Basic_Http_Auth_Provider',
179:           'filepath'   => RESTIAN_DIR . '/auth-providers/basic-http-auth-provider.php',
180:         );
181:         break;
182:       default:
183:         $internal = false;
184:         /**
185:          * Or if an externally defined auth provider, do this:
186:          */
187:         $provider = array(
188:           'class_name'=> $class_name,
189:           'filepath'   => $filepath,
190:         );
191:         break;
192:     }
193:     if ( $internal ) {
194:       if ( $class_name )
195:         $provider['class_name'] = $class_name;
196: 
197:       if ( $filepath )
198:         $provider['filepath'] = $filepath;
199:     }
200:     $provider['provider_type'] = $provider_type;
201:     self::$_auth_providers[$provider_type] = $provider;
202:   }
203:   /**
204:    * Constructs a new Auth Provider instance
205:    *
206:    * @param string $auth_type RESTian-specific type of auth providers
207:    * @param bool|RESTian_Client $api - The API that's dping the calling
208:    * @return RESTian_Auth_Provider_Base
209:    */
210:   static function get_new_auth_provider( $auth_type, $api = false ) {
211:     $provider = false;
212:     if ( ! isset( self::$_auth_providers[$auth_type] ) ) {
213:       /**
214:        * Try to register a provider for this auth type.
215:        */
216:       self::register_auth_provider( $auth_type );
217:       $provider = self::$_auth_providers[$auth_type];
218:       require_once( $provider['filepath'] );
219:       $class_name = $provider['class_name'];
220:     } else if ( ! isset( self::$_auth_providers[$auth_type]['instance'] ) ) {
221:       $provider = self::$_auth_providers[$auth_type];
222:       $class_name = $provider['class_name'];
223:       if ( ! class_exists( $class_name ) )
224:         require_once( $provider['filepath'] );
225:     } else {
226:       $provider = self::$_auth_providers[$auth_type]['instance'];
227:       /**
228:        * Resetting $api in case it is different instance than the one that was used before.
229:        */
230:       $provider->api = $api;
231:     }
232:     if ( isset( $class_name ) ) {
233:       $provider = new $class_name( $api );
234:       $provider->auth_type = $auth_type;
235:       self::$_auth_providers[$auth_type]['instance'] = $provider;
236:     }
237:     return $provider;
238:   }
239: 
240:   /**
241:    * Registers an HTTP Agent type
242:    *
243:    * @param string $agent_type RESTian-specific type of HTTP agent
244:    * @param bool|string $class_name Name of class that defines this HTTP agent
245:    * @param bool|string $filepath Full local file path for the file containing the class.
246:    */
247:   static function register_http_agent( $agent_type, $class_name = false, $filepath = false ) {
248:     /**
249:      * Hardcode the predefined agent types this way because it appears this is most performant approach
250:      * and most efficient use of memory vs. pre-registering them.
251:      * Predefined types ignore class_name and filepath.
252:      */
253:     $internal = true;
254:     switch ( $agent_type ) {
255:       case 'wordpress':
256:         $agent = array(
257:           'class_name'=> 'RESTian_WordPress_Http_Agent',
258:           'filepath'   => RESTIAN_DIR . '/http-agents/wordpress-http-agent.php',
259:         );
260:         break;
261:       case 'php_curl':
262:         $agent = array(
263:           'class_name'=> 'RESTian_Php_Curl_Http_Agent',
264:           'filepath'   => RESTIAN_DIR . '/http-agents/php-curl-http-agent.php',
265:         );
266:         break;
267:       default:
268:         $internal = false;
269:         /**
270:          * Or if an externally defined http agent, do this:
271:          */
272:         $agent = array(
273:           'class_name'=> $class_name,
274:           'filepath'   => $filepath,
275:         );
276:         break;
277:     }
278:     if ( $internal ) {
279:       if ( $class_name )
280:         $agent['class_name'] = $class_name;
281: 
282:       if ( $filepath )
283:         $agent['filepath'] = $filepath;
284:     }
285:     $agent['agent_type'] = $agent_type;
286:     self::$_http_agents[$agent_type] = $agent;
287:   }
288: 
289:   /**
290:    * Constructs a new HTTP Agent instance
291:    *
292:    * @param string $agent_type RESTian-specific type of HTTP agent
293:    * @return RESTian_Http_Agent_Base
294:    */
295:   static function get_new_http_agent( $agent_type ) {
296:     if ( isset( self::$_http_agents[$agent_type] ) ) {
297:       $class_name = self::$_http_agents[$agent_type]['class_name'];
298:     } else {
299:       self::register_http_agent( $agent_type );
300:       $agent = self::$_http_agents[$agent_type];
301:       require_once( $agent['filepath'] );
302:       $class_name = $agent['class_name'];
303:     }
304:     return new $class_name( $agent_type );
305:   }
306: 
307:   /**
308:    * Expands the following shortcut content types to their valid mime type:
309:    *
310:    * @see: https://www.iana.org/assignments/media-types/index.html
311:    *
312:    *   xml    => application/xml
313:    *   json   => application/json
314:    *   form   => application/x-www-form-urlencoded
315:    *   html   => text/html
316:    *   plain  => text/plain
317:    *   csv    => text/csv
318:    *
319:    * @param string $content_type
320:    * @return string
321:    */
322:   static function expand_content_type( $content_type ) {
323:     if ( false !== strpos( 'jx', $content_type[0] ) )  {
324:       $content_type = preg_replace( '#^(json|xml)$#', 'application/$1', $content_type );
325:     } else if ( false !== strpos( 'htc', $content_type[0] ) ) {
326:       $content_type = preg_replace( '#^(html|text|csv)$#', 'text/$1', $content_type );
327:     } else if ( 'form' == $content_type ) {
328:       $content_type = 'application/x-www-form-urlencoded';
329:     }
330:     return $content_type;
331:   }
332: 
333:   /**
334:    * Parses a string of arguments using a data format optimized for the use-case.
335:    *
336:    * The data format is similar to URL query string format but it uses vertical bars ('|') as seperators
337:    * instead of ampersands ('&') because ampersands are frequently used in URLs. Names without no equals
338:    * sign ('=') following are set to boolean true. Names prefixed with exclamation point ('!') will negate
339:    * the value they would otherwise have, so a name with an exclamation point and no equals sign will
340:    * be set to boolean false which is the primary use case for the ('!') syntax.
341:    *
342:    * @example 'foo|!bar|baz=zoom' parses to
343:    *
344:    *     array(
345:    *       'foo' => true,
346:    *       'bar' => false,
347:    *       'baz' => 'zoom',
348:    *    )
349:    *
350:    * @param $args
351:    * @return array
352:    */
353:   static function parse_args( $args ) {
354:     if ( is_string( $args ) ) {
355:       $args = explode( '|', $args );
356:       $new_args = array();
357:       foreach( $args as $arg ) {
358:         list( $name, $value ) = array_map( 'trim', explode( '=', "{$arg}=" ) );
359:         if ( 0 == strlen( $value ) ) {
360:           $value = true;
361:         } else if ( preg_match( '#^(true|false)$#', $value ) ) {
362:           $value = 't' == $value[0];
363:         }
364:         if ( '!' ==$name[0] ) {
365:           /**
366:            * If $name begins with '!' then we want to NOT it's value.
367:            * If no values was passed (i.e. "!omit_body" was the value) then
368:            * then that will set 'omit_body' => true which was the goal of
369:            * adding this syntax sugar.
370:            */
371:           $name = substr( $name, 1 );
372:           $value = ! $value;
373:         }
374:         $new_args[$name] = $value;
375:       }
376:       $args = $new_args;
377:     }
378:     return $args;
379:   }
380:   /**
381:    * Takes a like this 'color,type=all,size' and translates into an array that looks like this:
382:    *
383:    *     array(
384:    *       'color' => true,
385:    *       'type'  => 'all'
386:    *       'size'  => true
387:    *     );
388:    *
389:    * @param string $string
390:    * @param string $separator
391:    * @return array
392:    */
393:   static function parse_string( $string, $separator = ',' ) {
394:     $array = array_fill_keys( explode( $separator, $string ), true );
395:     foreach( $array as $name => $value ) {
396:       unset( $array[$name] );
397:       if ( preg_match( '#=#', $name ) ) {
398:         list( $name, $value ) = explode( '=', $name );
399:       }
400:       $array[$name] = $value;
401:     }
402:     return $array;
403:   }
404:   /**
405:      * Parses comma seperated transforms like this:
406:      *
407:      *     fill[/],replace[a][b],trim
408:      *
409:      * To this:
410:      *
411:      *    array(
412:      *      'fill' => '/'
413:      *       'replace' => array( 'a','b' ),
414:      *       'trim' => true,
415:      *     )
416:      *
417:      * @param string $string
418:      * @param string $separator
419:      * @return array
420:      */
421:   static function parse_transforms( $string, $separator = ',' ) {
422:     $transforms = RESTian::parse_string( $string, $separator );
423:     $new_transforms = array();
424:     foreach( array_keys( $transforms ) as $name ) {
425:       if ( ! preg_match( '#\[#', $name ) ) {
426:         $new_transforms[$name] = true;
427:       } else {
428:         $data = explode( '[', $name );
429:         $name = array_shift( $data );
430:         foreach( $data as $index => $value ) {
431:           $data[$index] = trim( $value, '][' );
432:         }
433:         $new_transforms[$name] = 1 == count( $data ) ? $data[0] : $data;
434:       }
435:     }
436:     return $new_transforms;
437:   }
438: 
439:   /**
440:    * @param array $args
441:    * @param array $shortnames
442:    * @return array
443:    */
444:   static function expand_shortnames( $args, $shortnames = array() ) {
445:     foreach( $args as $property_name => $value ) {
446:       if ( isset( $shortnames[$property_name] ) ) {
447:         $args[$shortnames[$property_name]] = $value;
448:         unset( $args[$property_name] );
449:       }
450:     }
451:     return $args;
452:   }
453:   /**
454:    * Adds a filter hook for an object
455:    *
456:    *    RESTian::add_filter( 'filter_data', array( $this, 'filter_data' ) );
457:    *    RESTian::add_filter( 'filter_data', array( $this, 'filter_data' ), 11 );
458:    *    RESTian::add_filter( 'filter_data', 'special_func' );
459:    *    RESTian::add_filter( 'filter_data', 'special_func', 11 );
460:    *    RESTian::add_filter( 'filter_data', array( __CLASS__, 'filter_data' ) );
461:    *    RESTian::add_filter( 'filter_data', array( __CLASS__, 'filter_data' ), 11 );
462:    *    RESTian::add_filter( 'filter_data', array( new SpecialClass(), 'filter_data' ) );
463:    *    RESTian::add_filter( 'filter_data', array( new SpecialClass(), 'filter_data' ), 11 );
464:    *
465:    * @param string $filter_name
466:    * @param array|string $callable
467:    * @param int $priority
468:    *
469:    * @return mixed
470:    */
471:   static function add_filter( $filter_name, $callable, $priority = 10 ) {
472:     if ( is_string( $callable ) ) {
473:       $function = "{$callable}()";
474:     } else if ( is_array( $callable ) ) {
475:       if ( is_string( $callable[0] ) ) {
476:         $function = "{$callable[0]}::{$callable[1]}()";
477:       } else if ( is_object( $callable[0] ) ) {
478:         $object_hash = spl_object_hash( $callable[0] );
479:         $function = "{$object_hash}->{$callable[1]}()";
480:       }
481:     }
482:     self::$_filters[$filter_name][$function][$priority][] = $callable;
483:   }
484: 
485:   /**
486:    * Adds a filter hook for an object
487:    *
488:    *    RESTian::add_action( 'process_action', array( $this, 'process_action' ) );
489:    *    RESTian::add_action( 'process_action', array( $this, 'process_action' ), 11 );
490:    *    RESTian::add_action( 'process_action', 'special_func' );
491:    *    RESTian::add_action( 'process_action', 'special_func', 11 );
492:    *    RESTian::add_action( 'process_action', array( __CLASS__, 'process_action' ) );
493:    *    RESTian::add_action( 'process_action', array( __CLASS__, 'process_action' ), 11 );
494:    *    RESTian::add_action( 'process_action', array( new SpecialClass(), 'process_action' ) );
495:    *    RESTian::add_action( 'process_action', array( new SpecialClass(), 'process_action' ), 11 );
496:    *
497:    * @param string $action_name
498:    * @param array|string $callable
499:    * @param int $priority
500:    *
501:    * @return mixed
502:    */
503:   static function add_action( $action_name, $callable, $priority = 10 ) {
504:     self::add_filter( $action_name, $callable, $priority );
505:   }
506: 
507:   /**
508:    * Return a list of filters
509:    *
510:    * @param string $filter_name
511:    *
512:    * @return mixed
513:    */
514:   static function get_filters( $filter_name ) {
515:     return isset( self::$_filters[$filter_name] ) ? self::$_filters[$filter_name] : false;
516:   }
517: }
518: 
API documentation generated by ApiGen 2.8.0