-
Notifications
You must be signed in to change notification settings - Fork 64
Add Content Generation integration to WordPress Quick Draft widget #1012
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
5e6e18f
4cf3718
dbc9b5e
060f133
4336832
7172275
6707b29
dbc4f4a
3b77378
1487ad2
c5fe121
6f81801
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,262 @@ | ||
| <?php | ||
| /** | ||
| * Quick Draft Integration Feature. | ||
| * | ||
| * Integrates ClassifAI Content Generation with WordPress Quick Draft widget. | ||
| */ | ||
|
|
||
| namespace Classifai\Features; | ||
|
|
||
| use Classifai\Features\ContentGeneration; | ||
| use WP_REST_Server; | ||
| use WP_REST_Request; | ||
| use WP_Error; | ||
|
|
||
| /** | ||
| * Quick Draft Integration Feature. | ||
| * | ||
| * Integrates ClassifAI Content Generation with WordPress Quick Draft widget. | ||
| */ | ||
| class QuickDraftIntegration { | ||
|
|
||
| /** | ||
| * Content Generation feature instance. | ||
| * | ||
| * @var ContentGeneration | ||
| */ | ||
| private $content_generation; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| */ | ||
| public function __construct() { | ||
| $this->content_generation = new ContentGeneration(); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize the Quick Draft integration. | ||
| */ | ||
| public function init() { | ||
| // Only initialize if Content Generation is enabled. | ||
| if ( ! $this->content_generation->is_feature_enabled() ) { | ||
| return; | ||
| } | ||
|
|
||
| // Check if Quick Draft integration is enabled. | ||
| if ( ! $this->is_quick_draft_enabled() ) { | ||
| return; | ||
| } | ||
|
|
||
| add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); | ||
| add_action( 'wp_dashboard_setup', [ $this, 'modify_quick_draft_widget' ] ); | ||
| add_action( 'rest_api_init', [ $this, 'register_endpoints' ] ); | ||
| } | ||
|
|
||
| /** | ||
| * Check if Quick Draft integration is enabled. | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function is_quick_draft_enabled(): bool { | ||
| $settings = $this->content_generation->get_settings(); | ||
| return isset( $settings['enable_quick_draft'] ) ? (bool) $settings['enable_quick_draft'] : true; | ||
| } | ||
|
|
||
| /** | ||
| * Enqueue Quick Draft assets on the dashboard. | ||
| */ | ||
| public function enqueue_assets() { | ||
| $screen = get_current_screen(); | ||
|
|
||
| // Only load on dashboard. | ||
| if ( ! $screen || 'dashboard' !== $screen->id ) { | ||
| return; | ||
| } | ||
|
|
||
| // Only load if user can create posts. | ||
| if ( ! current_user_can( 'edit_posts' ) ) { | ||
| return; | ||
| } | ||
|
|
||
| wp_enqueue_script( | ||
| 'classifai-quick-draft-js', | ||
| plugin_dir_url( dirname( __DIR__, 2 ) ) . 'dist/classifai-quick-draft.js', | ||
| [ 'jquery', 'wp-api-fetch' ], | ||
| '3.8.0', | ||
| true | ||
| ); | ||
|
|
||
| wp_localize_script( | ||
| 'classifai-quick-draft-js', | ||
| 'classifaiQuickDraft', | ||
| [ | ||
| 'nonce' => wp_create_nonce( 'classifai_quick_draft' ), | ||
| 'restUrl' => rest_url( 'classifai/v1/' ), | ||
| 'createContent' => __( 'Create Draft from Prompt Content', 'classifai' ), | ||
| 'generating' => __( 'Generating...', 'classifai' ), | ||
| 'error' => __( 'Error generating content. Please try again.', 'classifai' ), | ||
| 'currentUserId' => get_current_user_id(), | ||
| ] | ||
| ); | ||
|
|
||
| wp_enqueue_style( | ||
| 'classifai-quick-draft-css', | ||
| plugin_dir_url( dirname( __DIR__, 2 ) ) . 'dist/classifai-quick-draft.css', | ||
| [], | ||
| '3.8.0' | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Modify the Quick Draft widget to add our button. | ||
| */ | ||
| public function modify_quick_draft_widget() { | ||
| // Only modify if user can create posts | ||
| if ( ! current_user_can( 'edit_posts' ) ) { | ||
| return; | ||
| } | ||
|
|
||
| // Use a different approach - add the button via JavaScript | ||
| add_action( 'admin_footer', [ $this, 'add_quick_draft_button_script' ] ); | ||
| } | ||
|
|
||
| /** | ||
| * Add the button via JavaScript in the admin footer. | ||
| */ | ||
| public function add_quick_draft_button_script() { | ||
| $screen = get_current_screen(); | ||
|
|
||
| // Only add on dashboard | ||
| if ( ! $screen || 'dashboard' !== $screen->id ) { | ||
| return; | ||
| } | ||
| ?> | ||
| <script type="text/javascript"> | ||
| jQuery(document).ready(function($) { | ||
| // Wait for the Quick Draft widget to be loaded | ||
| setTimeout(function() { | ||
| var saveButton = $('#save-post'); | ||
| if (saveButton.length && !$('#classifai-generate-content').length) { | ||
| var generateButton = $('<input type="button" id="classifai-generate-content" class="button" value="<?php echo esc_js( __( 'Create Draft from Prompt Content', 'classifai' ) ); ?>" style="margin-left: 10px;" />'); | ||
| saveButton.after(generateButton); | ||
| } | ||
| }, 1000); | ||
| }); | ||
| </script> | ||
| <?php | ||
| } | ||
|
|
||
| /** | ||
| * Register Quick Draft specific endpoints. | ||
| */ | ||
| public function register_endpoints() { | ||
| register_rest_route( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I almost think a better approach here would be to register a more generic endpoint in the Content Generation Feature class that allows generating content that isn't associated with a post ID (or modify our existing endpoint to support that). That way we don't end up with a very specific endpoint here |
||
| 'classifai/v1', | ||
| 'quick-draft-generate', | ||
| [ | ||
| 'methods' => WP_REST_Server::CREATABLE, | ||
| 'callback' => [ $this, 'endpoint_callback' ], | ||
| 'permission_callback' => [ $this, 'permissions_check' ], | ||
| 'args' => [ | ||
| 'title' => [ | ||
| 'type' => 'string', | ||
| 'sanitize_callback' => 'sanitize_text_field', | ||
| 'validate_callback' => 'rest_validate_request_arg', | ||
| 'description' => esc_html__( 'The title of the article.', 'classifai' ), | ||
| ], | ||
| 'content' => [ | ||
| 'required' => true, | ||
| 'type' => 'string', | ||
| 'sanitize_callback' => 'sanitize_textarea_field', | ||
| 'validate_callback' => 'rest_validate_request_arg', | ||
| 'description' => esc_html__( 'The prompt content for generation.', 'classifai' ), | ||
| ], | ||
| ], | ||
| ] | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Check permissions for Quick Draft generation. | ||
| * | ||
| * @return WP_Error|bool | ||
| */ | ||
| public function permissions_check() { | ||
| // Ensure user can create posts | ||
| if ( ! current_user_can( 'edit_posts' ) ) { | ||
| return false; | ||
| } | ||
|
|
||
| // Ensure the feature is enabled | ||
| if ( ! $this->content_generation->is_feature_enabled() ) { | ||
| return new WP_Error( 'not_enabled', esc_html__( 'Content Generation is not currently enabled.', 'classifai' ) ); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Handle Quick Draft content generation. | ||
| * | ||
| * @param WP_REST_Request $request The full request object. | ||
| * @return \WP_REST_Response | ||
| */ | ||
| public function endpoint_callback( WP_REST_Request $request ) { | ||
| $title = $request->get_param( 'title' ); | ||
| $content = $request->get_param( 'content' ); | ||
|
|
||
| // Create a new auto-draft post | ||
| $post_data = [ | ||
| 'post_title' => $title ? $title : '', | ||
| 'post_content' => '', | ||
| 'post_status' => 'auto-draft', | ||
| 'post_type' => 'post', | ||
| 'post_author' => get_current_user_id(), | ||
| ]; | ||
|
|
||
| $post_id = wp_insert_post( $post_data ); | ||
|
|
||
| if ( is_wp_error( $post_id ) ) { | ||
| return new WP_Error( 'post_creation_failed', esc_html__( 'Failed to create draft post.', 'classifai' ) ); | ||
| } | ||
|
|
||
| // Generate content using the existing content generation logic | ||
| $result = $this->content_generation->run( | ||
| $post_id, | ||
| 'create_content', | ||
| [ | ||
| 'title' => $title, | ||
| 'summary' => $content, | ||
| ] | ||
| ); | ||
|
|
||
| if ( is_wp_error( $result ) ) { | ||
| // Clean up the post if generation failed | ||
| wp_delete_post( $post_id, true ); | ||
| return $result; | ||
| } | ||
|
|
||
| // Update the post with generated content | ||
| $updated_post = [ | ||
| 'ID' => $post_id, | ||
| 'post_content' => $result, | ||
| 'post_status' => 'draft', | ||
| ]; | ||
|
|
||
| $update_result = wp_update_post( $updated_post ); | ||
|
|
||
| if ( is_wp_error( $update_result ) ) { | ||
| return new WP_Error( 'post_update_failed', esc_html__( 'Failed to update post with generated content.', 'classifai' ) ); | ||
| } | ||
|
|
||
| return rest_ensure_response( | ||
| [ | ||
| 'post_id' => $post_id, | ||
| 'edit_url' => admin_url( "post.php?post={$post_id}&action=edit" ), | ||
| 'content' => $result, | ||
| 'title' => $title, | ||
| 'success' => true, | ||
| ] | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,6 +42,7 @@ public function enable() { | |
| add_filter( 'plugin_action_links_' . CLASSIFAI_PLUGIN_BASENAME, [ $this, 'filter_plugin_action_links' ] ); | ||
| add_filter( 'robots_txt', [ $this, 'maybe_block_ai_crawlers' ] ); | ||
| add_action( 'after_classifai_init', [ $this, 'load_action_scheduler' ] ); | ||
| add_action( 'after_classifai_init', [ $this, 'init_quick_draft_integration' ] ); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -302,6 +303,14 @@ public function maybe_block_ai_crawlers( $robots_txt ) { | |
| return $robots_txt; | ||
| } | ||
|
|
||
| /** | ||
| * Initialize Quick Draft integration. | ||
| */ | ||
| public function init_quick_draft_integration() { | ||
| $quick_draft = new \Classifai\Features\QuickDraftIntegration(); | ||
| $quick_draft->init(); | ||
| } | ||
|
Comment on lines
+309
to
+312
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I love initializing this here. Since this is tied to the Content Generation Feature, would it make more sense to initialize this in that class? |
||
|
|
||
| /** | ||
| * Load the Action Scheduler library. | ||
| */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're loading custom CSS, can we remove this inline style here and add it there instead?