From 961833c1bda4fb319760a72835f3754a73b9c7ac Mon Sep 17 00:00:00 2001 From: Ronald Huereca Date: Wed, 29 Sep 2021 10:04:53 -0500 Subject: [PATCH 1/7] Removing theme post types if theme is installed. --- .gitignore | 3 ++- class-phpdoc-plugin.php | 3 +++ php/Plugin.php | 13 +++++++++++++ php/RegisterPostTypes.php | 15 +++++++++++++++ php/RegisterTaxonomies.php | 0 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 php/RegisterPostTypes.php create mode 100644 php/RegisterTaxonomies.php diff --git a/.gitignore b/.gitignore index d98e886..4da4d64 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,5 @@ phpunit.xml phpcs-report-*.txt # Allowed vendor files -!vendor/freemius \ No newline at end of file +!vendor/freemius +.vscode/launch.json diff --git a/class-phpdoc-plugin.php b/class-phpdoc-plugin.php index fa4e8af..36dc641 100644 --- a/class-phpdoc-plugin.php +++ b/class-phpdoc-plugin.php @@ -32,6 +32,9 @@ class Bootstrap { public function plugins_loaded() { $plugin = new Plugin(); + // Run any actions for theme init. + add_action( 'after_setup_theme', array( $plugin, 'after_setup_theme' ) ); + // Init the plugin. add_action( 'init', array( $plugin, 'init' ) ); } diff --git a/php/Plugin.php b/php/Plugin.php index 7858f53..06eb0ee 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -43,6 +43,19 @@ public function init() { // todo - init actions here. } + /** + * After a theme's functions.php file has been run. + * + * @see WP after_setup_theme action. + */ + public function after_setup_theme() { + // Remove post types registered by theme. + global $explanations; + remove_action( 'init', array( 'DevHub_CLI', 'action_init_register_post_types' ) ); + remove_action( 'init', array( 'DevHub_Registrations', 'do_init' ), 10 ); + remove_action( 'init', array( $explanations, 'register_post_type' ), 0 ); + } + /** * Is WP debug mode enabled. * diff --git a/php/RegisterPostTypes.php b/php/RegisterPostTypes.php new file mode 100644 index 0000000..56fd8f8 --- /dev/null +++ b/php/RegisterPostTypes.php @@ -0,0 +1,15 @@ + Date: Thu, 30 Sep 2021 09:08:22 -0500 Subject: [PATCH 2/7] Add post types to plugin. --- php/Plugin.php | 3 +- php/PostTypes.php | 168 ++++++++++++++++++++++++++++++++++++++ php/RegisterPostTypes.php | 15 ---- 3 files changed, 170 insertions(+), 16 deletions(-) create mode 100644 php/PostTypes.php delete mode 100644 php/RegisterPostTypes.php diff --git a/php/Plugin.php b/php/Plugin.php index 06eb0ee..b5c5b69 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -40,7 +40,8 @@ public function __construct() { * @see WP init action. */ public function init() { - // todo - init actions here. + // Create post types. + PostTypes::create(); } /** diff --git a/php/PostTypes.php b/php/PostTypes.php new file mode 100644 index 0000000..b52aaa9 --- /dev/null +++ b/php/PostTypes.php @@ -0,0 +1,168 @@ + 'reference/functions', + 'label' => __( 'Functions', 'wporg' ), + 'labels' => array( + 'name' => __( 'Functions', 'wporg' ), + 'singular_name' => __( 'Function', 'wporg' ), + 'all_items' => __( 'Functions', 'wporg' ), + 'new_item' => __( 'New Function', 'wporg' ), + 'add_new' => __( 'Add New', 'wporg' ), + 'add_new_item' => __( 'Add New Function', 'wporg' ), + 'edit_item' => __( 'Edit Function', 'wporg' ), + 'view_item' => __( 'View Function', 'wporg' ), + 'search_items' => __( 'Search Functions', 'wporg' ), + 'not_found' => __( 'No Functions found', 'wporg' ), + 'not_found_in_trash' => __( 'No Functions found in trash', 'wporg' ), + 'parent_item_colon' => __( 'Parent Function', 'wporg' ), + 'menu_name' => __( 'Functions', 'wporg' ), + ), + 'menu_icon' => 'dashicons-editor-code', + 'public' => true, + 'rewrite' => array( + 'feeds' => false, + 'slug' => 'reference/functions', + 'with_front' => false, + ), + 'supports' => $supports, + 'show_in_rest' => true, + ) + ); + } + + add_rewrite_rule( 'reference/classes/page/([0-9]{1,})/?$', 'index.php?post_type=wp-parser-class&paged=$matches[1]', 'top' ); + add_rewrite_rule( 'reference/classes/([^/]+)/([^/]+)/?$', 'index.php?post_type=wp-parser-method&name=$matches[1]-$matches[2]', 'top' ); + + if ( ! post_type_exists( 'wp-parser-class' ) ) { + register_post_type( + 'wp-parser-class', + array( + 'has_archive' => 'reference/classes', + 'label' => __( 'Classes', 'wporg' ), + 'labels' => array( + 'name' => __( 'Classes', 'wporg' ), + 'singular_name' => __( 'Class', 'wporg' ), + 'all_items' => __( 'Classes', 'wporg' ), + 'new_item' => __( 'New Class', 'wporg' ), + 'add_new' => __( 'Add New', 'wporg' ), + 'add_new_item' => __( 'Add New Class', 'wporg' ), + 'edit_item' => __( 'Edit Class', 'wporg' ), + 'view_item' => __( 'View Class', 'wporg' ), + 'search_items' => __( 'Search Classes', 'wporg' ), + 'not_found' => __( 'No Classes found', 'wporg' ), + 'not_found_in_trash' => __( 'No Classes found in trash', 'wporg' ), + 'parent_item_colon' => __( 'Parent Class', 'wporg' ), + 'menu_name' => __( 'Classes', 'wporg' ), + ), + 'menu_icon' => 'dashicons-editor-code', + 'public' => true, + 'rewrite' => array( + 'feeds' => false, + 'slug' => 'reference/classes', + 'with_front' => false, + ), + 'supports' => $supports, + 'show_in_rest' => true, + ) + ); + } + + if ( ! post_type_exists( 'wp-parser-hook' ) ) { + register_post_type( + 'wp-parser-hook', + array( + 'has_archive' => 'reference/hooks', + 'label' => __( 'Hooks', 'wporg' ), + 'labels' => array( + 'name' => __( 'Hooks', 'wporg' ), + 'singular_name' => __( 'Hook', 'wporg' ), + 'all_items' => __( 'Hooks', 'wporg' ), + 'new_item' => __( 'New Hook', 'wporg' ), + 'add_new' => __( 'Add New', 'wporg' ), + 'add_new_item' => __( 'Add New Hook', 'wporg' ), + 'edit_item' => __( 'Edit Hook', 'wporg' ), + 'view_item' => __( 'View Hook', 'wporg' ), + 'search_items' => __( 'Search Hooks', 'wporg' ), + 'not_found' => __( 'No Hooks found', 'wporg' ), + 'not_found_in_trash' => __( 'No Hooks found in trash', 'wporg' ), + 'parent_item_colon' => __( 'Parent Hook', 'wporg' ), + 'menu_name' => __( 'Hooks', 'wporg' ), + ), + 'menu_icon' => 'dashicons-editor-code', + 'public' => true, + 'rewrite' => array( + 'feeds' => false, + 'slug' => 'reference/hooks', + 'with_front' => false, + ), + 'supports' => $supports, + 'show_in_rest' => true, + ) + ); + } + + if ( ! post_type_exists( 'wp-parser-method' ) ) { + register_post_type( + 'wp-parser-method', + array( + 'has_archive' => 'reference/methods', + 'label' => __( 'Methods', 'wporg' ), + 'labels' => array( + 'name' => __( 'Methods', 'wporg' ), + 'singular_name' => __( 'Method', 'wporg' ), + 'all_items' => __( 'Methods', 'wporg' ), + 'new_item' => __( 'New Method', 'wporg' ), + 'add_new' => __( 'Add New', 'wporg' ), + 'add_new_item' => __( 'Add New Method', 'wporg' ), + 'edit_item' => __( 'Edit Method', 'wporg' ), + 'view_item' => __( 'View Method', 'wporg' ), + 'search_items' => __( 'Search Methods', 'wporg' ), + 'not_found' => __( 'No Methods found', 'wporg' ), + 'not_found_in_trash' => __( 'No Methods found in trash', 'wporg' ), + 'parent_item_colon' => __( 'Parent Method', 'wporg' ), + 'menu_name' => __( 'Methods', 'wporg' ), + ), + 'menu_icon' => 'dashicons-editor-code', + 'public' => true, + 'rewrite' => array( + 'feeds' => false, + 'slug' => 'classes', + 'with_front' => false, + ), + 'supports' => $supports, + 'show_in_rest' => true, + ) + ); + } + + } +} diff --git a/php/RegisterPostTypes.php b/php/RegisterPostTypes.php deleted file mode 100644 index 56fd8f8..0000000 --- a/php/RegisterPostTypes.php +++ /dev/null @@ -1,15 +0,0 @@ - Date: Thu, 30 Sep 2021 09:15:35 -0500 Subject: [PATCH 3/7] Adding parsed post types. --- php/PostTypes.php | 131 ++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/php/PostTypes.php b/php/PostTypes.php index b52aaa9..63bf21e 100644 --- a/php/PostTypes.php +++ b/php/PostTypes.php @@ -30,21 +30,21 @@ public static function create() { 'wp-parser-function', array( 'has_archive' => 'reference/functions', - 'label' => __( 'Functions', 'wporg' ), + 'label' => __( 'Functions', 'phpdoc-plugin' ), 'labels' => array( - 'name' => __( 'Functions', 'wporg' ), - 'singular_name' => __( 'Function', 'wporg' ), - 'all_items' => __( 'Functions', 'wporg' ), - 'new_item' => __( 'New Function', 'wporg' ), - 'add_new' => __( 'Add New', 'wporg' ), - 'add_new_item' => __( 'Add New Function', 'wporg' ), - 'edit_item' => __( 'Edit Function', 'wporg' ), - 'view_item' => __( 'View Function', 'wporg' ), - 'search_items' => __( 'Search Functions', 'wporg' ), - 'not_found' => __( 'No Functions found', 'wporg' ), - 'not_found_in_trash' => __( 'No Functions found in trash', 'wporg' ), - 'parent_item_colon' => __( 'Parent Function', 'wporg' ), - 'menu_name' => __( 'Functions', 'wporg' ), + 'name' => __( 'Functions', 'phpdoc-plugin' ), + 'singular_name' => __( 'Function', 'phpdoc-plugin' ), + 'all_items' => __( 'Functions', 'phpdoc-plugin' ), + 'new_item' => __( 'New Function', 'phpdoc-plugin' ), + 'add_new' => __( 'Add New', 'phpdoc-plugin' ), + 'add_new_item' => __( 'Add New Function', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit Function', 'phpdoc-plugin' ), + 'view_item' => __( 'View Function', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Functions', 'phpdoc-plugin' ), + 'not_found' => __( 'No Functions found', 'phpdoc-plugin' ), + 'not_found_in_trash' => __( 'No Functions found in trash', 'phpdoc-plugin' ), + 'parent_item_colon' => __( 'Parent Function', 'phpdoc-plugin' ), + 'menu_name' => __( 'Functions', 'phpdoc-plugin' ), ), 'menu_icon' => 'dashicons-editor-code', 'public' => true, @@ -67,21 +67,21 @@ public static function create() { 'wp-parser-class', array( 'has_archive' => 'reference/classes', - 'label' => __( 'Classes', 'wporg' ), + 'label' => __( 'Classes', 'phpdoc-plugin' ), 'labels' => array( - 'name' => __( 'Classes', 'wporg' ), - 'singular_name' => __( 'Class', 'wporg' ), - 'all_items' => __( 'Classes', 'wporg' ), - 'new_item' => __( 'New Class', 'wporg' ), - 'add_new' => __( 'Add New', 'wporg' ), - 'add_new_item' => __( 'Add New Class', 'wporg' ), - 'edit_item' => __( 'Edit Class', 'wporg' ), - 'view_item' => __( 'View Class', 'wporg' ), - 'search_items' => __( 'Search Classes', 'wporg' ), - 'not_found' => __( 'No Classes found', 'wporg' ), - 'not_found_in_trash' => __( 'No Classes found in trash', 'wporg' ), - 'parent_item_colon' => __( 'Parent Class', 'wporg' ), - 'menu_name' => __( 'Classes', 'wporg' ), + 'name' => __( 'Classes', 'phpdoc-plugin' ), + 'singular_name' => __( 'Class', 'phpdoc-plugin' ), + 'all_items' => __( 'Classes', 'phpdoc-plugin' ), + 'new_item' => __( 'New Class', 'phpdoc-plugin' ), + 'add_new' => __( 'Add New', 'phpdoc-plugin' ), + 'add_new_item' => __( 'Add New Class', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit Class', 'phpdoc-plugin' ), + 'view_item' => __( 'View Class', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Classes', 'phpdoc-plugin' ), + 'not_found' => __( 'No Classes found', 'phpdoc-plugin' ), + 'not_found_in_trash' => __( 'No Classes found in trash', 'phpdoc-plugin' ), + 'parent_item_colon' => __( 'Parent Class', 'phpdoc-plugin' ), + 'menu_name' => __( 'Classes', 'phpdoc-plugin' ), ), 'menu_icon' => 'dashicons-editor-code', 'public' => true, @@ -101,21 +101,21 @@ public static function create() { 'wp-parser-hook', array( 'has_archive' => 'reference/hooks', - 'label' => __( 'Hooks', 'wporg' ), + 'label' => __( 'Hooks', 'phpdoc-plugin' ), 'labels' => array( - 'name' => __( 'Hooks', 'wporg' ), - 'singular_name' => __( 'Hook', 'wporg' ), - 'all_items' => __( 'Hooks', 'wporg' ), - 'new_item' => __( 'New Hook', 'wporg' ), - 'add_new' => __( 'Add New', 'wporg' ), - 'add_new_item' => __( 'Add New Hook', 'wporg' ), - 'edit_item' => __( 'Edit Hook', 'wporg' ), - 'view_item' => __( 'View Hook', 'wporg' ), - 'search_items' => __( 'Search Hooks', 'wporg' ), - 'not_found' => __( 'No Hooks found', 'wporg' ), - 'not_found_in_trash' => __( 'No Hooks found in trash', 'wporg' ), - 'parent_item_colon' => __( 'Parent Hook', 'wporg' ), - 'menu_name' => __( 'Hooks', 'wporg' ), + 'name' => __( 'Hooks', 'phpdoc-plugin' ), + 'singular_name' => __( 'Hook', 'phpdoc-plugin' ), + 'all_items' => __( 'Hooks', 'phpdoc-plugin' ), + 'new_item' => __( 'New Hook', 'phpdoc-plugin' ), + 'add_new' => __( 'Add New', 'phpdoc-plugin' ), + 'add_new_item' => __( 'Add New Hook', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit Hook', 'phpdoc-plugin' ), + 'view_item' => __( 'View Hook', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Hooks', 'phpdoc-plugin' ), + 'not_found' => __( 'No Hooks found', 'phpdoc-plugin' ), + 'not_found_in_trash' => __( 'No Hooks found in trash', 'phpdoc-plugin' ), + 'parent_item_colon' => __( 'Parent Hook', 'phpdoc-plugin' ), + 'menu_name' => __( 'Hooks', 'phpdoc-plugin' ), ), 'menu_icon' => 'dashicons-editor-code', 'public' => true, @@ -135,21 +135,21 @@ public static function create() { 'wp-parser-method', array( 'has_archive' => 'reference/methods', - 'label' => __( 'Methods', 'wporg' ), + 'label' => __( 'Methods', 'phpdoc-plugin' ), 'labels' => array( - 'name' => __( 'Methods', 'wporg' ), - 'singular_name' => __( 'Method', 'wporg' ), - 'all_items' => __( 'Methods', 'wporg' ), - 'new_item' => __( 'New Method', 'wporg' ), - 'add_new' => __( 'Add New', 'wporg' ), - 'add_new_item' => __( 'Add New Method', 'wporg' ), - 'edit_item' => __( 'Edit Method', 'wporg' ), - 'view_item' => __( 'View Method', 'wporg' ), - 'search_items' => __( 'Search Methods', 'wporg' ), - 'not_found' => __( 'No Methods found', 'wporg' ), - 'not_found_in_trash' => __( 'No Methods found in trash', 'wporg' ), - 'parent_item_colon' => __( 'Parent Method', 'wporg' ), - 'menu_name' => __( 'Methods', 'wporg' ), + 'name' => __( 'Methods', 'phpdoc-plugin' ), + 'singular_name' => __( 'Method', 'phpdoc-plugin' ), + 'all_items' => __( 'Methods', 'phpdoc-plugin' ), + 'new_item' => __( 'New Method', 'phpdoc-plugin' ), + 'add_new' => __( 'Add New', 'phpdoc-plugin' ), + 'add_new_item' => __( 'Add New Method', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit Method', 'phpdoc-plugin' ), + 'view_item' => __( 'View Method', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Methods', 'phpdoc-plugin' ), + 'not_found' => __( 'No Methods found', 'phpdoc-plugin' ), + 'not_found_in_trash' => __( 'No Methods found in trash', 'phpdoc-plugin' ), + 'parent_item_colon' => __( 'Parent Method', 'phpdoc-plugin' ), + 'menu_name' => __( 'Methods', 'phpdoc-plugin' ), ), 'menu_icon' => 'dashicons-editor-code', 'public' => true, @@ -163,6 +163,25 @@ public static function create() { ) ); } + } + + /** + * Return registered post types for plugin. + * + * @param bool $labels Whether to return just post type keys or also labels. + */ + public static function get_parsed_post_types( bool $labels = true ) { + $post_types = array( + 'wp-parser-class' => __( 'Classes', 'phpdoc-plugin' ), + 'wp-parser-function' => __( 'Functions', 'phpdoc-plugin' ), + 'wp-parser-hook' => __( 'Hooks', 'phpdoc-plugin' ), + 'wp-parser-method' => __( 'Methods', 'phpdoc-plugin' ), + ); + + if ( ! $labels ) { + return array_keys( $post_types ); + } + return $post_types; } } From cac782a5911aab40c939e9759553b4b4d5e74e41 Mon Sep 17 00:00:00 2001 From: Ronald Huereca Date: Thu, 30 Sep 2021 09:21:21 -0500 Subject: [PATCH 4/7] Add taxonomies. --- php/Plugin.php | 3 ++ php/RegisterTaxonomies.php | 0 php/Taxonomies.php | 91 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) delete mode 100644 php/RegisterTaxonomies.php create mode 100644 php/Taxonomies.php diff --git a/php/Plugin.php b/php/Plugin.php index b5c5b69..d4f051c 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -42,6 +42,9 @@ public function __construct() { public function init() { // Create post types. PostTypes::create(); + + // Add taxonomies. + Taxonomies::create(); } /** diff --git a/php/RegisterTaxonomies.php b/php/RegisterTaxonomies.php deleted file mode 100644 index e69de29..0000000 diff --git a/php/Taxonomies.php b/php/Taxonomies.php new file mode 100644 index 0000000..e1c1672 --- /dev/null +++ b/php/Taxonomies.php @@ -0,0 +1,91 @@ + __( 'Files', 'phpdoc-plugin' ), + 'labels' => array( + 'name' => __( 'Files', 'phpdoc-plugin' ), + 'singular_name' => _x( 'File', 'taxonomy general name', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Files', 'phpdoc-plugin' ), + 'popular_items' => null, + 'all_items' => __( 'All Files', 'phpdoc-plugin' ), + 'parent_item' => __( 'Parent File', 'phpdoc-plugin' ), + 'parent_item_colon' => __( 'Parent File:', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit File', 'phpdoc-plugin' ), + 'update_item' => __( 'Update File', 'phpdoc-plugin' ), + 'add_new_item' => __( 'New File', 'phpdoc-plugin' ), + 'new_item_name' => __( 'New File', 'phpdoc-plugin' ), + 'separate_items_with_commas' => __( 'Files separated by comma', 'phpdoc-plugin' ), + 'add_or_remove_items' => __( 'Add or remove Files', 'phpdoc-plugin' ), + 'choose_from_most_used' => __( 'Choose from the most used Files', 'phpdoc-plugin' ), + 'menu_name' => __( 'Files', 'phpdoc-plugin' ), + ), + 'public' => true, + // Hierarchical x 2 to enable (.+) rather than ([^/]+) for rewrites. + 'hierarchical' => true, + 'rewrite' => array( + 'with_front' => false, + 'slug' => 'reference/files', + 'hierarchical' => true, + ), + 'sort' => false, + 'update_count_callback' => '_update_post_term_count', + 'show_in_rest' => true, + ) + ); + + register_taxonomy( + 'wp-parser-package', + PostTypes::get_parsed_post_types( false ), + array( + 'hierarchical' => true, + 'label' => '@package', + 'public' => true, + 'rewrite' => array( + 'with_front' => false, + 'slug' => 'reference/package', + ), + 'sort' => false, + 'update_count_callback' => '_update_post_term_count', + 'show_in_rest' => true, + ) + ); + + // @since + register_taxonomy( + 'wp-parser-since', + PostTypes::get_parsed_post_types( false ), + array( + 'hierarchical' => true, + 'label' => __( '@since', 'phpdoc-plugin' ), + 'public' => true, + 'rewrite' => array( + 'with_front' => false, + 'slug' => 'reference/since', + ), + 'sort' => false, + 'update_count_callback' => '_update_post_term_count', + 'show_in_rest' => true, + ) + ); + + } +} From 14971bd6fd68604f4f63e27d1509428b86f4ad57 Mon Sep 17 00:00:00 2001 From: Ronald Huereca Date: Thu, 30 Sep 2021 09:30:42 -0500 Subject: [PATCH 5/7] Adding P2P initialization. --- php/Plugin.php | 3 + php/PostsToPosts.php | 168 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 php/PostsToPosts.php diff --git a/php/Plugin.php b/php/Plugin.php index d4f051c..80fdb5e 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -45,6 +45,9 @@ public function init() { // Add taxonomies. Taxonomies::create(); + + // Init Posts to Posts. + PostsToPosts::register_post_relationships(); } /** diff --git a/php/PostsToPosts.php b/php/PostsToPosts.php new file mode 100644 index 0000000..7467ebd --- /dev/null +++ b/php/PostsToPosts.php @@ -0,0 +1,168 @@ + 'functions_to_functions', + 'from' => 'wp-parser-function', + 'to' => 'wp-parser-function', + 'can_create_post' => false, + 'self_connections' => true, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Uses Functions', 'phpdoc-plugin' ), + 'to' => __( 'Used by Functions', 'phpdoc-plugin' ), + ), + ) + ); + + p2p_register_connection_type( + array( + 'name' => 'functions_to_methods', + 'from' => 'wp-parser-function', + 'to' => 'wp-parser-method', + 'can_create_post' => false, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Uses Methods', 'phpdoc-plugin' ), + 'to' => __( 'Used by Functions', 'phpdoc-plugin' ), + ), + ) + ); + + p2p_register_connection_type( + array( + 'name' => 'functions_to_hooks', + 'from' => 'wp-parser-function', + 'to' => 'wp-parser-hook', + 'can_create_post' => false, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Uses Hooks', 'phpdoc-plugin' ), + 'to' => __( 'Used by Functions', 'phpdoc-plugin' ), + ), + ) + ); + + /* + * Methods to functions, methods and hooks + */ + p2p_register_connection_type( + array( + 'name' => 'methods_to_functions', + 'from' => 'wp-parser-method', + 'to' => 'wp-parser-function', + 'can_create_post' => false, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Uses Functions', 'phpdoc-plugin' ), + 'to' => __( 'Used by Methods', 'phpdoc-plugin' ), + ), + ) + ); + + p2p_register_connection_type( + array( + 'name' => 'methods_to_methods', + 'from' => 'wp-parser-method', + 'to' => 'wp-parser-method', + 'can_create_post' => false, + 'self_connections' => true, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Uses Methods', 'phpdoc-plugin' ), + 'to' => __( 'Used by Methods', 'phpdoc-plugin' ), + ), + ) + ); + + p2p_register_connection_type( + array( + 'name' => 'methods_to_hooks', + 'from' => 'wp-parser-method', + 'to' => 'wp-parser-hook', + 'can_create_post' => false, + 'from_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'to_query_vars' => array( + 'orderby' => 'post_title', + 'order' => 'ASC', + ), + 'title' => array( + 'from' => __( 'Used by Methods', 'phpdoc-plugin' ), + 'to' => __( 'Uses Hooks', 'phpdoc-plugin' ), + ), + ) + ); + } +} From 235b2ed8a10243cfc3d284f0f47c9a284bb18fdf Mon Sep 17 00:00:00 2001 From: Ronald Huereca Date: Thu, 30 Sep 2021 09:47:06 -0500 Subject: [PATCH 6/7] Add rewrite rules. --- class-phpdoc-plugin.php | 1 + php/Plugin.php | 7 +++++++ php/PostTypes.php | 3 --- php/RewriteRules.php | 29 +++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 php/RewriteRules.php diff --git a/class-phpdoc-plugin.php b/class-phpdoc-plugin.php index 36dc641..e0f9c2d 100644 --- a/class-phpdoc-plugin.php +++ b/class-phpdoc-plugin.php @@ -41,5 +41,6 @@ public function plugins_loaded() { } $phpdoc_plugin = new Bootstrap(); +register_activation_hook( __FILE__, array( '\Pods\phpDoc_Plugin\Plugin', 'register_activation_hook' ) ); add_action( 'plugins_loaded', array( $phpdoc_plugin, 'plugins_loaded' ) ); diff --git a/php/Plugin.php b/php/Plugin.php index 80fdb5e..ef3ce42 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -63,6 +63,13 @@ public function after_setup_theme() { remove_action( 'init', array( $explanations, 'register_post_type' ), 0 ); } + /** + * Run when the plugin is activated. + */ + public static function register_activation_hook() { + RewriteRules::flush(); + } + /** * Is WP debug mode enabled. * diff --git a/php/PostTypes.php b/php/PostTypes.php index 63bf21e..1f10473 100644 --- a/php/PostTypes.php +++ b/php/PostTypes.php @@ -59,9 +59,6 @@ public static function create() { ); } - add_rewrite_rule( 'reference/classes/page/([0-9]{1,})/?$', 'index.php?post_type=wp-parser-class&paged=$matches[1]', 'top' ); - add_rewrite_rule( 'reference/classes/([^/]+)/([^/]+)/?$', 'index.php?post_type=wp-parser-method&name=$matches[1]-$matches[2]', 'top' ); - if ( ! post_type_exists( 'wp-parser-class' ) ) { register_post_type( 'wp-parser-class', diff --git a/php/RewriteRules.php b/php/RewriteRules.php new file mode 100644 index 0000000..5c11ace --- /dev/null +++ b/php/RewriteRules.php @@ -0,0 +1,29 @@ + Date: Fri, 1 Oct 2021 10:43:47 -0500 Subject: [PATCH 7/7] Adding explanations post type to plugin. --- assets/js/explanations.js | 105 ++++++ class-phpdoc-plugin.php | 3 + php/Explanations.php | 670 ++++++++++++++++++++++++++++++++++++++ php/Functions.php | 82 +++++ php/Plugin.php | 9 + 5 files changed, 869 insertions(+) create mode 100644 assets/js/explanations.js create mode 100644 php/Explanations.php create mode 100644 php/Functions.php diff --git a/assets/js/explanations.js b/assets/js/explanations.js new file mode 100644 index 0000000..3e32eb8 --- /dev/null +++ b/assets/js/explanations.js @@ -0,0 +1,105 @@ +/** + * Explanations JS. + */ + +( function( $ ) { + + // + // Explanations AJAX handlers. + // + + var statusLabel = $( '#status-label' ), + createLink = $( '#create-expl' ), + unPublishLink = $( '#unpublish-expl' ), + rowActions = $( '#expl-row-actions' ); + + var rowCreateLink = $( '.create-expl' ); + + /** + * AJAX handler for creating and associating a new explanation post. + * + * @param {object} event Event object. + */ + function createExplanation( event ) { + event.preventDefault(); + + wp.ajax.send( 'new_explanation', { + success: createExplSuccess, + error: createExplError, + data: { + nonce: $( this ).data( 'nonce' ), + post_id: $( this ).data( 'id' ), + context: event.data.context + } + } ); + } + + /** + * Success callback for creating a new explanation via AJAX. + * + * @param {object} data Data response object. + */ + function createExplSuccess( data ) { + var editLink = '' + wporg.editContentLabel + ''; + + if ( 'edit' == data.context ) { + // Action in the parsed post type edit screen. + createLink.hide(); + rowActions.html( editLink ); + statusLabel.text( wporg.statusLabel.draft ); + } else { + // Row link in the list table. + $( '#post-' + data.parent_id + ' .add-expl' ).html( editLink + ' | ' ); + } + } + + /** + * Error callback for creating a new explanation via AJAX. + * + * @param {object} data Data response object. + */ + function createExplError( data ) {} + + /** + * Handler for un-publishing an existing Explanation. + * + * @param {object} event Event object. + */ + function unPublishExplantaion( event ) { + event.preventDefault(); + + wp.ajax.send( 'un_publish', { + success: unPublishSuccess, + error: unPublishError, + data: { + nonce: $( this ).data( 'nonce' ), + post_id: $( this ).data( 'id' ) + } + } ); + } + + /** + * Success callback for un-publishing an explanation via AJAX. + * + * @param {object} data Data response object. + */ + function unPublishSuccess( data ) { + if ( statusLabel.hasClass( 'pending' ) || statusLabel.hasClass( 'publish' ) ) { + statusLabel.removeClass( 'pending publish' ).text( wporg.statusLabel.draft ); + } + unPublishLink.hide(); + } + + /** + * Error callback for un-publishing an explanation via AJAX. + * + * @param {object} data Data response object. + */ + function unPublishError( data ) {} + + // Events. + createLink.on( 'click', { context: 'edit' }, createExplanation ); + rowCreateLink.on( 'click', { context: 'list' }, createExplanation ); + unPublishLink.on( 'click', unPublishExplantaion ); + +} )( jQuery ); diff --git a/class-phpdoc-plugin.php b/class-phpdoc-plugin.php index e0f9c2d..53ab706 100644 --- a/class-phpdoc-plugin.php +++ b/class-phpdoc-plugin.php @@ -37,6 +37,9 @@ public function plugins_loaded() { // Init the plugin. add_action( 'init', array( $plugin, 'init' ) ); + + // Plugins loaded actions. + $plugin->plugins_loaded(); } } diff --git a/php/Explanations.php b/php/Explanations.php new file mode 100644 index 0000000..d0c780b --- /dev/null +++ b/php/Explanations.php @@ -0,0 +1,670 @@ +post_types = PostTypes::get_parsed_post_types(); + + $this->screen_ids = array( $this->exp_post_type, "edit-{$this->exp_post_type}" ); + + // Setup. + add_action( 'init', array( $this, 'register_post_type' ), 0 ); + add_action( 'init', array( $this, 'remove_editor_support' ), 100 ); + + // Admin. + add_action( 'edit_form_after_title', array( $this, 'post_to_expl_controls' ) ); + add_action( 'edit_form_top', array( $this, 'expl_to_post_controls' ) ); + add_action( 'admin_bar_menu', array( $this, 'toolbar_edit_link' ), 100 ); + add_action( 'admin_menu', array( $this, 'admin_menu' ) ); + add_action( 'load-post-new.php', array( $this, 'prevent_direct_creation' ) ); + // Add admin post listing column for explanations indicator. + add_filter( 'manage_posts_columns', array( $this, 'add_post_column' ) ); + // Output checkmark in explanations column if post has an explanation. + add_action( 'manage_posts_custom_column', array( $this, 'handle_column_data' ), 10, 2 ); + + add_filter( 'preview_post_link', array( $this, 'preview_post_link' ), 10, 2 ); + + // Permissions. + add_action( 'after_switch_theme', array( $this, 'add_roles' ) ); + add_filter( 'user_has_cap', array( $this, 'grant_caps' ) ); + add_filter( 'post_row_actions', array( $this, 'expl_row_action' ), 10, 2 ); + + // Script and styles. + add_filter( 'devhub-admin_enqueue_scripts', array( $this, 'admin_enqueue_base_scripts' ) ); + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + + // AJAX. + add_action( 'wp_ajax_new_explanation', array( $this, 'new_explanation' ) ); + add_action( 'wp_ajax_un_publish', array( $this, 'un_publish_explanation' ) ); + } + + /** + * Register the Explanations post type. + * + * @access public + */ + public function register_post_type() { + register_post_type( + $this->exp_post_type, + array( + 'labels' => array( + 'name' => __( 'Explanations', 'phpdoc-plugin' ), + 'singular_name' => __( 'Explanation', 'phpdoc-plugin' ), + 'all_items' => __( 'Explanations', 'phpdoc-plugin' ), + 'edit_item' => __( 'Edit Explanation', 'phpdoc-plugin' ), + 'view_item' => __( 'View Explanation', 'phpdoc-plugin' ), + 'search_items' => __( 'Search Explanations', 'phpdoc-plugin' ), + 'not_found' => __( 'No Explanations found', 'phpdoc-plugin' ), + 'not_found_in_trash' => __( 'No Explanations found in trash', 'phpdoc-plugin' ), + ), + 'public' => false, + 'publicly_queryable' => true, + 'hierarchical' => false, + 'show_ui' => true, + 'show_in_menu' => true, + 'menu_icon' => 'dashicons-info', + 'show_in_admin_bar' => false, + 'show_in_nav_menus' => false, + 'capability_type' => 'explanation', + 'map_meta_cap' => true, + 'supports' => array( 'editor', 'revisions' ), + 'rewrite' => false, + 'query_var' => false, + ) + ); + } + + /** + * Remove 'editor' support for the function, hook, class, and method post types. + * + * @access public + */ + public function remove_editor_support() { + foreach ( $this->post_types as $type ) { + remove_post_type_support( $type, 'editor' ); + } + } + + /** + * Override preview post links for explanations to preview the explanation + * within the context of its associated function/hook/method/class. + * + * The associated post's preview link is amended with query parameters used + * by `get_explanation_content()` to use the explanation being previewed + * instead of the published explanation currently associated with the post. + * + * @access public + * @see 'preview_post_link' filter + * + * @param string $preview_link URL used for the post preview. + * @param WP_Post $post Post object. + * @return string + **/ + public function preview_post_link( $preview_link, $post ) { + if ( $this->exp_post_type !== $post->post_type ) { + return $preview_link; + } + + if ( false !== strpos( $preview_link, 'preview_nonce=' ) ) { + $url = wp_parse_url( $preview_link ); + $url_query = array(); + parse_str( $url['query'], $url_query ); + + $preview_link = get_preview_post_link( + $post->post_parent, + array( + 'wporg_explanations_preview_id' => $url_query['preview_id'], + 'wporg_explanations_preview_nonce' => $url_query['preview_nonce'], + ) + ); + } + + return $preview_link; + } + + /** + * Customizes admin menu. + * + * - Removes "Add new". + * - Adds count of pending explanations. + * + * @access public + */ + public function admin_menu() { + global $menu; + + $menu_slug = 'edit.php?post_type=' . $this->exp_post_type; + + // Remove 'Add New' from submenu. + remove_submenu_page( $menu_slug, 'post-new.php?post_type=' . $this->exp_post_type ); + + // Add pending posts count. + $counts = wp_count_posts( $this->exp_post_type ); + $count = $counts->pending; + if ( $count ) { + // Find the explanations menu item. + foreach ( $menu as $i => $item ) { + if ( $menu_slug === $item[2] ) { + // Modify it to include the pending count. + $menu[ $i ][0] = sprintf( // phpcs:ignore + /* Translators: %s is the count. */ + __( 'Explanations %s', 'phpdoc-plugin' ), + "" . number_format_i18n( $count ) . '' + ); + break; + } + } + } + } + + /** + * Prevents direct access to the admin page for creating a new explanation. + * + * Only prevents admin UI access to directly create a new explanation. It does + * not attempt to prevent direct programmatic creation of a new explanation. + * + * @access public + */ + public function prevent_direct_creation() { + $post_type = filter_input( INPUT_GET, 'post_type', FILTER_SANITIZE_STRING ); + if ( $post_type && $post_type === $this->exp_post_type ) { + wp_safe_redirect( admin_url() ); + exit; + } + } + + /** + * Output the Post-to-Explanation controls in the post editor for functions, + * hooks, classes, and methods. + * + * @access public + * + * @param WP_Post $post Current post object. + */ + public function post_to_expl_controls( $post ) { + if ( ! in_array( $post->post_type, $this->post_types, true ) ) { + return; + } + + $explanation = get_explanation( $post ); + $date_format = get_option( 'date_format' ) . ', ' . get_option( 'time_format' ); + ?> +
+
+

