Ticket #2968: 2968.diff
| File 2968.diff, 23.7 KB (added by , 9 years ago) |
|---|
-
wp-content/plugins/wporg-markdown/README.md
1 # WPORG Markdown Importer 2 3 Imports Markdown from a remote site (like GitHub) into WordPress as pages. 4 5 ## Configuration 6 7 Each importer needs to override the abstract methods: 8 9 * `get_base()` - Base URL for imported pages. This will be stripped from the key before comparing. 10 * `get_manifest_url()` - URL pointing to the manifest. 11 * `get_post_type()` - Post type to import as. 12 13 ## Manifest Format 14 15 The manifest should be a JSON object, with the keys set to the desired permalink (excluding the base path). Each item should also be a JSON object, containing the following keys: 16 17 * `slug` - Post name to insert. (Must match the final path-part of the key.) 18 * `markdown_source` - URL for the Markdown file to parse into content. 19 * `parent` - Key for the parent to store under. (Must correspond to the non-final path-parts of the key.) 20 * `title` - Title to use when creating post. Used temporarily, will be updated from the Markdown file. If not specified, defaults to `slug` (but will be updated from Markdown source). 21 22 **Note:** The Handbook index should have the slug `index`. 23 24 Example: 25 26 ```json 27 { 28 "foo": { 29 "title": "Temporary Foo Title", 30 "slug": "foo", 31 "markdown_source": "https://raw.githubusercontent.com/WordPress/doc-repo/master/foo.md", 32 "parent": null 33 }, 34 "foo/bar": { 35 "title": "Temporary Bar Title", 36 "slug": "bar", 37 "markdown_source": "https://raw.githubusercontent.com/WordPress/doc-repo/master/foo/bar.md", 38 "parent": "foo" 39 }, 40 "foo/bar/quux": { 41 "title": "Temporary Quux Title", 42 "slug": "quux", 43 "markdown_source": "https://raw.githubusercontent.com/WordPress/doc-repo/master/foo/bar/quux.md", 44 "parent": "foo/bar" 45 } 46 } 47 ``` -
wp-content/plugins/wporg-markdown/inc/class-importer.php
1 <?php 2 3 namespace WordPressdotorg\Markdown; 4 5 use WP_CLI; 6 use WP_Error; 7 use WP_Post; 8 use WP_Query; 9 use WPCom_GHF_Markdown_Parser; 10 11 abstract class Importer { 12 /** 13 * Meta key to store source in. 14 * 15 * @var string 16 */ 17 protected $meta_key = 'wporg_markdown_source'; 18 19 /** 20 * Meta key to store request ETag in. 21 * 22 * @var string 23 */ 24 protected $etag_meta_key = 'wporg_markdown_etag'; 25 26 /** 27 * Posts per page to query for. 28 * 29 * This needs to be set at least as high as the number of pages being 30 * imported, but should not be unbounded (-1). 31 * 32 * @var int 33 */ 34 protected $posts_per_page = 350; 35 36 /** 37 * Get base URL for all pages. 38 * 39 * This is used for generating the keys for the existing pages. 40 * 41 * @see static::get_existing_for_post() 42 * 43 * @return string Base URL to strip from page permalink. 44 */ 45 abstract protected function get_base(); 46 47 /** 48 * Get manifest URL. 49 * 50 * This URL should point to a JSON file containing the manifest for the 51 * site's content. (Typically raw.githubusercontent.com) 52 * 53 * @return string URL for the manifest file. 54 */ 55 abstract protected function get_manifest_url(); 56 57 /** 58 * Get post type for the type being imported. 59 * 60 * @return string Post type slug to import as. 61 */ 62 abstract protected function get_post_type(); 63 64 /** 65 * Get existing data for a given post. 66 * 67 * @param WP_Post $post Post to get existing data for. 68 * @return array 2-tuple of array key and data. 69 */ 70 protected function get_existing_for_post( WP_Post $post ) { 71 $key = rtrim( str_replace( $this->get_base(), '', get_permalink( $post->ID ) ), '/' ); 72 if ( empty( $key ) ) { 73 $key = 'index'; 74 } 75 76 $data = array( 77 'post_id' => $post->ID, 78 ); 79 return array( $key, $data ); 80 } 81 82 /** 83 * Import the manifest. 84 * 85 * Fetches the manifest, parses, and creates pages as needed. 86 */ 87 public function import_manifest() { 88 $response = wp_remote_get( $this->get_manifest_url() ); 89 if ( is_wp_error( $response ) ) { 90 if ( class_exists( 'WP_CLI' ) ) { 91 WP_CLI::error( $response->get_error_message() ); 92 } 93 return $response; 94 } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) { 95 if ( class_exists( 'WP_CLI' ) ) { 96 WP_CLI::error( 'Non-200 from Markdown source' ); 97 } 98 return new WP_Error( 'invalid-http-code', 'Markdown source returned non-200 http code.' ); 99 } 100 $manifest = json_decode( wp_remote_retrieve_body( $response ), true ); 101 if ( ! $manifest ) { 102 if ( class_exists( 'WP_CLI' ) ) { 103 WP_CLI::error( 'Invalid manifest' ); 104 } 105 return new WP_Error( 'invalid-manifest', 'Manifest did not unfurl properly.' );; 106 } 107 // Fetch all handbook posts for comparison 108 $q = new WP_Query( array( 109 'post_type' => $this->get_post_type(), 110 'post_status' => 'publish', 111 'posts_per_page' => $this->posts_per_page, 112 ) ); 113 $existing = array(); 114 foreach ( $q->posts as $post ) { 115 list( $key, $data ) = $this->get_existing_for_post( $post ); 116 $existing[ $key ] = $data; 117 } 118 $created = $updated = 0; 119 foreach ( $manifest as $key => $doc ) { 120 // Already exists, update. 121 if ( ! empty( $existing[ $key ] ) ) { 122 $existing_id = $existing[ $key ]['post_id']; 123 if ( $this->update_post_from_manifest_doc( $existing_id, $doc ) ) { 124 $updated++; 125 } 126 127 continue; 128 } 129 if ( $this->process_manifest_doc( $doc, $existing, $manifest ) ) { 130 $created++; 131 } 132 } 133 if ( class_exists( 'WP_CLI' ) ) { 134 WP_CLI::success( "Successfully created {$created} and updated {$updated} handbook pages." ); 135 } 136 } 137 138 /** 139 * Process a document from the manifest. 140 * 141 * @param array $doc Document to process. 142 * @param array $existing List of existing posts, will be added to. 143 * @param array $manifest Manifest data. 144 * @return boolean True if processing succeeded, false otherwise. 145 */ 146 protected function process_manifest_doc( $doc, &$existing, $manifest ) { 147 $post_parent = null; 148 if ( ! empty( $doc['parent'] ) ) { 149 // Find the parent in the existing set 150 if ( empty( $existing[ $doc['parent'] ] ) ) { 151 if ( ! $this->process_manifest_doc( $manifest[ $doc['parent'] ], $existing, $manifest ) ) { 152 return false; 153 } 154 } 155 if ( ! empty( $existing[ $doc['parent'] ] ) ) { 156 $parent = $existing[ $doc['parent'] ]; 157 $post_parent = $parent['post_id']; 158 } 159 } 160 $post = $this->create_post_from_manifest_doc( $doc, $post_parent ); 161 if ( $post ) { 162 list( $key, $data ) = $this->get_existing_for_post( $post ); 163 $existing[ $key ] = $data; 164 return true; 165 } 166 return false; 167 } 168 169 /** 170 * Create a new handbook page from the manifest document 171 */ 172 protected function create_post_from_manifest_doc( $doc, $post_parent = null ) { 173 if ( $doc['slug'] === 'index' ) { 174 $doc['slug'] = $this->get_post_type(); 175 } 176 $post_data = array( 177 'post_type' => $this->get_post_type(), 178 'post_status' => 'publish', 179 'post_parent' => $post_parent, 180 'post_title' => wp_slash( $doc['slug'] ), 181 'post_name' => sanitize_title_with_dashes( $doc['slug'] ), 182 ); 183 if ( isset( $doc['title'] ) ) { 184 $doc['post_title'] = sanitize_text_field( wp_slash( $doc['title'] ) ); 185 } 186 $post_id = wp_insert_post( $post_data ); 187 if ( ! $post_id ) { 188 return false; 189 } 190 if ( class_exists( 'WP_CLI' ) ) { 191 WP_CLI::log( "Created post {$post_id} for {$doc['slug']}." ); 192 } 193 update_post_meta( $post_id, $this->meta_key, esc_url_raw( $doc['markdown_source'] ) ); 194 return get_post( $post_id ); 195 } 196 197 /** 198 * Update an existing post from the manifest. 199 * 200 * @param int $post_id Existing post ID. 201 * @param array $doc Document details from the manifest. 202 * @return boolean True if updated, false otherwise. 203 */ 204 protected function update_post_from_manifest_doc( $post_id, $doc ) { 205 $did_update = update_post_meta( $post_id, $this->meta_key, esc_url_raw( $doc['markdown_source'] ) ); 206 return $did_update; 207 } 208 209 /** 210 * Update existing posts from Markdown source. 211 * 212 * Reparses the Markdown for every page. 213 */ 214 public function import_all_markdown() { 215 $q = new WP_Query( array( 216 'post_type' => $this->get_post_type(), 217 'post_status' => 'publish', 218 'fields' => 'ids', 219 'posts_per_page' => $this->posts_per_page, 220 ) ); 221 $ids = $q->posts; 222 $success = 0; 223 foreach( $ids as $id ) { 224 $ret = $this->update_post_from_markdown_source( $id ); 225 if ( class_exists( 'WP_CLI' ) ) { 226 if ( is_wp_error( $ret ) ) { 227 WP_CLI::warning( $ret->get_error_message() ); 228 } elseif ( false === $ret ) { 229 WP_CLI::log( "No updates for {$id}" ); 230 $success++; 231 } else { 232 WP_CLI::log( "Updated {$id} from markdown source" ); 233 $success++; 234 } 235 } 236 } 237 if ( class_exists( 'WP_CLI' ) ) { 238 $total = count( $ids ); 239 WP_CLI::success( "Successfully updated {$success} of {$total} pages." ); 240 } 241 } 242 243 /** 244 * Update a post from its Markdown source. 245 * 246 * @param int $post_id Post ID to update. 247 * @return boolean|WP_Error True if updated, false if no update needed, error otherwise. 248 */ 249 protected function update_post_from_markdown_source( $post_id ) { 250 $markdown_source = $this->get_markdown_source( $post_id ); 251 if ( is_wp_error( $markdown_source ) ) { 252 return $markdown_source; 253 } 254 if ( ! function_exists( 'jetpack_require_lib' ) ) { 255 return new WP_Error( 'missing-jetpack-require-lib', 'jetpack_require_lib() is missing on system.' ); 256 } 257 258 // Transform GitHub repo HTML pages into their raw equivalents 259 $markdown_source = preg_replace( '#https?://github\.com/([^/]+/[^/]+)/blob/(.+)#', 'https://raw.githubusercontent.com/$1/$2', $markdown_source ); 260 $markdown_source = add_query_arg( 'v', time(), $markdown_source ); 261 262 // Grab the stored ETag, and use it to deduplicate. 263 $args = array( 264 'headers' => array(), 265 ); 266 $last_etag = get_post_meta( $post_id, $this->etag_meta_key, true ); 267 if ( ! empty( $last_etag ) ) { 268 $args['headers']['If-None-Match'] = $last_etag; 269 } 270 271 $response = wp_remote_get( $markdown_source, $args ); 272 if ( is_wp_error( $response ) ) { 273 return $response; 274 } elseif ( 304 === wp_remote_retrieve_response_code( $response ) ) { 275 // No update required! 276 return false; 277 } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) { 278 return new WP_Error( 'invalid-http-code', 'Markdown source returned non-200 http code.' ); 279 } 280 281 $etag = wp_remote_retrieve_header( $response, 'etag' ); 282 283 $markdown = wp_remote_retrieve_body( $response ); 284 // Strip YAML doc from the header 285 $markdown = preg_replace( '#^---(.+)---#Us', '', $markdown ); 286 287 $title = null; 288 if ( preg_match( '/^#\s(.+)/', $markdown, $matches ) ) { 289 $title = $matches[1]; 290 $markdown = preg_replace( '/^#\swp\s(.+)/', '', $markdown ); 291 } 292 $markdown = trim( $markdown ); 293 294 // Steal the first sentence as the excerpt 295 $excerpt = ''; 296 if ( preg_match( '/^(.+)/', $markdown, $matches ) ) { 297 $excerpt = $matches[1]; 298 $markdown = preg_replace( '/^(.+)/', '', $markdown ); 299 } 300 301 // Transform to HTML and save the post 302 jetpack_require_lib( 'markdown' ); 303 $parser = new WPCom_GHF_Markdown_Parser(); 304 $html = $parser->transform( $markdown ); 305 $post_data = array( 306 'ID' => $post_id, 307 'post_content' => wp_filter_post_kses( wp_slash( $html ) ), 308 'post_excerpt' => sanitize_text_field( wp_slash( $excerpt ) ), 309 ); 310 if ( ! is_null( $title ) ) { 311 $post_data['post_title'] = sanitize_text_field( wp_slash( $title ) ); 312 } 313 wp_update_post( $post_data ); 314 315 // Set ETag for future updates. 316 update_post_meta( $post_id, $this->etag_meta_key, wp_slash( $etag ) ); 317 318 return true; 319 } 320 321 /** 322 * Retrieve the markdown source URL for a given post. 323 */ 324 public function get_markdown_source( $post_id ) { 325 $markdown_source = get_post_meta( $post_id, $this->meta_key, true ); 326 if ( ! $markdown_source ) { 327 return new WP_Error( 'missing-markdown-source', 'Markdown source is missing for post.' ); 328 } 329 330 return $markdown_source; 331 } 332 } -
wp-content/plugins/wporg-markdown/plugin.php
1 <?php 2 /** 3 * Plugin Name: WPORG Markdown Importer 4 * Description: Automatic Markdown imports for handbooks and DevHub (CLI/API handbooks) 5 * Author: Daniel Bachhuber and Ryan McCue 6 */ 7 8 require __DIR__ . '/inc/class-importer.php'; -
wp-content/themes/pub/wporg-developer/functions.php
61 61 require __DIR__ . '/inc/cli.php'; 62 62 63 63 /** 64 * REST API handbook. 65 */ 66 require __DIR__ . '/inc/rest-api.php'; 67 68 /** 64 69 * Explanations for functions. hooks, classes, and methods. 65 70 */ 66 71 require( __DIR__ . '/inc/explanations.php' ); -
wp-content/themes/pub/wporg-developer/inc/cli.php
1 1 <?php 2 2 3 class DevHub_CLI { 3 use WordPressdotorg\Markdown\Importer; 4 4 5 private static $commands_manifest = 'https://raw.githubusercontent.com/wp-cli/handbook/master/bin/commands-manifest.json'; 6 private static $meta_key = 'wporg_cli_markdown_source'; 7 private static $supported_post_types = array( 'command' ); 8 private static $posts_per_page = 350; 5 class DevHub_CLI extends Importer { 6 /** 7 * Singleton instance. 8 * 9 * @var static 10 */ 11 protected static $instance; 9 12 10 public static function init() { 11 add_action( 'init', array( __CLASS__, 'action_init_register_cron_jobs' ) ); 12 add_action( 'init', array( __CLASS__, 'action_init_register_post_types' ) ); 13 add_action( 'pre_get_posts', array( __CLASS__, 'action_pre_get_posts' ) ); 14 add_action( 'devhub_cli_manifest_import', array( __CLASS__, 'action_devhub_cli_manifest_import' ) ); 15 add_action( 'devhub_cli_markdown_import', array( __CLASS__, 'action_devhub_cli_markdown_import' ) ); 13 /** 14 * Meta key to store source in. 15 * 16 * Overridden for compatibility. 17 * 18 * @var string 19 */ 20 protected $meta_key = 'wporg_cli_markdown_source'; 21 22 /** 23 * Get the singleton instance, or create if needed. 24 * 25 * @return static 26 */ 27 public static function instance() { 28 if ( empty( static::$instance ) ) { 29 static::$instance = new static(); 30 } 31 32 return static::$instance; 16 33 } 17 34 35 public function init() { 36 add_action( 'init', array( $this, 'action_init_register_cron_jobs' ) ); 37 add_action( 'init', array( $this, 'action_init_register_post_types' ) ); 38 add_action( 'pre_get_posts', array( $this, 'action_pre_get_posts' ) ); 39 add_action( 'devhub_cli_manifest_import', array( $this, 'import_manifest' ) ); 40 add_action( 'devhub_cli_markdown_import', array( $this, 'import_all_markdown' ) ); 41 } 42 43 protected function get_base() { 44 return home_url( 'cli/commands/' ); 45 } 46 47 protected function get_manifest_url() { 48 return 'https://raw.githubusercontent.com/wp-cli/handbook/master/bin/commands-manifest.json'; 49 } 50 51 protected function get_post_type() { 52 return 'command'; 53 } 54 18 55 public static function action_init_register_cron_jobs() { 19 56 if ( ! wp_next_scheduled( 'devhub_cli_manifest_import' ) ) { 20 57 wp_schedule_event( time(), 'twicedaily', 'devhub_cli_manifest_import' ); … … 70 107 $query->set( 'posts_per_page', 250 ); 71 108 } 72 109 } 73 74 public static function action_devhub_cli_manifest_import() {75 $response = wp_remote_get( self::$commands_manifest );76 if ( is_wp_error( $response ) ) {77 return $response;78 } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) {79 return new WP_Error( 'invalid-http-code', 'Markdown source returned non-200 http code.' );80 }81 $manifest = json_decode( wp_remote_retrieve_body( $response ), true );82 if ( ! $manifest ) {83 return new WP_Error( 'invalid-manifest', 'Manifest did not unfurl properly.' );;84 }85 // Fetch all handbook posts for comparison86 $q = new WP_Query( array(87 'post_type' => self::$supported_post_types,88 'post_status' => 'publish',89 'posts_per_page' => self::$posts_per_page,90 ) );91 $existing = array();92 foreach( $q->posts as $post ) {93 $cmd_path = rtrim( str_replace( home_url( 'cli/commands/' ), '', get_permalink( $post->ID ) ), '/' );94 $existing[ $cmd_path ] = array(95 'post_id' => $post->ID,96 'cmd_path' => $cmd_path,97 );98 }99 $created = 0;100 foreach( $manifest as $doc ) {101 // Already exists102 if ( wp_filter_object_list( $existing, array( 'cmd_path' => $doc['cmd_path'] ) ) ) {103 continue;104 }105 if ( self::process_manifest_doc( $doc, $existing, $manifest ) ) {106 $created++;107 }108 }109 if ( class_exists( 'WP_CLI' ) ) {110 \WP_CLI::success( "Successfully created {$created} handbook pages." );111 }112 }113 114 private static function process_manifest_doc( $doc, &$existing, $manifest ) {115 $post_parent = null;116 if ( ! empty( $doc['parent'] ) ) {117 // Find the parent in the existing set118 $parents = wp_filter_object_list( $existing, array( 'cmd_path' => $doc['parent'] ) );119 if ( empty( $parents ) ) {120 if ( ! self::process_manifest_doc( $manifest[ $doc['parent'] ], $existing, $manifest ) ) {121 return;122 }123 $parents = wp_filter_object_list( $existing, array( 'cmd_path' => $doc['parent'] ) );124 }125 if ( ! empty( $parents ) ) {126 $parent = array_shift( $parents );127 $post_parent = $parent['post_id'];128 }129 }130 $post = self::create_post_from_manifest_doc( $doc, $post_parent );131 if ( $post ) {132 $cmd_path = rtrim( str_replace( home_url( 'cli/commands/' ), '', get_permalink( $post->ID ) ), '/' );133 $existing[ $cmd_path ] = array(134 'post_id' => $post->ID,135 'cmd_path' => $cmd_path,136 );137 return true;138 }139 return false;140 }141 142 public static function action_devhub_cli_markdown_import() {143 $q = new WP_Query( array(144 'post_type' => self::$supported_post_types,145 'post_status' => 'publish',146 'fields' => 'ids',147 'posts_per_page' => self::$posts_per_page,148 ) );149 $ids = $q->posts;150 $success = 0;151 foreach( $ids as $id ) {152 $ret = self::update_post_from_markdown_source( $id );153 if ( class_exists( 'WP_CLI' ) ) {154 if ( is_wp_error( $ret ) ) {155 \WP_CLI::warning( $ret->get_error_message() );156 } else {157 \WP_CLI::log( "Updated {$id} from markdown source" );158 $success++;159 }160 }161 }162 if ( class_exists( 'WP_CLI' ) ) {163 $total = count( $ids );164 \WP_CLI::success( "Successfully updated {$success} of {$total} CLI command pages." );165 }166 }167 168 /**169 * Create a new handbook page from the manifest document170 */171 private static function create_post_from_manifest_doc( $doc, $post_parent = null ) {172 $post_data = array(173 'post_type' => 'command',174 'post_status' => 'publish',175 'post_parent' => $post_parent,176 'post_title' => sanitize_text_field( wp_slash( $doc['title'] ) ),177 'post_name' => sanitize_title_with_dashes( $doc['slug'] ),178 );179 $post_id = wp_insert_post( $post_data );180 if ( ! $post_id ) {181 return false;182 }183 if ( class_exists( 'WP_CLI' ) ) {184 \WP_CLI::log( "Created post {$post_id} for {$doc['title']}." );185 }186 update_post_meta( $post_id, self::$meta_key, esc_url_raw( $doc['markdown_source'] ) );187 return get_post( $post_id );188 }189 190 /**191 * Update a post from its Markdown source192 */193 private static function update_post_from_markdown_source( $post_id ) {194 $markdown_source = self::get_markdown_source( $post_id );195 if ( is_wp_error( $markdown_source ) ) {196 return $markdown_source;197 }198 if ( ! function_exists( 'jetpack_require_lib' ) ) {199 return new WP_Error( 'missing-jetpack-require-lib', 'jetpack_require_lib() is missing on system.' );200 }201 202 // Transform GitHub repo HTML pages into their raw equivalents203 $markdown_source = preg_replace( '#https?://github\.com/([^/]+/[^/]+)/blob/(.+)#', 'https://raw.githubusercontent.com/$1/$2', $markdown_source );204 $markdown_source = add_query_arg( 'v', time(), $markdown_source );205 $response = wp_remote_get( $markdown_source );206 if ( is_wp_error( $response ) ) {207 return $response;208 } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) {209 return new WP_Error( 'invalid-http-code', 'Markdown source returned non-200 http code.' );210 }211 212 $markdown = wp_remote_retrieve_body( $response );213 // Strip YAML doc from the header214 $markdown = preg_replace( '#^---(.+)---#Us', '', $markdown );215 216 $title = null;217 if ( preg_match( '/^#\s(.+)/', $markdown, $matches ) ) {218 $title = $matches[1];219 $markdown = preg_replace( '/^#\swp\s(.+)/', '', $markdown );220 }221 $markdown = trim( $markdown );222 223 // Steal the first sentence as the excerpt224 $excerpt = '';225 if ( preg_match( '/^(.+)/', $markdown, $matches ) ) {226 $excerpt = $matches[1];227 $markdown = preg_replace( '/^(.+)/', '', $markdown );228 }229 230 // Transform to HTML and save the post231 jetpack_require_lib( 'markdown' );232 $parser = new \WPCom_GHF_Markdown_Parser;233 $html = $parser->transform( $markdown );234 $post_data = array(235 'ID' => $post_id,236 'post_content' => wp_filter_post_kses( wp_slash( $html ) ),237 'post_excerpt' => sanitize_text_field( wp_slash( $excerpt ) ),238 );239 if ( ! is_null( $title ) ) {240 $post_data['post_title'] = sanitize_text_field( wp_slash( $title ) );241 }242 wp_update_post( $post_data );243 return true;244 }245 246 /**247 * Retrieve the markdown source URL for a given post.248 */249 public static function get_markdown_source( $post_id ) {250 $markdown_source = get_post_meta( $post_id, self::$meta_key, true );251 if ( ! $markdown_source ) {252 return new WP_Error( 'missing-markdown-source', 'Markdown source is missing for post.' );253 }254 255 return $markdown_source;256 }257 258 110 } 259 111 260 DevHub_CLI::init(); 261 112 DevHub_CLI::instance()->init(); -
wp-content/themes/pub/wporg-developer/inc/rest-api.php
1 <?php 2 3 use WordPressdotorg\Markdown\Importer; 4 5 class DevHub_REST_API extends Importer { 6 /** 7 * Singleton instance. 8 * 9 * @var static 10 */ 11 protected static $instance; 12 13 /** 14 * Get the singleton instance, or create if needed. 15 * 16 * @return static 17 */ 18 public static function instance() { 19 if ( empty( static::$instance ) ) { 20 static::$instance = new static(); 21 } 22 23 return static::$instance; 24 } 25 26 protected function get_base() { 27 return home_url( 'rest-api/' ); 28 } 29 30 protected function get_manifest_url() { 31 return 'https://raw.githubusercontent.com/WP-API/docs/master/bin/manifest.json'; 32 } 33 34 protected function get_post_type() { 35 return 'rest-api-handbook'; 36 } 37 38 public function init() { 39 add_action( 'init', array( $this, 'register_cron_jobs' ) ); 40 add_action( 'restapi_import_manifest', array( $this, 'import_manifest' ) ); 41 add_action( 'restapi_import_all_markdown', array( $this, 'import_all_markdown' ) ); 42 } 43 44 public function register_cron_jobs() { 45 if ( ! wp_next_scheduled( 'restapi_import_manifest' ) ) { 46 wp_schedule_event( time(), '15_minutes', 'restapi_import_manifest' ); 47 } 48 if ( ! wp_next_scheduled( 'restapi_import_all_markdown' ) ) { 49 wp_schedule_event( time(), '15_minutes', 'restapi_import_all_markdown' ); 50 } 51 } 52 } 53 54 DevHub_REST_API::instance()->init(); 55