WC_CLI_Runner

WC API to WC CLI Bridge.

Defined (1)

The class is defined in the following location(s).

/includes/cli/class-wc-cli-runner.php  
  1. class WC_CLI_Runner { 
  2. /** 
  3. * Endpoints to disable (meaning they will not be avaiable as CLI commands). 
  4. * Some of these can either be done via WP already, or are offered with 
  5. * some other changes (like tools). 
  6. */ 
  7. private static $disabled_endpoints = array( 
  8. 'settings',  
  9. 'settings/(?P<group_id>[\w-]+)',  
  10. 'settings/(?P<group_id>[\w-]+)/batch',  
  11. 'settings/(?P<group_id>[\w-]+)/(?P<id>[\w-]+)',  
  12. 'system_status',  
  13. 'system_status/tools',  
  14. 'system_status/tools/(?P<id>[\w-]+)',  
  15. 'reports',  
  16. 'reports/sales',  
  17. 'reports/top_sellers',  
  18. ); 
  19.  
  20. /** 
  21. * The version of the REST API we should target to 
  22. * generate commands. 
  23. */ 
  24. private static $target_rest_version = 'v2'; 
  25.  
  26. /** 
  27. * Register's all endpoints as commands once WP and WC have all loaded. 
  28. */ 
  29. public static function after_wp_load() { 
  30. global $wp_rest_server; 
  31. $wp_rest_server = new WP_REST_Server; 
  32. do_action( 'rest_api_init', $wp_rest_server ); 
  33.  
  34. $request = new WP_REST_Request( 'GET', '/' ); 
  35. $request->set_param( 'context', 'help' ); 
  36. $response = $wp_rest_server->dispatch( $request ); 
  37. $response_data = $response->get_data(); 
  38. if ( empty( $response_data ) ) { 
  39. return; 
  40.  
  41. // Loop through all of our endpoints and register any valid WC endpoints. 
  42. foreach ( $response_data['routes'] as $route => $route_data ) { 
  43. // Only register endpoints for WC and our target version. 
  44. if ( substr( $route, 0, 4 + strlen( self::$target_rest_version ) ) !== '/wc/' . self::$target_rest_version ) { 
  45. continue; 
  46.  
  47. // Only register endpoints with schemas 
  48. if ( empty( $route_data['schema']['title'] ) ) { 
  49. WP_CLI::debug( sprintf( __( 'No schema title found for %s, skipping REST command registration.', 'woocommerce' ), $route ), 'wc' ); 
  50. continue; 
  51. // Ignore batch endpoints 
  52. if ( 'batch' === $route_data['schema']['title'] ) { 
  53. continue; 
  54. // Disable specific endpoints 
  55. $route_pieces = explode( '/', $route ); 
  56. $endpoint_piece = str_replace( '/wc/' . $route_pieces[2] . '/', '', $route ); 
  57. if ( in_array( $endpoint_piece, self::$disabled_endpoints ) ) { 
  58. continue; 
  59.  
  60. self::register_route_commands( new WC_CLI_REST_Command( $route_data['schema']['title'], $route, $route_data['schema'] ), $route, $route_data ); 
  61.  
  62. /** 
  63. * Generates command information and tells WP CLI about all 
  64. * commands avaiable from a route. 
  65. * @param string $rest_command 
  66. * @param string $route 
  67. * @param array $route_data 
  68. * @param array $command_args 
  69. */ 
  70. private static function register_route_commands( $rest_command, $route, $route_data, $command_args = array() ) { 
  71. // Define IDs that we are looking for in the routes (in addition to id) 
  72. // so that we can pass it to the rest command, and use it here to generate documentation. 
  73. $supported_ids = array( 
  74. 'id' => __( 'ID.', 'woocommerce' ),  
  75. 'product_id' => __( 'Product ID.', 'woocommerce' ),  
  76. 'customer_id' => __( 'Customer ID.', 'woocommerce' ),  
  77. 'order_id' => __( 'Order ID.', 'woocommerce' ),  
  78. 'refund_id' => __( 'Refund ID.', 'woocommerce' ),  
  79. 'attribute_id' => __( 'Attribute ID.', 'woocommerce' ),  
  80. 'zone_id' => __( 'Zone ID.', 'woocommerce' ),  
  81. ); 
  82. $rest_command->set_supported_ids( $supported_ids ); 
  83. $positional_args = array_keys( $supported_ids ); 
  84.  
  85. $parent = "wc {$route_data['schema']['title']}"; 
  86. $supported_commands = array(); 
  87.  
  88. // Get a list of supported commands for each route. 
  89. foreach ( $route_data['endpoints'] as $endpoint ) { 
  90. $parsed_args = preg_match_all( '#\([^\)]+\)#', $route, $matches ); 
  91. $first_match = $matches[0]; 
  92. $resource_id = ! empty( $matches[0] ) ? array_pop( $matches[0] ) : null; 
  93. $trimmed_route = rtrim( $route ); 
  94. $is_singular = substr( $trimmed_route, - strlen( $resource_id ) ) === $resource_id; 
  95. if ( ! $is_singular ) { 
  96. $resource_id = $first_match; 
  97. $command = ''; 
  98.  
  99. // List a collection 
  100. if ( array( 'GET' ) == $endpoint['methods'] && ! $is_singular ) { 
  101. $supported_commands['list'] = ! empty( $endpoint['args'] ) ? $endpoint['args'] : array(); 
  102. // Create a specific resource 
  103. if ( array( 'POST' ) == $endpoint['methods'] && ! $is_singular ) { 
  104. $supported_commands['create'] = ! empty( $endpoint['args'] ) ? $endpoint['args'] : array(); 
  105. // Get a specific resource 
  106. if ( array( 'GET' ) == $endpoint['methods'] && $is_singular ) { 
  107. $supported_commands['get'] = ! empty( $endpoint['args'] ) ? $endpoint['args'] : array(); 
  108. // Update a specific resource 
  109. if ( in_array( 'POST', $endpoint['methods'] ) && $is_singular ) { 
  110. $supported_commands['update'] = ! empty( $endpoint['args'] ) ? $endpoint['args'] : array(); 
  111. // Delete a specific resource 
  112. if ( array( 'DELETE' ) == $endpoint['methods'] && $is_singular ) { 
  113. $supported_commands['delete'] = ! empty( $endpoint['args'] ) ? $endpoint['args'] : array(); 
  114.  
  115. foreach ( $supported_commands as $command => $endpoint_args ) { 
  116. $synopsis = array(); 
  117. $arg_regs = array(); 
  118.  
  119. foreach ( $supported_ids as $id_name => $id_desc ) { 
  120. if ( strpos( $route, '<' . $id_name . '>' ) !== false ) { 
  121. $synopsis[] = array( 
  122. 'name' => $id_name,  
  123. 'type' => 'positional',  
  124. 'description' => $id_desc,  
  125. 'optional' => false,  
  126. ); 
  127.  
  128. if ( in_array( $command, array( 'delete', 'get', 'update' ) ) ) { 
  129. $synopsis[] = array( 
  130. 'name' => 'id',  
  131. 'type' => 'positional',  
  132. 'description' => __( 'The id for the resource.', 'woocommerce' ),  
  133. 'optional' => false,  
  134. ); 
  135.  
  136. foreach ( $endpoint_args as $name => $args ) { 
  137. if ( ! in_array( $name, $positional_args ) ) { 
  138. $arg_regs[] = array( 
  139. 'name' => $name,  
  140. 'type' => 'assoc',  
  141. 'description' => ! empty( $args['description'] ) ? $args['description'] : '',  
  142. 'optional' => empty( $args['required'] ) ? true : false,  
  143. ); 
  144.  
  145. foreach ( $arg_regs as $arg_reg ) { 
  146. $synopsis[] = $arg_reg; 
  147.  
  148. if ( in_array( $command, array( 'list', 'get' ) ) ) { 
  149. $synopsis[] = array( 
  150. 'name' => 'fields',  
  151. 'type' => 'assoc',  
  152. 'description' => __( 'Limit response to specific fields. Defaults to all fields.', 'woocommerce' ),  
  153. 'optional' => true,  
  154. ); 
  155. $synopsis[] = array( 
  156. 'name' => 'field',  
  157. 'type' => 'assoc',  
  158. 'description' => __( 'Get the value of an individual field.', 'woocommerce' ),  
  159. 'optional' => true,  
  160. ); 
  161. $synopsis[] = array( 
  162. 'name' => 'format',  
  163. 'type' => 'assoc',  
  164. 'description' => __( 'Render response in a particular format.', 'woocommerce' ),  
  165. 'optional' => true,  
  166. 'default' => 'table',  
  167. 'options' => array( 
  168. 'table',  
  169. 'json',  
  170. 'csv',  
  171. 'ids',  
  172. 'yaml',  
  173. 'count',  
  174. 'headers',  
  175. 'body',  
  176. 'envelope',  
  177. ),  
  178. ); 
  179.  
  180. if ( in_array( $command, array( 'create', 'update', 'delete' ) ) ) { 
  181. $synopsis[] = array( 
  182. 'name' => 'porcelain',  
  183. 'type' => 'flag',  
  184. 'description' => __( 'Output just the id when the operation is successful.', 'woocommerce' ),  
  185. 'optional' => true,  
  186. ); 
  187.  
  188. $methods = array( 
  189. 'list' => 'list_items',  
  190. 'create' => 'create_item',  
  191. 'delete' => 'delete_item',  
  192. 'get' => 'get_item',  
  193. 'update' => 'update_item',  
  194. ); 
  195.  
  196. $before_invoke = null; 
  197. if ( empty( $command_args['when'] ) && \WP_CLI::get_config( 'debug' ) ) { 
  198. $before_invoke = function() { 
  199. if ( ! defined( 'SAVEQUERIES' ) ) { 
  200. define( 'SAVEQUERIES', true ); 
  201. }; 
  202.  
  203. WP_CLI::add_command( "{$parent} {$command}", array( $rest_command, $methods[ $command ] ), array( 
  204. 'synopsis' => $synopsis,  
  205. 'when' => ! empty( $command_args['when'] ) ? $command_args['when'] : '',  
  206. 'before_invoke' => $before_invoke,  
  207. ) );