+
+ + + + + + + + + + + + + +
+ + + +
+ + +

ID ) ); ?>

+
+
+
+
+ exp_post_type !== $post->post_type ) { + return; + } + ?> +
+
+
+ + %2$s', + esc_url( get_permalink( $post->post_parent ) ), + esc_html( str_replace( 'Explanation: ', '', get_the_title( $post->post_parent ) ) ) + ); + ?> +
+
+
+ get_queried_object(); + + if ( is_admin() || empty( $screen->post_type ) || ! is_singular( $this->post_types ) ) { + return; + } + + // Proceed only if there's an explanation for the current reference post type. + if ( ! empty( $screen->post_type ) && $explanation = get_explanation( $screen ) ) { // phpcs:ignore + + // Must be able to edit the explanation. + if ( is_user_member_of_blog() && current_user_can( 'edit_explanation', $explanation->ID ) ) { + $post_type = get_post_type_object( $this->exp_post_type ); + + $wp_admin_bar->add_menu( + array( + 'id' => 'edit-explanation', + 'title' => $post_type->labels->edit_item, + 'href' => get_edit_post_link( $explanation ), + ) + ); + } + } + } + + /** + * Adds the 'Explanation Editor' role. + * + * @access public + */ + public function add_roles() { + add_role( + 'expl_editor', + __( 'Explanation Editor', 'phpdoc-plugin' ), + array( + 'unfiltered_html' => true, + 'read' => true, + 'edit_explanations' => true, + 'edit_others_explanations' => true, + 'edit_published_explanations' => true, + 'edit_private_explanations' => true, + 'read_private_explanations' => true, + ) + ); + } + + /** + * Grants explanation capabilities to users. + * + * @access public + * + * @param array $caps Capabilities. + * @return array Modified capabilities array. + */ + public function grant_caps( $caps ) { + + if ( ! is_user_member_of_blog() ) { + return $caps; + } + + $role = wp_get_current_user()->roles[0]; + + // Only grant explanation post type caps for admins, editors, and explanation editors. + if ( in_array( $role, array( 'administrator', 'editor', 'expl_editor' ), true ) ) { + $base_caps = array( + 'edit_explanations', + 'edit_others_explanations', + 'edit_published_explanations', + 'edit_posts', + ); + + foreach ( $base_caps as $cap ) { + $caps[ $cap ] = true; + } + + $editor_caps = array( + 'publish_explanations', + 'delete_explanations', + 'delete_others_explanations', + 'delete_published_explanations', + 'delete_private_explanations', + 'edit_private_explanations', + 'read_private_explanations', + ); + + if ( ! empty( $caps['edit_pages'] ) ) { + foreach ( $editor_caps as $cap ) { + $caps[ $cap ] = true; + } + } + } + + return $caps; + } + + /** + * Adds the 'Add/Edit Explanation' row actions to the parsed post type list tables. + * + * @access public + * + * @param array $actions Row actions. + * @param \WP_Post $post Parsed post object. + * @return array (Maybe) filtered row actions. + */ + public function expl_row_action( $actions, $post ) { + if ( ! in_array( $post->post_type, PostTypes::get_parsed_post_types(), true ) ) { + return $actions; + } + + $expl = \DevHub\get_explanation( $post ); + + $expl_action = array(); + + if ( $expl ) { + if ( ! current_user_can( 'edit_posts', $expl->ID ) ) { + return $actions; + } + + $expl_action['edit-expl'] = sprintf( + '%3$s', + esc_url( get_edit_post_link( $expl->ID ) ), + esc_attr__( 'Edit Explanation', 'phpdoc-plugin' ), + __( 'Edit Explanation', 'phpdoc-plugin' ) + ); + } else { + $expl_action['add-expl'] = sprintf( + '%3$s', + esc_attr( wp_create_nonce( 'create-expl' ) ), + esc_attr( $post->ID ), + __( 'Add Explanation', 'phpdoc-plugin' ) + ); + } + + return array_merge( $expl_action, $actions ); + } + + /** + * Output the Explanation status controls. + * + * @access public + * + * @param int|WP_Post $post Post ID or WP_Post object. + */ + public function status_controls( $post ) { + $explanation = DevHub\get_explanation( $post ); + + if ( $explanation ) : + echo wp_kses_post( $this->get_status_label( $explanation->ID ) ); + ?> + + + + + + + + + + + +

