created. * * @var array */ private static array $logged = array(); public static function is_active(): bool { return Integrations::enabled( self::PLUGIN, class_exists( 'GFForms', false ) ); } public static function event_types(): array { return Forms::event_types(); } public static function register( ?bool $active = null ): void { if ( ! ( $active ?? self::is_active() ) ) { return; } add_action( 'gform_after_save_form', array( __CLASS__, 'log_form_saved' ), 10, 2 ); add_action( 'gform_post_form_duplicated', array( __CLASS__, 'log_form_duplicated' ), 10, 2 ); add_action( 'gform_post_form_activated', array( __CLASS__, 'log_form_activated' ) ); add_action( 'gform_post_form_deactivated', array( __CLASS__, 'log_form_deactivated' ) ); add_action( 'gform_post_form_trashed', array( __CLASS__, 'log_form_trashed' ) ); add_action( 'gform_post_form_restored', array( __CLASS__, 'log_form_restored' ) ); add_action( 'gform_before_delete_form', array( __CLASS__, 'log_form_deleted' ) ); add_action( 'gform_after_submission', array( __CLASS__, 'log_submission' ), 10, 2 ); add_action( 'gform_delete_entry', array( __CLASS__, 'log_entry_deleted' ) ); add_action( 'gform_update_status', array( __CLASS__, 'log_entry_status' ), 10, 3 ); } public static function post_types(): array { return array(); } public static function internal_post_types(): array { return array(); } /** * @param mixed $form The form array. * @param mixed $is_new Whether it was just created. */ public static function log_form_saved( $form, $is_new = false ): void { if ( ! is_array( $form ) ) { return; } $id = isset( $form['id'] ) && is_numeric( $form['id'] ) ? (int) $form['id'] : 0; if ( $id <= 0 || isset( self::$logged[ $id ] ) ) { return; } $created = (bool) $is_new; self::$logged[ $id ] = $created; self::form_row( $created ? Forms::CREATED : Forms::UPDATED, $id, (string) ( $form['title'] ?? '' ), $created ? 'created' : 'updated' ); } /** * @param mixed $form_id The original. * @param mixed $new_id The copy. */ public static function log_form_duplicated( $form_id, $new_id ): void { $new_id = is_numeric( $new_id ) ? (int) $new_id : 0; if ( $new_id <= 0 || isset( self::$logged[ $new_id ] ) ) { return; } self::$logged[ $new_id ] = true; self::form_row( Forms::CREATED, $new_id, self::form_title( $new_id ), 'created as a copy', array( 'duplicated_from' => (int) $form_id ) ); } /** * @param mixed $form_id The form. */ public static function log_form_activated( $form_id ): void { self::form_row( Forms::UPDATED, (int) $form_id, self::form_title( (int) $form_id ), 'activated', array( 'active' => true ) ); } /** * @param mixed $form_id The form. */ public static function log_form_deactivated( $form_id ): void { self::form_row( Forms::UPDATED, (int) $form_id, self::form_title( (int) $form_id ), 'deactivated', array( 'active' => false ) ); } /** * @param mixed $form_id The form. */ public static function log_form_trashed( $form_id ): void { self::form_row( Forms::TRASHED, (int) $form_id, self::form_title( (int) $form_id ), 'moved to trash' ); } /** * @param mixed $form_id The form. */ public static function log_form_restored( $form_id ): void { self::form_row( Forms::RESTORED, (int) $form_id, self::form_title( (int) $form_id ), 'restored from trash' ); } /** * @param mixed $form_id The form, still in the database. */ public static function log_form_deleted( $form_id ): void { self::form_row( Forms::DELETED, (int) $form_id, self::form_title( (int) $form_id ), 'deleted' ); } /** * `gform_after_submission`. Spam is skipped. * * @param mixed $entry The saved entry. * @param mixed $form The form. */ public static function log_submission( $entry, $form ): void { if ( ! is_array( $entry ) || ! is_array( $form ) ) { return; } if ( 'spam' === ( $entry['status'] ?? '' ) ) { return; } $form_id = isset( $form['id'] ) && is_numeric( $form['id'] ) ? (int) $form['id'] : 0; $entry_id = isset( $entry['id'] ) && is_numeric( $entry['id'] ) ? (int) $entry['id'] : 0; Forms::submitted( self::PLUGIN, self::NOUN, $form_id, (string) ( $form['title'] ?? '' ), $entry_id ); } /** * `gform_delete_entry`, before the delete. * * @param mixed $entry_id The entry. */ public static function log_entry_deleted( $entry_id ): void { $entry_id = is_numeric( $entry_id ) ? (int) $entry_id : 0; if ( $entry_id <= 0 ) { return; } $form_id = self::entry_form( $entry_id ); EventLogger::log( Forms::ENTRY_DELETED, sprintf( 'Entry #%1$d of %2$s "%3$s" deleted', $entry_id, self::NOUN, Forms::title( self::form_title( $form_id ), $form_id ) ), 'form_entry', $entry_id, array( 'plugin' => self::PLUGIN, 'form_id' => $form_id, ) ); } /** * `gform_update_status`. * * @param mixed $entry_id The entry. * @param mixed $value The new status. * @param mixed $previous The status before. */ public static function log_entry_status( $entry_id, $value, $previous = '' ): void { $entry_id = is_numeric( $entry_id ) ? (int) $entry_id : 0; $to = Forms::status( $value ); $from = Forms::status( $previous ); if ( $entry_id <= 0 || '' === $to || $from === $to ) { return; } $form_id = self::entry_form( $entry_id ); EventLogger::log( Forms::ENTRY_STATUS, sprintf( 'Entry #%1$d of %2$s "%3$s" marked %4$s', $entry_id, self::NOUN, Forms::title( self::form_title( $form_id ), $form_id ), $to ), 'form_entry', $entry_id, array( 'plugin' => self::PLUGIN, 'form_id' => $form_id, 'from' => $from, 'to' => $to, ) ); } /** * @param string $type Event type. * @param int $form_id The form. * @param string $title Its title. * @param string $verb What happened. * @param array $extra More details. */ private static function form_row( string $type, int $form_id, string $title, string $verb, array $extra = array() ): void { if ( $form_id <= 0 ) { return; } EventLogger::log( $type, sprintf( '%1$s "%2$s" %3$s', self::NOUN, Forms::title( $title, $form_id ), $verb ), 'form', $form_id, array( 'plugin' => self::PLUGIN ) + $extra ); } /** * A form's title through Gravity Forms' own API, or '' when it cannot be * read. * * @param int $form_id The form. */ private static function form_title( int $form_id ): string { if ( $form_id <= 0 || ! is_callable( array( 'GFAPI', 'get_form' ) ) ) { return ''; } $form = call_user_func( array( 'GFAPI', 'get_form' ), $form_id ); return is_array( $form ) && isset( $form['title'] ) && is_string( $form['title'] ) ? $form['title'] : ''; } /** * The form an entry belongs to, or 0. * * @param int $entry_id The entry. */ private static function entry_form( int $entry_id ): int { if ( ! is_callable( array( 'GFAPI', 'get_entry' ) ) ) { return 0; } $entry = call_user_func( array( 'GFAPI', 'get_entry' ), $entry_id ); return is_array( $entry ) && isset( $entry['form_id'] ) && is_numeric( $entry['form_id'] ) ? (int) $entry['form_id'] : 0; } /** Forget the forms logged this request. Tests only. */ public static function reset(): void { self::$logged = array(); } }