PATH:
home
/
centosnipponia
/
public_html
/
nipponiacar
/
wp-content
/
plugins
/
kirki
/
includes
/
Ajax
/
Collaboration
<?php /** * Collaboration controller * * @package kirki */ namespace Kirki\Ajax\Collaboration; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } use Kirki\HelperFunctions; /** * Collaboration class for running and getting the collaboration process. */ class Collaboration { /** * This method will trigger from builder ajax actions. * This method will save all type and action related data inside data column. * * @return void wp_send_json */ public static function save_actions() { // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $data = isset( $_POST['data'] ) ? $_POST['data'] : null; // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended $session_id = HelperFunctions::sanitize_text( isset( $_POST['session_id'] ) ? sanitize_text_field( wp_unslash( $_POST['session_id'] ) ) : '' ); if ( empty( $data ) ) { wp_send_json_error( array( 'message' => 'No data received' ) ); } // Decode the JSON data $data = json_decode( stripslashes( $data ), true ); $results = array(); // Handle both single action and batch of actions if ( isset( $data[0] ) && is_array( $data[0] ) ) { // Batch mode foreach ( $data as $item ) { $parent = isset( $item['parent'] ) ? $item['parent'] : ''; $parent_id = isset( $item['parent_id'] ) ? $item['parent_id'] : ''; $action = isset( $item['action'] ) ? $item['action'] : ''; $status = 1; $result = self::save_action_to_db( $parent, $parent_id, $action, $status, $session_id ); if ( $result ) { $results[] = $result; } } } else { // Single action (backward compatible) $parent = isset( $data['parent'] ) ? $data['parent'] : ''; $parent_id = isset( $data['parent_id'] ) ? $data['parent_id'] : ''; $action = isset( $data['action'] ) ? $data['action'] : ''; $status = 1; $result = self::save_action_to_db( $parent, $parent_id, $action, $status, $session_id ); if ( $result ) { $results[] = $result; } } wp_send_json_success( $results ); } /** * Save action to db function will save a event if more than one people connected. * * @param string $parent post | styleblock for now. * @param string $parent_id post id or 0 if global data. * @param array $data total event data. * @param int $status event status. * * @return bool,array if success. */ public static function save_action_to_db( $parent, $parent_id, $data, $status = 1, $session_id = '', $cleanup = true ) { if ( count( self::get_all_connected_rows( $cleanup ) ) > 1 ) { $user_id = get_current_user_id(); global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $wpdb->prefix . KIRKI_COLLABORATION_TABLE, array( 'user_id' => (int) $user_id, 'session_id' => $session_id, 'parent' => $parent, 'parent_id' => (int) $parent_id, 'data' => wp_json_encode( $data ), 'status' => (int) $status, ), array( '%d', '%s', '%s', '%d', '%s', '%d', ) ); return array( 'id' => $wpdb->insert_id, 'session_id' => $session_id, ); } return false; } /** * Send action is The main eventsouce function. * this method will start the eventsouce mechanism. * * @return void */ public static function send_actions() { self::save_connection_data(); $sender = new Sender(); $sender->start(); self::clean_disconnected_rows(); exit(); } /** * Save connection data */ private static function save_connection_data() { // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated $session_id = HelperFunctions::sanitize_text( sanitize_text_field( wp_unslash( $_GET['session_id'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated $post_id = HelperFunctions::sanitize_text( sanitize_text_field( wp_unslash( $_GET['post_id'] ) ) ); $user_id = get_current_user_id(); if ( ! self::get_connection( $session_id ) ) { self::add_connection( $user_id, $session_id, $post_id ); } } /** * Add connection if a user is give eventsource request. * * @param int $user_id wp user id. * @param string $session_id current user session id. * @param int $post_id current post id. */ private static function add_connection( $user_id, $session_id, $post_id ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery $wpdb->insert( $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected', array( 'user_id' => (int) $user_id, 'post_id' => (int) $post_id, 'session_id' => $session_id, ), array( '%d', '%d', '%s', ) ); if ( $wpdb->insert_id ) { // TODO: send connection id to all connected users for add $this_connection = self::get_connection( $session_id ); $data = array( 'type' => 'COLLABORATION_ADD_CONNECTION', 'payload' => array( 'data' => $this_connection ), ); self::save_action_to_db( 'post', $post_id, $data, 1, $session_id ); return $this_connection; } return false; } /** * Get single connection. * * @param string $session_id current user session id. * * @return bool,array */ public static function get_connection( $session_id ) { global $wpdb; $query = $wpdb->prepare( 'SELECT * FROM %1s WHERE session_id = %s', $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected', $session_id ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $this_connection = $wpdb->get_row( $query ); if ( $this_connection ) { $date = gmdate( 'Y-m-d H:i:s' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->update( $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected', array( 'updated_at' => $date, ), array( 'session_id' => $session_id, ), array( '%s', ), array( '%s', ) ); return self::format_connection_data( $this_connection ); } return false; } /** * Get all connected rows. * first clean disconnected rows then get only recent connected rows. * * @param bool $cleanup if true will clean disconnected rows. * @return array */ public static function get_all_connected_rows( $cleanup = true ) { if ( $cleanup ) { self::clean_disconnected_rows(); } global $wpdb; $query2 = $wpdb->prepare( 'SELECT * FROM %1s', $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $res = $wpdb->get_results( $query2 ); return $res; } public static function get_connected_collaboration_users_list( $post_id ) { global $wpdb; $query = $wpdb->prepare( 'SELECT * FROM %1s WHERE post_id = %d', $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected', $post_id ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $res = $wpdb->get_results( $query ); foreach ( $res as $key => $connection ) { $res[ $key ] = self::format_connection_data( $connection ); } return $res; } private static function format_connection_data( $connection ) { $connection->user_name = get_the_author_meta( 'display_name', $connection->user_id ); return $connection; } /** * Clean disconnected rows if inactive less then 50 seconds. * * @return void */ public static function clean_disconnected_rows() { global $wpdb; $fifty_seconds_ago = gmdate( 'Y-m-d H:i:s', strtotime( '-20 seconds' ) ); $table_name = $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected'; // Get all expired connections (session_id + post_id in one query) $query = $wpdb->prepare( "SELECT session_id, post_id FROM $table_name WHERE updated_at <= %s", $fifty_seconds_ago ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $connections = $wpdb->get_results( $query ); if ( empty( $connections ) ) { return; } // Step 1: Broadcast removal for each connection foreach ( $connections as $connection ) { $data = array( 'type' => 'COLLABORATION_REMOVE_CONNECTION', 'payload' => array( 'session_id' => $connection->session_id ), ); self::save_action_to_db( 'post', $connection->post_id, $data, 1, $connection->session_id, false ); } // Step 2: Bulk delete all expired sessions in one query $session_ids = wp_list_pluck( $connections, 'session_id' ); $placeholders = implode( ',', array_fill( 0, count( $session_ids ), '%s' ) ); $delete_sql = $wpdb->prepare( "DELETE FROM $table_name WHERE session_id IN ($placeholders)", $session_ids ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( $delete_sql ); } /** * Delete connection if a user gives event close request. * * @param string $session_id current user session id. * @param bool $send whether to broadcast removal. */ public static function delete_connection( $session_id ) { global $wpdb; $table_name = $wpdb->prefix . KIRKI_COLLABORATION_TABLE . '_connected'; $query = $wpdb->prepare( "SELECT * FROM $table_name WHERE session_id = %s", $session_id ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared $this_connection = $wpdb->get_row( $query ); if ( $this_connection ) { $post_id = $this_connection->post_id; $data = array( 'type' => 'COLLABORATION_REMOVE_CONNECTION', 'payload' => array( 'session_id' => $session_id ), ); self::save_action_to_db( 'post', $post_id, $data, 1, $session_id ); } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->delete( $table_name, array( 'session_id' => $session_id ) ); } }
[+]
..
[-] Collaboration.php
[edit]
[-] Sender.php
[edit]
[-] .htaccess.disabled
[edit]