I am using an objected oriented design to build a plugin that will use a wp cron job to trigger a function every 10 seconds. However, I cannot get my wp cron job to trigger during this custom period (every 10 seconds).
My custom plugin class has a static activate function that successfully fires when the plugin is activated. This class is set out below.
class Datafetch {
public static function activate() {
update_option( 'rewrite_rules', '' );
require_once( DATAFETCH_PATH . 'schedule/class.datafetch-schedule.php' );
$Datafetch_Schedule = new Datafetch_Schedule();
$args = array();
add_filter( 'cron_schedules', $Datafetch_Schedule->set_seconds($args) );
if (!wp_next_scheduled('task_hook')) {
wp_schedule_event( time(), $args, array( 'Datafetch', 'task_hook' ) );
}
add_action( 'task_hook', $Datafetch_Schedule->begin_fetch_process(),10 );
}
The activate function instantiates the Datafetch_Schedule object. It then uses add_filter to call the method set_seconds, which sets the custom interval and then add_action to trigger the class's method begin_fetch_process. The Datafetch_Schedule class is set out below:
class Datafetch_Schedule{
public function __construct() {
}
public function begin_fetch_process() {
$args = [
'post_title' => 'Post every 10 seconds',
'post_content' => 'Test Post Content',
'post_status' => 'publish'
];
wp_insert_post($args);
}
function set_seconds( $schedules ) {
$schedules['ten_seconds'] = array(
'interval' => 10,
'display' => esc_html__( 'Every 10 Seconds' ), );
return $schedules;
}
}
The result is that one post with the title 'Post every 10 seconds' is posted at the time of the plugin's activation, but it does not post any more times. There is plenty of guidance on how to write a custom schedule, but not much of it centres around the use of classes. If any one can explain how I can successfully use the methods in the Datafetch class, from the main plugin class, to set the custom period and get my plugin to post every 10 seconds then I would be most grateful.
Related
How can I post a post on WordPress through a post request without using the UI?
If possible I would also like to have guidance on how I can implement this with ACF fields.
You could create a child theme or a plugin to write your custom functionality.
You can handle AJAX requests with a specific action, and call wp_insert_post() to create posts.
Example to get you started:
add_action( 'wp_ajax_create_post', 'create_post_ajax_handler' );
/**
* Handle the create post ajax request
*/
function create_post_ajax_handler() {
// Get the post title from the ajax request
// You can get whatever you have passed here
// Also, perform any validations you might want
$post_title = $_POST['post_title'];
// Create the post
$post_id = wp_insert_post( array(
'post_title' => $post_title,
'post_status' => 'publish'
// you could also specify the 'post_type', 'meta_input' etc
), true );
// Error handling
if ( is_wp_error( $post_id ) ) {
// Send error response
wp_send_json_error( $post_id->get_error_message() );
}
// Send success response
wp_send_json_success( $post_id );
}
add_action( 'wp_enqueue_scripts', 'enqueue_ajax_script' );
/**
* Enqueue the ajax script
*/
function enqueue_ajax_script() {
// Enqueue your JavaScript file with 'jquery' as a dependency
wp_enqueue_script(
'ajax-script',
plugin_dir_url( __FILE__ ) . 'ajax-script.js',
array( 'jquery' )
);
// Expose the url to admin-ajax.php as `ajax_object.ajaxurl`
wp_localize_script(
'ajax-script',
'ajax_object',
array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) )
);
}
// Set the url as `ajax_object.ajaxurl` which is the url to admin-ajax.php
$.ajax(ajax_object.ajaxurl, {
method: 'POST',
data: {
// Your action should match the name of your 'wp_ajax_{action}' hook
action: 'create_post',
// Pass any data you want
post_title: 'Example post title'
}
})
.done((response) => {
// Do whatever you want with the response (in this example, this would be the post id)
console.log(response);
})
.fail((error) => {
// Handle the errors
console.error(error);
});
You might also want to look into Nonces, which help protect against Cross-Site Request Forgery (CSRF).
Disclaimer: I haven't tested this code, but I hope you get the idea.
Edit: Since you mentioned that you use Advanced Custom Fields:
$post_id = wp_insert_post( array(
'post_title' => $post_title,
'post_status' => 'publish',
// You can set ACF fields in the 'meta_input' array
'meta_input' => array(
'acf_custom_field_name' => 'an example value'
)
), true );
Edit #2: Please read more about AJAX in WordPress on the Codex.
Replying to your comment:
to which URL should I make the ajax request in order for it to trigger?
On the Codex, under AJAX in Plugins > Ajax on the Viewer-Facing Side
You might also use wp_localize_script() to make the URL available to your script, and generate it using this expression: admin_url( 'admin-ajax.php' )
how do I insert the action "wp_ajax_create_post" in my post request?
On the Codex, AJAX in Plugins > Ajax on the Administration Side
Notice how the 'action' key's value 'my_action', defined in our JavaScript above, matches the latter half of the action 'wp_ajax_my_action' in our AJAX handler below.
After playing around with the Learndash API, I realised it was not possible to get the user progression on the courses he is enrolled to.
I contacted the Learndash support that confirmed it was not possible.
I am new to wordpress dev (I am more familiar with app development), and I would like to know how to implement this feature by myself ? Do I have, for example, to create a custom endpoint ?
I would like to know how to add some 'responses' missing for a plugin API.
What I understand, is that everything from Learndash (courses, topics etc) are like custom posts, so I am guessing it is like adding custom endpoints for posts.
Thanks
I have done this for the course list API. I wanted to remove the "_links" parameter from the response.
I have worked with the object-oriented concept and here is my code:
/* Filter sfwd-courses object */
add_filter( 'rest_prepare_sfwd-courses', array( $this, 'prepare_ld_courses' ), 999, 3 );
public function prepare_ld_courses( $response, $object, $request ) {
/* Remove all links from response */
foreach ( $response->get_links() as $k_l => $v_k ) {
$response->remove_link( $k_l );
}
$data = $response->get_data();
$base_course_id = $data['id'];
$content = array( 'ID' => $course_id, 'parent_id' => (int) $base_course_id, 'title' => $course_obj->post_title, 'description' => $course_obj->post_content, 'cover_image' => null, 'thumbnail' => null);
/* Set thumbnail and cover_image */
$content = EI_Rest_Course::setup_images( $content, $base_course_id );
$response->set_data( $content );
return $response;
}
public static function setup_images( $content, $course_id ) {
/* logic to get course image - $image */
$content['thumbnail'] = $image;
/* logic to get course cover_image - $cover_image */
$content['cover_image'] = $cover_image;
return $content;
}
I'm using WP as a headless CMS with ACF en ACF-2-REST plugins. I've added categories to a post-type and when I make a GET call, it shows me all the information of a particular post including the categories, but only the ID's. If I want to match it, I have to do another call to Categories to get the information of that categories (name, parent etc).
How can I show that information instead of just the ID in a post call?
How the JSON looks now at the /activities call:
{
"id":111,
"date":"2020-01-18T15:39:27",
"date_gmt":"2020-01-18T15:39:27",
"guid":{"rendered":"https:\/\/url.be\/?post_type=activities&p=111"},
"modified":"2020-01-18T15:39:27",
"modified_gmt":"2020-01-18T15:39:27",
"slug":"walking-on-wood",
"status":"publish",
"type":"activities",
"link":"https:\/\/url.be\/activities\/walking-on-wood\/",
"title":{"rendered":"Walking on wood"},
"template":"",
"categories":[14,25,13,2,18,21,6,24],
"acf":{...}
}
What I want to show in the "categories" instead of just the numbers (from the categories call)
{
"id":3,
"count":1,
"description":"",
"link":"https:\/\/url.be\/category\/duration\/lower-than-30-min\/",
"name":"< 30 min.",
"slug":"lower-than-30-min",
"taxonomy":"category",
"parent":2,"meta":[],
"acf":[],
"_links":{"self":[{"href":"https:\/\/url.be\/wp-json\/wp\/v2\/categories\/3"}],
"collection":[{"href":"https:\/\/url.be\/wp-json\/wp\/v2\/categories"}],
"about":[{"href":"https:\/\/url.be\/wp-json\/wp\/v2\/taxonomies\/category"}],
"up":[{"embeddable":true,"href":"https:\/\/url.be\/wp-json\/wp\/v2\/categories\/2"}],
"wp:post_type":[{"href":"https:\/\/url.be\/wp-json\/wp\/v2\/posts?categories=3"},{"href":"https:\/\/url.be\/wp-json\/wp\/v2\/activities?categories=3"}],
"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}
}
Can't find any solution on the internet how I could manipulate the structure of that JSON with a custom function, would appreciate it a lot if someone point me to the right direction. Thanks!
As discussed in the comments section, a solution to this question is to use a custom endpoint method for the WP REST API and perform extra queries in there to get the data you need. This way, you can do all the data manipulation to get the perfect response, resulting in one REST call.
As taken from the official developer docs
Define an endpoint method and add some extra data
<?php
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func', //note that this is the method it will fire
'args' => array(
'id' => array(
'validate_callback' => function($param, $request, $key) {
return is_numeric( $param );
}
),
),
) );
/**
* Grab latest post by an author along with its category!
*
* #param array $data Options for the function.
* #return array Post,
*/
function my_awesome_func( $data ) {
$posts = get_posts( array(
'author' => $data['id'],
) );
if(!empty($posts)) {
//Example of appending extra data
foreach($posts as $post) {
$category = wp_get_post_terms($post->ID, 'category');
$post['category'] = $category;
}
return $posts;
} else {
return new WP_Error( 'no_author', 'Invalid author', array( 'status' => 404 ) );
}
}
I've created a custom wordpress plugin in which I'm defining a custom post type and at one point I'm calling add_action to set custom column in the admin.
The 'manage_[custompostname]_posts_columns' is working great, but the 'manage_[custompostname]_posts_custom_column' do not.
add_filter('manage_bbc_cp_game_posts_columns', bbc_cp_game_table_head');
function bbc_cp_game_table_head( $defaults ) {
$columns = array(
'team_id' => 'Equipe',
'opponent_id' => 'Adversaire',
'gamedatetime' => 'Date / heure',
'score' => 'Score'
);
return $columns;
}
add_action( 'manage_bbc_cp_game_posts_custom_column', 'bbc_cp_game_table_content', 10, 2 );
function bbc_cp_game_table_content( $column, $post_id ) { die('it should work'); }
The second add_action returns true, but the function is never called.
I'd really appreciate if any of you had an idea of what could be the issue, or how to debug it.
Thanks,
I'm trying to figure out a way for members on my Wordpress (Buddypress) site to pick their "favorite movies, books, etc."
It would be nice if, instead of members simply typing a list of these things, they could select from books already in the system, and add more as the please in the future.
I'm hoping that there is an easy answer to this, such as a plugin that I can use, or, at least, modify. Does anyone know of anything that I can look into?
Your title asks how to add a user profile field. Here is the code to add as many fields as you like. Once you add the field, you can easily place additional inputs or options on the custom tab page for users to enter their own favorites.
function my_test_setup_nav() {
global $bp;
$parent_slug = ‘test’;
$child_slug = ‘test_sub’;
//name, slug, screen, position, default subnav
bp_core_new_nav_item( array(‘name’ => __( ‘Test’ ),’slug’ => $parent_slug,’screen_function’ => ‘my_profile_page_function_to_show_screen’,'position’ => 40,’default_subnav_slug’ => $child_slug ) );
/* Add the subnav items to the profile */
// name, slug, parent_url, parent slug, screen function
bp_core_new_subnav_item( array( ‘name’ => __( ‘Home’ ), ‘slug’ => $child_slug, ‘parent_url’ => $bp->loggedin_user->domain . $parent_slug.’/', ‘parent_slug’ => $parent_slug, ‘screen_function’ => ‘my_profile_page_function_to_show_screen’ ) );
bp_core_new_subnav_item( array( ‘name’ => __( ‘Random Page’ ), ‘slug’ => ‘random’, ‘parent_url’ => $bp->loggedin_user->domain . $parent_slug.’/', ‘parent_slug’ => $parent_slug, ‘screen_function’ => ‘my_profile_page_function_to_show_screen234′ ) );
}
function my_profile_page_function_to_show_screen() {
//add title and content here – last is to call the members plugin.php template
add_action( ‘bp_template_title’, ‘my_profile_page_function_to_show_screen_title’ );
add_action( ‘bp_template_content’, ‘my_profile_page_function_to_show_screen_content’ );
bp_core_load_template( apply_filters( ‘bp_core_template_plugin’, ‘members/single/plugins’ ) );
}
function my_profile_page_function_to_show_screen_title() {
echo ‘wptaskforce title’;
}
function my_profile_page_function_to_show_screen_content() {
echo ‘wptaskforce content’;
}
//random page content:
function my_profile_page_function_to_show_screen234() {
//add content here – last is to call the members plugin.php template
add_action( ‘bp_template_content’, ‘my_profile_page_function_to_show_screen234_content’ );
bp_core_load_template( apply_filters( ‘bp_core_template_plugin’, ‘members/single/plugins’ ) );
}
function my_profile_page_function_to_show_screen234_content() {
echo ‘This is a random page.’;
}
add_action( ‘bp_setup_nav’, ‘my_test_setup_nav’ );