
WordPress plugin dev with the help of Claude.ai, part 3
Maybe you’ve seen I’ve started another post series, but let’s not forget about WordPress and AI. We’ll carry on with the development of the plugin
As mentioned in all previous posts, it may still be easier to follow along with the full code from this series:
https://github.com/jalonenbrothers/film-review-plugin-demo
Moving things around in the back-end
in the public/class-jbros-film-review-public.php
get_film_review
method I’d like to query the tmdb api first , if the action is not ‘get_existing’, and only call Anthropic API
if tmdb api returns a result. We can then include the TMDB API
results in the call to create_or_update_film_review_post
method.
To implement the desired functionality, you can modify the get_film_review
method in the class-jbros-film-review-public.php
file. Here’s the updated code:
/**
* Get a film review from the Anthropic API.
*
* @param WP_REST_Request $request The REST API request.
*
* @return WP_REST_Response The API response.
*/
public function get_film_review($request)
{
$title = sanitize_text_field($request->get_param('title'));
$year = absint($request->get_param('year'));
$action = sanitize_text_field($request->get_param('action'));
if (empty($title) || empty($year)) {
return new WP_REST_Response(array(
'success' => false,
'message' => 'Invalid request parameters.',
), 400);
}
$existing_post_id = $this->get_film_review_post_id($title, $year);
if ($action === 'get_existing' && $existing_post_id) {
$existing_post = get_post($existing_post_id);
return new WP_REST_Response(array(
'success' => true,
'data' => array(
'title' => $title,
'year' => $year,
'film_review' => $existing_post->post_content,
'post_id' => $existing_post_id,
),
), 200);
}
// Query the TMDB API first if the action is not 'get_existing'
if ($action !== 'get_existing') {
$tmdb_api = new TMDB_API();
$movie_data = $tmdb_api->get_movie_data_by_title_and_year($title, $year);
if (is_wp_error($movie_data)) {
return new WP_REST_Response(array(
'success' => false,
'message' => $movie_data->get_error_message(),
), 500);
}
// If TMDB API returns a result, proceed with Anthropic API
if (!empty($movie_data)) {
$anthropic_api = new Anthropic_API();
$film_review = $anthropic_api->get_film_review($title, $year);
if (is_wp_error($film_review)) {
return new WP_REST_Response(array(
'success' => false,
'message' => $film_review->get_error_message(),
), 500);
}
$post_id = $this->create_or_update_film_review_post($title, $year, $film_review, $movie_data);
if (is_wp_error($post_id)) {
return new WP_REST_Response(array(
'success' => false,
'message' => $post_id->get_error_message(),
), 500);
}
return new WP_REST_Response(array(
'success' => true,
'data' => array(
'title' => $title,
'year' => $year,
'film_review' => $film_review,
'post_id' => $post_id,
'movie_data' => $movie_data,
),
), 200);
}
}
// If TMDB API doesn't return a result or the action is 'get_existing', return an appropriate response
return new WP_REST_Response(array(
'success' => false,
'message' => 'No movie found or invalid action.',
), 404);
}
Here’s what the updated code does:
- If the action is not ‘get_existing’, it queries the
TMDB API
first using theget_movie_data_by_title_and_year
method. - If the
TMDB API
returns a valid result, it proceeds to call the Anthropic API and fetch the film review. - If both the
TMDB API
andAnthropic API
responses are successful, it creates or updates the film review post using thecreate_or_update_film_review_post
method, passing the movie data from theTMDB API
as an additional argument. - The response includes the movie data from the
TMDB API
along with the film review and other relevant information. - If the
TMDB API
doesn’t return a result or the action is ‘get_existing’, it returns an appropriate error response.
You will also need to update the create_or_update_film_review_post
method to accept the $movie_data
parameter and store the relevant data using the update_post_meta
function calls.
/**
* Create or update a film review post.
*
* @param string $title The movie title.
* @param int $year The movie year.
* @param string $film_review The film review content.
* @param array $movie_data The movie data from TMDB API.
*
* @return int|WP_Error The post ID on success, or WP_Error on failure.
*/
private function create_or_update_film_review_post($title, $year, $film_review, $movie_data)
{
// ... (existing code) ...
// Save post meta (including movie data)
update_post_meta($post_id, 'film_title', $title);
update_post_meta($post_id, 'film_year', $year);
update_post_meta($post_id, 'jbros_movie_id', $movie_data['id']);
update_post_meta($post_id, 'jbros_poster_url', $movie_data['poster_url']);
update_post_meta($post_id, 'jbros_backdrop_path', $movie_data['backdrop_path']);
update_post_meta($post_id, 'jbros_overview', $movie_data['overview']);
return $post_id;
}
With these changes, the plugin will first query the TMDB API
for movie details, and if a result is found, it will proceed to fetch the film review from the Anthropic API
. The movie data will be stored along with the film review in the corresponding post.
public function __construct() {
$this->api_key = get_option( 'jbros_film_review_anthropic_api_key' );
$this->api_url = get_option( 'jbros_film_review_anthropic_api_url' ) ;
}
Sure, you can add a settings page to your WordPress plugin to manage the API keys and URLs for both Anthropic API
and TMDB API
.
Here’s how you can proceed:
- Create a new file for settings page
- Create a new file in your plugin’s admin directory, e.g.,
class-jbros-film-review-settings.php
. This file will contain the class responsible for rendering and handling the plugin settings page. - Define the settings page class
In the class-jbros-film-review-settings.php
file, define a new class, e.g., Jbros_Film_Review_Settings
, that extends the WP_Settings_Page
class. This class will handle the rendering and saving of the plugin settings.
/**
* Jbros_Film_Review_Settings class.
*/
class Jbros_Film_Review_Settings extends WP_Settings_Page {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'jbros-film-review';
$this->label = esc_html__( 'JBros Film Review', 'jbros-film-review' );
$this->menu_slug = 'jbros-film-review';
$this->option_group = 'jbros_film_review_options';
parent::__construct();
}
/**
* Get settings array.
*
* @return array
*/
public function get_settings() {
return array(
array(
'id' => 'jbros_film_review_anthropic_api_key',
'title' => esc_html__( 'Anthropic API Key', 'jbros-film-review' ),
'callback' => array( $this, 'sanitize_text_field' ),
'args' => array(),
),
array(
'id' => 'jbros_film_review_anthropic_api_url',
'title' => esc_html__( 'Anthropic API URL', 'jbros-film-review' ),
'callback' => array( $this, 'sanitize_text_field' ),
'args' => array(),
),
array(
'id' => 'jbros_film_review_tmdb_api_key',
'title' => esc_html__( 'TMDB API Key', 'jbros-film-review' ),
'callback' => array( $this, 'sanitize_text_field' ),
'args' => array(),
),
// You can add more settings fields as needed
);
}
/**
* Render the settings page.
*/
public function render_settings_page() {
echo '<div class="wrap">';
echo '<h1>' . esc_html( get_admin_page_title() ) . '</h1>';
echo '<form action="options.php" method="post">';
settings_fields( $this->option_group );
do_settings_sections( $this->menu_slug );
submit_button();
echo '</form>';
echo '</div>';
}
}
- Initialize the settings page
In your plugin’s main file (e.g., jbros-film-review.php), include the class-jbros-film-review-settings.php file and initialize the settings page instance.
// Include the settings page class
require_once plugin_dir_path( __FILE__ ) . 'admin/class-jbros-film-review-settings.php';
// Initialize the settings page
$jbros_film_review_settings = new Jbros_Film_Review_Settings();
Update constructor in
Anthropic_API
andTMDB_API
classesUpdate the constructor in the
Anthropic_API
andTMDB_API
classes to retrieve the API key and URL from the plugin settings.
// In includes/api/class-anthropic-api.php
public function __construct() {
$this->api_key = get_option( 'jbros_film_review_anthropic_api_key' );
$this->api_url = get_option( 'jbros_film_review_anthropic_api_url' );
}
// In includes/api/class-tmdb-api.php
public function __construct() {
$this->api_key = get_option( 'jbros_film_review_tmdb_api_key' );
// If you have a separate URL setting for TMDB API, add it here
}
Additional settings
You can add more settings fields to the get_settings
method in the Jbros_Film_Review_Settings
class based on your requirements. Here are some suggestions for additional settings:
TMDB API URL:
If theTMDB API URL
is not a constant, you can add a separate setting field for it.- Default movie language: You can add a setting field to specify the default language for movie details fetched from TMDB API.
- Enable/Disable caching: You can add a setting field to enable or disable caching for API responses.
- Cache expiration time: If caching is enabled, you can add a setting field to specify the cache expiration time.
Anthropic API
rate limiting: You can add settings to manageAnthropic API
rate limiting, such as the maximum number of requests per minute or hour.
By implementing these changes, you can manage the API keys and URLs for both Anthropic API
and TMDB API
through the WordPress admin settings page for your plugin.
To include the class-jbros-film-review-settings.php
file in your existing plugin main file, you can follow the best practice of loading all required dependencies within the load_dependencies
method. Here’s how you can do it:
Move the class-jbros-film-review-settings.php
file to the includes directory of your plugin. This way, all the related classes and files are organized within the includes directory.
In the load_dependencies
method, add a new line to require the class-jbros-film-review-settings.php
file:
/**
* Load the required dependencies.
*/
private function load_dependencies() {
require_once $this->plugin_path . 'includes/api/class-anthropic-api.php';
require_once $this->plugin_path . 'includes/api/class-tmdb-api.php';
require_once $this->plugin_path . 'public/class-jbros-film-review-public.php';
require_once $this->plugin_path . 'public/blocks/blocks.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-post-types.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-settings.php'; // Add this line
}
In the define_admin_hooks
method, initialize the Jbros_Film_Review_Settings
class and add the necessary hooks to display the settings page in the WordPress admin area:
/**
* Register all hooks related to the admin area functionality.
*/
private function define_admin_hooks() {
// Initialize the settings page
$jbros_film_review_settings = new Jbros_Film_Review_Settings();
// Add the settings page to the admin menu
add_action( 'admin_menu', array( $jbros_film_review_settings, 'add_settings_page' ) );
// Render the settings page
add_action( 'load-' . $jbros_film_review_settings->get_menu_slug(), array( $jbros_film_review_settings, 'render_settings_page' ) );
}
After making these changes, your plugin will load the class-jbros-film-review-settings.php
file, and the settings page will be available in the WordPress admin area under the menu item “JBros Film Review”.
By following this approach, you’re separating concerns and organizing your plugin files in a structured manner, which makes it easier to maintain and extend in the future.
Since you haven’t mentioned using any specific library or framework in your project, I’ll provide an alternative approach using WordPress’s built-in Settings API to create the plugin settings page.
Here’s how you can modify the class-jbros-film-review-settings.php
file:
<?php
/**
* Jbros_Film_Review_Settings class.
*/
class Jbros_Film_Review_Settings {
/**
* The plugin option group.
*
* @var string
*/
private $option_group = 'jbros_film_review_settings';
/**
* Constructor.
*/
public function __construct() {
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
}
/**
* Register plugin settings.
*/
public function register_settings() {
register_setting(
$this->option_group,
'jbros_film_review_anthropic_api_key',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
$this->option_group,
'jbros_film_review_anthropic_api_url',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
$this->option_group,
'jbros_film_review_tmdb_api_key',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
// Register additional settings as needed
}
/**
* Add the settings page to the admin menu.
*/
public function add_settings_page() {
add_options_page(
'JBros Film Review Settings',
'JBros Film Review',
'manage_options',
'jbros-film-review',
array( $this, 'render_settings_page' )
);
}
/**
* Render the settings page.
*/
public function render_settings_page() {
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields( $this->option_group );
do_settings_sections( 'jbros-film-review' );
submit_button();
?>
</form>
</div>
<?php
}
}
// Initialize the settings class
$jbros_film_review_settings = new Jbros_Film_Review_Settings();
In this updated code:
- The
register_settings
method uses theregister_setting
function from WordPress to register the plugin settings. - The
add_settings_page
method uses theadd_options_page
function to add the settings page to the admin menu. - The
render_settings_page
method displays the settings page with the appropriate form and fields.
With this approach, you’re using WordPress’s built-in Settings API, which is a recommended practice for adding settings pages to plugins and themes.
To use the registered settings, you can retrieve their values using the get_option function in your plugin’s other classes, such as Anthropic_API
and TMDB_API
.
// In includes/api/class-anthropic-api.php
public function __construct() {
$this->api_key = get_option( 'jbros_film_review_anthropic_api_key' );
$this->api_url = get_option( 'jbros_film_review_anthropic_api_url' );
}
// In includes/api/class-tmdb-api.php
public function __construct() {
$this->api_key = get_option( 'jbros_film_review_tmdb_api_key' );
// If you have a separate URL setting for TMDB API, add it here
}
This approach follows WordPress coding standards and best practices, making it easier to maintain and extend your plugin in the future.
Yes, you need to update the load_dependencies
and define_admin_hooks
methods in the main plugin file to include the class-jbros-film-review-settings.php
file and register the admin hooks for the settings page.
Here’s how you can update the main plugin file:
In the load_dependencies
method, require the class-jbros-film-review-settings.php
file:
/**
* Load the required dependencies.
*/
private function load_dependencies() {
require_once $this->plugin_path . 'includes/api/class-anthropic-api.php';
require_once $this->plugin_path . 'includes/api/class-tmdb-api.php';
require_once $this->plugin_path . 'public/class-jbros-film-review-public.php';
require_once $this->plugin_path . 'public/blocks/blocks.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-post-types.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-settings.php';
}
In the define_admin_hooks
method, initialize an instance of the Jbros_Film_Review_Settings
class and register the necessary admin hooks:
/**
* Register all hooks related to the admin area functionality.
*/
private function define_admin_hooks() {
// Initialize the settings class
$settings = new Jbros_Film_Review_Settings();
// Register the settings page
add_action( 'admin_menu', array( $settings, 'add_settings_page' ) );
}
After making these changes, your plugin will load the class-jbros-film-review-settings.php
file, and the settings page will be available in the WordPress admin area under the “Settings” menu.
The complete structure of your main plugin file should look like this:
<?php
/**
* Plugin Name: Jbros Film Review
* Plugin URI: https://ossi.jalonenbrothers.com/wordpress/jbros-film-review
* Description: A plugin that integrates the Anthropic API with a Gutenberg block for film reviews.
* Version: 1.0.0
* Author: Your Name
* Author URI: https://ossi.jalonenbrothers.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: jbros-film-review
* Domain Path: /languages
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The main plugin class.
*/
class Jbros_Film_Review {
// ... (existing code) ...
/**
* Load the required dependencies.
*/
private function load_dependencies() {
require_once $this->plugin_path . 'includes/api/class-anthropic-api.php';
require_once $this->plugin_path . 'includes/api/class-tmdb-api.php';
require_once $this->plugin_path . 'public/class-jbros-film-review-public.php';
require_once $this->plugin_path . 'public/blocks/blocks.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-post-types.php';
require_once $this->plugin_path . 'includes/class-jbros-film-review-settings.php';
}
/**
* Register all hooks related to the admin area functionality.
*/
private function define_admin_hooks() {
// Initialize the settings class
$settings = new Jbros_Film_Review_Settings();
// Register the settings page
add_action( 'admin_menu', array( $settings, 'add_settings_page' ) );
}
// ... (existing code) ...
}
// ... (existing code) ...
With these changes, your plugin will load the settings class and register the necessary hooks to display the settings page in the WordPress admin area.
The do_settings_sections
function in WordPress is used to render the settings sections and fields registered with the add_settings_section
and add_settings_field
functions.
In your class-jbros-film-review-settings.php
file, you haven’t registered any settings sections or fields, which is why the do_settings_sections(‘jbros-film-review’) function doesn’t render anything.
To add settings sections and fields, you can modify the register_settings
method in the Jbros_Film_Review_Settings
class like this:
/**
* Register plugin settings.
*/
public function register_settings() {
// Register settings
register_setting(
$this->option_group,
'jbros_film_review_anthropic_api_key',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
$this->option_group,
'jbros_film_review_anthropic_api_url',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
$this->option_group,
'jbros_film_review_tmdb_api_key',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
)
);
// Register settings sections and fields
add_settings_section(
'jbros_film_review_api_settings',
'API Settings',
array( $this, 'render_api_settings_section' ),
'jbros-film-review'
);
add_settings_field(
'jbros_film_review_anthropic_api_key',
'Anthropic API Key',
array( $this, 'render_anthropic_api_key_field' ),
'jbros-film-review',
'jbros_film_review_api_settings'
);
add_settings_field(
'jbros_film_review_anthropic_api_url',
'Anthropic API URL',
array( $this, 'render_anthropic_api_url_field' ),
'jbros-film-review',
'jbros_film_review_api_settings'
);
add_settings_field(
'jbros_film_review_tmdb_api_key',
'TMDB API Key',
array( $this, 'render_tmdb_api_key_field' ),
'jbros-film-review',
'jbros_film_review_api_settings'
);
}
Then, add the corresponding methods to render the settings section and fields:
/**
* Render the API settings section.
*/
public function render_api_settings_section() {
echo '<p>Configure the API settings for the JBros Film Review plugin.</p>';
}
/**
* Render the Anthropic API key field.
*/
public function render_anthropic_api_key_field() {
$value = get_option( 'jbros_film_review_anthropic_api_key' );
echo '<input type="text" name="jbros_film_review_anthropic_api_key" value="' . esc_attr( $value ) . '" />';
}
/**
* Render the Anthropic API URL field.
*/
public function render_anthropic_api_url_field() {
$value = get_option( 'jbros_film_review_anthropic_api_url' );
echo '<input type="text" name="jbros_film_review_anthropic_api_url" value="' . esc_attr( $value ) . '" />';
}
/**
* Render the TMDB API key field.
*/
public function render_tmdb_api_key_field() {
$value = get_option( 'jbros_film_review_tmdb_api_key' );
echo '<input type="text" name="jbros_film_review_tmdb_api_key" value="' . esc_attr( $value ) . '" />';
}
With these changes, the do_settings_sections('jbros-film-review')
function will now render the registered settings section and fields on the plugin’s settings page.
The rendered settings page will look something like this:
JBros Film Review Settings
API Settings
Configure the API settings for the JBros Film Review plugin.
Anthropic API Key
[input field]
Anthropic API URL
[input field]
TMDB API Key
[input field]
[Save Changes button]
You can customize the appearance and add more sections and fields as per your requirements.