Forum Replies Created

Viewing 9 replies - 1 through 9 (of 9 total)
  • Thread Starter huetherb

    (@huetherb)

    You may be able to blindly remove all callbacks to the action from within your callback. remove_all_actions(‘save_post’);

    Wow – I have spent so much time trying to accomplish just that. I hadn’t found such a function and ended up just removing the entries from $wp_filter for tag ‘save_post’ and then returning $wp_filter back to normal after my insert. But will use this function instead!

    Thanks

    Thread Starter huetherb

    (@huetherb)

    Maybe tomorrow something will be clearer to me. I am just not sure what code I could look at that I haven’t already looked at. I have run through debugger, line by line… A course edit page has save_post actions associated with saving meta data. Since I added course meta boxes, I tap into save_post_courses, where I look at meta data so I can do my group insert. But I will try and figure out another hook. I already tried adjusting priorities to see if delaying my hook would have some positive result (which it didn’t), but after I saw how these problematic hooks were actually resulting in the odd behavior (that is, they were not checking post type of passed id since they had no reason to), I realized that it would be tougher to solve than I thought. Anyway, thanks for the patience!

    Brian

    Thread Starter huetherb

    (@huetherb)

    Meant to say, that some of these other hooks that are causing trouble are doing save_post hooks, not save_post_courses hooks – the course plugin’s add_action tag is simply save_post and is called from course edit page.

    I think the reason the plugin does it this way is because it uses one admin function to setup admin pages for various custom content types – course, lesson, quiz. It checks a $this variable and checks for course, lesson, etc. When my wp_insert_post is manually called, this plugin still sees $this and associated data for a course, for instance, which is why it runs its logic twice – not because of AUTO_SAVE.

    The problem gets even worse, because a separate plugin (OneSignal) has a check box on a course edit page and the wp_insert_post that I am doing is triggering the OneSignal hook as well, and because that hook is seeing the POST data that shows its course edit page check box, it is adding meta data for my created group. You can see why this happens since OneSignal does

     public static function on_save_post($post_id, $post, $updated)
        {
            if ($post->post_type == 'wdslp-wds-log') {
                // Prevent recursive post logging
                return;
            }
            /*
                 * We need to verify this came from the our screen and with proper authorization,
                 * because save_post can be triggered at other times.
                 */
            // Check if our nonce is set.
            if (!isset($_POST[OneSignal_Admin::$SAVE_POST_NONCE_KEY])) {
                // This is called on every new post ... not necessary to log it.
                // onesignal_debug('Nonce is not set for post ' . $post->post_title . ' (ID ' . $post_id . ')');
                return $post_id;
            }
    
            $nonce = $_POST[OneSignal_Admin::$SAVE_POST_NONCE_KEY];
    
            // Verify that the nonce is valid.
            if (!wp_verify_nonce($nonce, OneSignal_Admin::$SAVE_POST_NONCE_ACTION)) {
                onesignal_debug('Nonce is not valid for '.$post->post_title.' (ID '.$post_id.')');
    
                return $post_id;
            }
    
            /*
                 * If this is an autosave, our form has not been submitted,
                 * so we don't want to do anything.
                 */
            if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
                return $post_id;
            }
    
            /* OK, it's safe for us to save the data now. */
    
            /* Some WordPress environments seem to be inconsistent about whether on_save_post is called before transition_post_status
               * Check flag in case we just sent a notification for this post (this on_save_post is called after a successful send)
              */
            $just_sent_notification = (get_post_meta($post_id, 'onesignal_notification_already_sent', true) == true);
    
            if ($just_sent_notification) {
                // Reset our flag
                update_post_meta($post_id, 'onesignal_notification_already_sent', false);
                onesignal_debug('A notification was just sent, so ignoring on_save_post. Resetting check flag.');
    
                return;
            }
    
            if (array_key_exists('onesignal_meta_box_present', $_POST)) {
                update_post_meta($post_id, 'onesignal_meta_box_present', true);
                onesignal_debug('Set post metadata "onesignal_meta_box_present" to true.');
            } else {
                update_post_meta($post_id, 'onesignal_meta_box_present', false);
                onesignal_debug('Set post metadata "onesignal_meta_box_present" to false.');
            } 

    All those initial checks give green lights. It sees a nonce from the course edit page. But it doesn’t know that a manual wp_insert_post was called as part of the course save_post hook. This isn’t a plugin problem, so no need for me to contact OneSignal.

    This is just another example of how the wp filter stack can cause odd behavior if a manual wp_insert_post is called from an Update on a different post type’s edit page.

    Not surprising that this problem doesn’t pop up often and moreover I think most people that have this problem are solving it via remove_action calls. I was just hoping for another way ??

    Thread Starter huetherb

    (@huetherb)

    It isn’t a question of what code my hook action is being passed, but rather what other hooks are doing in response to my manually called wp_insert_post.

    In my save_post_courses hook I check for AUTO_SAVE, and know I am being passed a course_id. Regardless if new or updated post, I then check for $_POST data. For instance course_group_name because I added a meta box for courses to allow me to collect group data.

    If $_POST['course_group_name'] is set I execute wp_insert_post() with necessary args to create a post of type group. That adds a save_post hook to the global hook $wp_filter which is why some of the troublesome hooks in question are causing trouble – they just aren’t doing any checks (because they think they have no reason to do so). This is why I think wp should add some controls to its hooks API. For instance, if there is a hook that was set up via array($someclass, ‘some_action’), then why not just check to see if the current context is different from $someclass? Not sure what context would truly mean here, but some way to check “Only fire that hook if the save_post event has same class as $someclass”. Or something similar.

    I looked at the function page and I didn’t see anything that stood out to solve my problem. The problem is that other hooks that I have no control over are not doing any checking. They are admin page hooks that assume the only way they will ever be called is if the post type is the type for the edit page I am on, because they assume that an ‘Update’ key press on course edit page will only be associated with a saved course. Moreover, if any of those hooks check globals they see courses as typenow even when they are passed the group id. I confirmed this behavior by stepping through everything in PHPStorm. I did a remove_action for one hook that I know is firing in response to the group wp_insert_post that I am making and that solved part of my problem, but other hooks are still adding meta data for what they think is a course.

    I truly hope I am missing something! Remember – they key here is that I am manually doing a group wp_insert_postinside a save_post_course hook.

    thanks!
    Brian

    Thread Starter huetherb

    (@huetherb)

    The problem is that the plugin that registers the courses post type has a save_action hook that is not save_post_courses specific, and it doesn’t do any post_type checks because ordinarily the add_action is only done as part of the plugin’s admin editor and so it thinks it is always dealing with courses. Its hook is called 1st time in response to my wp_insert_post. At that point it is passed post_id of the group I created, and in the function call itself it examines $this which is not passed to it, but is available in the class instance. The global $post variable and associated info is all for the course, but it only looks at its class’s $this and sees what it expects to see (not caring if a group post type ID is passed). And global $current_filter is [‘save_post_courses’, ‘save_post_group’]. 2nd time it is called is when indeed post_id is course id. So it is not really recursion – just a sequence of hooks for 2 post types caused by my wp_insert_post. So I am trying to get around this. I think the only current way is to just write an SQL query to insert group, but that assumes no other plugins will ever need to do a hook based on a group save. So that is bad solution. Other solution is for me to look at $wp_filter global, find all save_post entries and do remove_action for each one. That is horrendous solution, forces me to loop through the entries, then figure out which ones are plain callbacks, and which ones are object based, then reattach them. So I think I need to manipulate the $current_filter global variable in some way to get around this. Just not sure how…

    Thread Starter huetherb

    (@huetherb)

    Ok, I will look into group blocks, thanks!

    Thread Starter huetherb

    (@huetherb)

    I guess what I can do then is create an exercise block with block lab, place that block in a section, then use wp.hooks.addFilter on block save, check for block type uagb-section, then check presence of my custom block, and do some modification of the attributes. Just thought of that approach now, will try it out!

    regards,
    Brian

    If you look at what Pods is doing behind the scenes, it is mainly dealing with meta data, taxonomies, all stuff that lends itself to direct query. The Pod is just a data object that has additoinal information about the type of posts the Pod is attached to, etc.

    What I have started doing is just direct querying, since shortcodes tend to not allow complex queries. So I use Pods to facilitate adding custom fields and using them in my posts, but querying using WordPress built in functions.

    So say you have a custom post type called ‘my-type’, a taxonomy called ‘my_taxonomy’ with some terms, and you have custom fields associated with the ‘my-type’ post. You can query pretty much anything you want using WordPress’s built in query builder. For instance

    $args = array(
    ‘post_type’ => ‘my-type’
    ‘order’ => ‘ASC’,
    ‘meta_query’ => array(
    ‘relation’ => ‘AND’,
    array(
    ‘key’ => ‘my_custom_field_1’,
    ‘value’ => ‘SomeVal’,
    ‘compare’ => ‘=’,
    ),
    array(
    ‘key’ => ‘my_custom_field_2’,
    ‘value’ => ‘AnotherVal’,
    ‘compare’ => ‘>’,
    ),
    ),
    ‘tax_query’ => array(
    array(
    ‘taxonomy’ => ‘my_taxonomy’,
    ‘field’ => ‘slug’,
    ‘terms’ => array(‘some_term’,’other_term’),
    ),
    ),
    )
    );

    $selection = new WP_Query($args);

    From that result you would have count. Notice how this approach lets you specify AND or OR relations, etc. With that tax_query you could also specify a relation type and just add as many arrays as you need with the separate taxonomies. And you can add all sorts of additional info like ‘status’, etc.

    So above method is equivalent of telling WordPress “Get all posts of my custom post type (or some standard type), that have custom fields meeting my criteria, and that are attached to taxonomies as I specify.”

    Pretty powerful approach. Notice also that you specify compare methods, so not just equal to, but greater than. So if you added a date field to a post via Pods, you can use this querying approach to, say, get your posts whose ‘my_date_field’ is greater than some date.

    This might look more complicated than it is. But once you get the hang of it, you might find yourself just building queries for whatever you need.

    Viel Spass!

    Brian

    Thread Starter huetherb

    (@huetherb)

    The thing is their support channel is to tell you if there is a development question that you need to hire a developer. Since I have development experience I am posting here since the name of the forum as I recall is something along the lines of “Developing with WordPress”.

    So before I customize this commercial product, I would like to hear from the WordPress developer community (is that not here?) on best practices for the sort of customizing I am looking to do.

    • This reply was modified 5 years, 5 months ago by Jan Dembowski.
Viewing 9 replies - 1 through 9 (of 9 total)