gatsbyjs / wp-gatsby

WordPress plugin for gatsby-source-wordpress
Other
167 stars 41 forks source link

Unable to create custom action monitor #174

Closed justlevine closed 2 years ago

justlevine commented 3 years ago

As per the docs, a custom action monitor should be created as such:

function some_callback( $object ) {
  $monitor = new \WPGatsby\ActionMonitor\Monitors\ActionMonitor();
  $monitor->log_action( $args );
}

However, Monitors\ActionMonitor requires an instance of WPGatsby\ActionMonitor and instantiating it without one causes a fatal error. But as far as I can tell, there's no way to get the existing instance.

Regardless, the docs need to be updated. But it's also possible that at some point that WPGatsby stopped supporting custom action monitors, and a pr is needed to reimplement the functionality.


For reference: This is where the built-in action monitors are instantiated.. The action/filter gives you access to the array of instantiated monitors, but no access to $this to instantiate your own.

justlevine commented 3 years ago

If a code change is needed here are a few approaches suggested in the slack:

  1. Pass $this to apply_filters( 'gatsby_action_monitors' ) (h/t @alevgal )

  2. Make the instance of WPGatsby/ActionMonitor publicly available. We can convert it to a singleton (h/t @alevgal ) or even just save the instance created in wp-gatsby.php to a static var.

  3. Drop the dependency from WPGatsby/ActionMonitors/Monitors/Monitor. This could be done by replacing the $this->action_monitor calls at the end of log_action() with a do_action, and then hooking them to run from WPGatsby\ActionMonitor's constructor.

alevgal commented 3 years ago

Hi, My goal is to track the ACF options pages updates. So the easy solution is to add this option to AcfMonitor

add_action(
            'acf/save_post',
            function( $id ) {
                if( 'options' === $id ) {
                    $page = isset( $_GET['page'] ) ? $_GET['page'] : 'Options page';
                    $this->trigger_schema_diff(
                        [
                            'title' => $page . ' has been updated',
                        ]
                    );
                }
            }
        );

But when I went into the code to find a solution, I have found gatsby_action_monitors filter, But it doesn't work as the Monitor class requires ActionMonitor instance as argument. So the solution I have tested - Add $this as a second argument to gatsby_action_monitors filter

$this->action_monitors = apply_filters( 'gatsby_action_monitors', $action_monitors, $this );

Create new monitor class

use WPGatsby\ActionMonitor\Monitors\Monitor;

class AcfOptionsMonitor extends Monitor {
    public function init() {
        add_action(
            'acf/save_post',
            function( $id ) {
                if( 'options' === $id ) {
                    $page = isset( $_GET['page'] ) ? $_GET['page'] : 'Options page';
                    $this->trigger_schema_diff(
                        [
                            'title' => $page . ' has been updated',
                        ]
                    );
                }
            }
        );
    }
}

Add new monitor with filter

 add_filter('gatsby_action_monitors', function( $monitors, $action_monitor ) {
            $acfOptionsMonitor = new AcfOptionsMonitor( $action_monitor );
            $acfOptionsMonitor->init();
            $monitors['AcfOptionsMonitor'] = $acfOptionsMonitor;
            return $monitors;
        }, 10, 2);

The only thing - I have a couple option pages, But all updates are added to one action monitor record because of this check So may be I should use log_action function instead of trigger_schema_diff? But what params should I pass?

justlevine commented 3 years ago

The only thing - I have a couple option pages, But all updates are added to one action monitor record because of this check So may be I should use log_action function instead of trigger_schema_diff? But what params should I pass?

The params for the log_action() are basically the same as trigger_schema_diff, except you manually set $args['action_type'] to 'CREATE', 'UPDATE', or 'DELETE', and assumingly the docs example still applies. For what you're describing, use UPDATE.

PS: for the meaningful ids/titles from the Options Page, you can use get_current_screen() (see this thread).

alevgal commented 3 years ago

Will there be a solution to this problem?