'unknown', 'event_trigger' => 'unknown', 'actor_type' => 'unknown', 'actor_id' => null, 'confidence' => 'unknown', ); if ( $expired ) { $r = array( 'source' => 'learndash', 'event_trigger' => 'course_access_expired', 'actor_type' => 'system', 'actor_id' => null, 'confidence' => 'confirmed', ); } elseif ( '' !== $wc_hook ) { // The change ran inside a WooCommerce order hook, so WooCommerce drove it (also for block checkout, which is a REST request). $wc_trigger = 'unknown'; if ( EVLFL_Event::ACTION_ENROLLED === $event['action'] ) { $wc_trigger = 'purchase'; } elseif ( ! empty( $context['reenrolled_in_request'] ) ) { $wc_trigger = 'access_reset'; } elseif ( false !== strpos( $wc_hook, 'refunded' ) ) { $wc_trigger = 'refund'; } $r = array( 'source' => 'woocommerce', 'event_trigger' => $wc_trigger, 'actor_type' => $uid > 0 ? ( $priv ? 'admin' : 'user' ) : 'unknown', 'actor_id' => $uid > 0 ? $uid : null, 'confidence' => 'detected', ); } elseif ( 'cron' === $type ) { $r = array( 'source' => 'cron', 'event_trigger' => 'unknown', 'actor_type' => 'cron', 'actor_id' => null, 'confidence' => 'detected', ); } elseif ( 'wp_cli' === $type ) { $r = array( 'source' => 'wp_cli', 'event_trigger' => 'unknown', 'actor_type' => 'system', 'actor_id' => null, 'confidence' => 'detected', ); } elseif ( 'rest_api' === $type ) { $r = array( 'source' => 'rest_api', 'event_trigger' => 'api', 'actor_type' => 'api', 'actor_id' => $uid > 0 ? $uid : null, 'confidence' => 'detected', ); } elseif ( 'admin' === $type && $priv ) { $r = array( 'source' => 'admin', 'event_trigger' => 'manual', 'actor_type' => 'admin', 'actor_id' => $uid, 'confidence' => 'detected', ); } elseif ( 'ajax' === $type && $priv ) { // An admin-AJAX call by a privileged user: the actor is known, the exact feature is not. $r = array( 'source' => 'admin', 'event_trigger' => 'unknown', 'actor_type' => 'admin', 'actor_id' => $uid, 'confidence' => 'inferred', ); } elseif ( $uid > 0 ) { // A logged-in user acted, but the originating feature (LearnDash form, shop, ...) is not reliably known. $r['actor_type'] = $priv ? 'admin' : 'user'; $r['actor_id'] = $uid; $r['confidence'] = 'inferred'; } $source = apply_filters( 'evlfl_resolve_source', $r['source'], $event, $context ); $r['source'] = $this->allowed( $source, EVLFL_Event::get_sources(), $r['source'] ); $trigger = apply_filters( 'evlfl_resolve_trigger', $r['event_trigger'], $event, $context, $r['source'] ); $r['event_trigger'] = $this->allowed( $trigger, EVLFL_Event::get_triggers(), $r['event_trigger'] ); $actor = apply_filters( 'evlfl_resolve_actor', array( 'actor_type' => $r['actor_type'], 'actor_id' => $r['actor_id'], ), $event, $context ); if ( is_array( $actor ) && isset( $actor['actor_type'] ) ) { $type_ok = $this->allowed( $actor['actor_type'], EVLFL_Event::get_actor_types(), $r['actor_type'] ); $r['actor_type'] = $type_ok; $r['actor_id'] = ( isset( $actor['actor_id'] ) && absint( $actor['actor_id'] ) > 0 ) ? absint( $actor['actor_id'] ) : null; } if ( 'unknown' !== $r['source'] && 'unknown' === $r['confidence'] ) { $r['confidence'] = 'detected'; // A filter supplied a source; it cannot be less than detected. } return $r; } /** * Allowlist helper. * * @param mixed $value Candidate. * @param array $allow Allowlist. * @param string $fallback Fallback. * @return string */ private function allowed( $value, array $allow, $fallback ) { $value = is_scalar( $value ) ? sanitize_key( (string) $value ) : ''; return isset( $allow[ $value ] ) ? $value : $fallback; } }