+ + + + + + post_status ) { // phpcs:ignore + case 'draft': + $label = __( 'Draft', 'phpdoc-plugin' ); + break; + case 'pending': + $label = __( 'Pending Review', 'phpdoc-plugin' ); + break; + case 'publish': + $label = __( 'Published', 'phpdoc-plugin' ); + break; + default: + $status = ''; + $label = __( 'None', 'phpdoc-plugin' ); + break; + } + + return '

' . $label . '

'; + } + + /** + * Enables enqueuing of admin.css for explanation pages. + * + * @access public + * + * @param bool $do_enqueue Should admin.css be enqueued?. + * + * @return bool True if admin.css should be enqueued, false otherwise. + */ + public function admin_enqueue_base_scripts( $do_enqueue ) { + return $do_enqueue || in_array( get_current_screen()->id, $this->screen_ids, true ); + } + + /** + * Enqueue JS and CSS for all parsed post types and explanation pages. + * + * @access public + */ + public function admin_enqueue_scripts() { + + $parsed_post_types_screen_ids = Functions::get_parsed_post_types_screen_ids(); + + if ( in_array( + get_current_screen()->id, + array_merge( + $parsed_post_types_screen_ids, + $this->screen_ids + ), + true + ) ) { + wp_enqueue_script( 'wporg-explanations', Plugin::get_plugin_dir( '/assets/js/explanations.js' ), array( 'jquery', 'wp-util' ), '20160630', true ); + + wp_localize_script( + 'wporg-explanations', + 'phpdoc-plugin', + array( + 'editContentLabel' => __( 'Edit Explanation', 'phpdoc-plugin' ), + 'statusLabel' => array( + 'draft' => __( 'Draft', 'phpdoc-plugin' ), + 'pending' => __( 'Pending Review', 'phpdoc-plugin' ), + 'publish' => __( 'Published', 'phpdoc-plugin' ), + ), + ) + ); + } + } + + /** + * AJAX handler for creating and associating a new explanation. + * + * @access public + */ + public function new_explanation() { + check_ajax_referer( 'create-expl', 'nonce' ); + + $post_id = empty( $_REQUEST['post_id'] ) ? 0 : absint( $_REQUEST['post_id'] ); + $context = empty( $_REQUEST['context'] ) ? '' : sanitize_text_field( wp_unslash( $_REQUEST['context'] ) ); + + if ( DevHub\get_explanation( $post_id ) ) { + wp_send_json_error( new WP_Error( 'post_exists', __( 'Explanation already exists.', 'phpdoc-plugin' ) ) ); + } else { + $title = get_post_field( 'post_title', $post_id ); + + $explanation = wp_insert_post( + array( + 'post_type' => 'wporg_explanations', + 'post_title' => "Explanation: $title", + 'ping_status' => false, + 'post_parent' => $post_id, + ) + ); + + if ( ! is_wp_error( $explanation ) && 0 !== $explanation ) { + wp_send_json_success( + array( + 'post_id' => $explanation, + 'parent_id' => $post_id, + 'context' => $context, + ) + ); + } else { + wp_send_json_error( + new WP_Error( 'post_error', __( 'Explanation could not be created.', 'phpdoc-plugin' ) ) + ); + } + } + } + + /** + * AJAX handler for un-publishing an explanation. + * + * @access public + */ + public function un_publish_explanation() { + check_ajax_referer( 'unpublish-expl', 'nonce' ); + + $post_id = empty( $_REQUEST['post_id'] ) ? 0 : absint( $_REQUEST['post_id'] ); + + if ( $explanation = get_explanation( $post_id ) ) { // phpcs:ignore + $update = wp_update_post( + array( + 'ID' => $explanation->ID, + 'post_status' => 'draft', + ) + ); + + if ( ! is_wp_error( $update ) && 0 !== $update ) { + wp_send_json_success( array( 'post_id' => $update ) ); + } else { + wp_send_json_error( + new WP_Error( 'unpublish_error', __( 'Explanation could not be un-published.', 'phpdoc-plugin' ) ) + ); + } + } + } + + /** + * Adds a column in the admin listing of posts for parsed post types to + * indicate if they have an explanation. + * + * Inserted as first column after title column. + * + * @access public + * + * @param array $columns Associative array of post column ids and labels. + * @return array + */ + public function add_post_column( $columns ) { + if ( ! empty( $_GET['post_type'] ) && Functions::is_parsed_post_type( $_GET['post_type'] ) ) { // phpcs:ignore + $index = array_search( 'title', array_keys( $columns ), true ); + $pos = false === $index ? count( $columns ) : $index + 1; + + $col_data = array( + 'has_explanation' => sprintf( + '%s', + esc_attr__( 'Has explanation?', 'phpdoc-plugin' ), + esc_html__( 'Explanation?', 'phpdoc-plugin' ) + ), + ); + $columns = array_merge( array_slice( $columns, 0, $pos ), $col_data, array_slice( $columns, $pos ) ); + } + + return $columns; + } + + /** + * Outputs an indicator for the explanations column if post has an explanation. + * + * @access public + * + * @param string $column_name The name of the column. + * @param int $post_id The ID of the post. + */ + public function handle_column_data( $column_name, $post_id ) { + if ( 'has_explanation' === $column_name ) { + if ( $explanation = get_explanation( $post_id ) ) { // phpcs:ignore + printf( + '%s%s', + esc_url( get_edit_post_link( $explanation ) ), + '', + '' . esc_html__( 'Post has an explanation.', 'phpdoc-plugin' ) . '' + ); + } + } + } +} diff --git a/php/Functions.php b/php/Functions.php new file mode 100644 index 0000000..989266f --- /dev/null +++ b/php/Functions.php @@ -0,0 +1,82 @@ + 'wporg_explanations', + 'post_parent' => $post->ID, + 'no_found_rows' => true, + 'posts_per_page' => 1, + ); + + if ( true === $published ) { + $args['post_status'] = 'publish'; + } + + $explanation = get_children( $args, OBJECT ); + + if ( empty( $explanation ) ) { + return null; + } + + $explanation = reset( $explanation ); + + if ( ! $explanation ) { + return null; + } + return $explanation; +} diff --git a/php/Plugin.php b/php/Plugin.php index ef3ce42..f6e9105 100644 --- a/php/Plugin.php +++ b/php/Plugin.php @@ -50,6 +50,15 @@ public function init() { PostsToPosts::register_post_relationships(); } + /** + * Actions to run when all plugins have been loaded. + * + * @see WP plugins_loaded action. + */ + public function plugins_loaded() { + new Explanations(); + } + /** * After a theme's functions.php file has been run. *