[FRAMEWORK] Xây dựng page Community Phần 2 (ok)

Like Community, Unlike Community

C:\xampp\htdocs\wordpress8\wp-content\themes\addframwork\framework\models\notification.php

<?php
class BJ_notification_Model extends Pv_Controller {
  private $table_notification_name = 'notification';
  public function create_notification($input) {
    global $wpdb;
    $table = $wpdb->prefix . $this->table_notification_name;
    $data  = array(
      "from_"   => $input["from"],
      "to_"     => $input["to"],
      "type"    => $input["type"],
      "content" => $input["content"],
    );
    $format = array('%d', '%d', '%s', '%s');
    $wpdb->insert($table, $data, $format);
    return $wpdb->insert_id;
  }
  public function del_notification_exact($input) {
    global $wpdb;
    $table  = $wpdb->prefix . $this->table_notification_name;
    $result = $wpdb->delete($table, array(
      "from_"   => $input["from"],
      "to_"     => $input["to"],
      "type"    => $input["type"],
      "content" => $input["content"],
    ), array('%d', '%s', '%s', '%s'));
    return $result;
  }
}

C:\xampp\htdocs\wordpress8\wp-content\themes\addframwork\inc\functions\function-global.php

<?php
/**
 *
 * @return HTML - option list tỉnh thành
 */
function reder_province_option($default = "") {
  $json_file = get_stylesheet_directory() . "/json/tinh_tp.json";
  if (file_exists($json_file)) {
    $json       = file_get_contents($json_file);
    $tinh_thanh = json_decode($json, true);
    foreach ($tinh_thanh as $key => $value) {
      if ($key == $default) {$select = "selected";} else { $select = "";}
      echo "<option " . $select . " value='" . $key . "'>" . $value["name"] . "</option>";
    }
  }
}
/**
 * @return HTML - option list quận huyện
 */
function reder_quan_huyen_option($tinh_thanh, $default) {
  $default    = sprintf('%02d', intval($default));
  $tinh_thanh = sprintf('%02d', intval($tinh_thanh));
  $json_file  = get_stylesheet_directory() . "/json/quan-huyen/" . $tinh_thanh . ".json";
  if (file_exists($json_file)) {
    $json       = file_get_contents($json_file);
    $quan_huyen = json_decode($json, true);
    foreach ($quan_huyen as $key => $value) {
      if ($key == $default) {
        $select = "selected";
      } else {
        $select = "";
      }
      echo "<option " . $select . " value='" . $key . "'>" . $value["name_with_type"] . "</option>";
    }
  }
}
/**
 * @return HTML - option list xã phường
 */
function reder_xa_phuong_option($quan_huyen, $default) {
  $default    = intval($default);
  $quan_huyen = sprintf('%03d', intval($quan_huyen));
  $json_file  = get_stylesheet_directory() . "/json/xa-phuong/" . $quan_huyen . ".json";
  if (file_exists($json_file)) {
    $json      = file_get_contents($json_file);
    $xa_phuong = json_decode($json, true);
    foreach ($xa_phuong as $key => $value) {
      if ($key == $default) {$select = "selected";} else { $select = "";}
      echo "<option " . $select . " value='" . $key . "'>" . $value["name_with_type"] . "</option>";
    }
  }
}
/**
 * AJAX load quận huyện khi select tỉnh thành phố
 */
add_action('wp_ajax_load_quan_huyen', 'load_quan_huyen');
function load_quan_huyen() {
  $tinh_thanh = $_POST['id'];
  $type       = $_POST['type'];
  $json_file  = get_stylesheet_directory() . "/json/quan-huyen/" . $tinh_thanh . ".json";
  if (file_exists($json_file)) {
    $json       = file_get_contents($json_file);
    $quan_huyen = json_decode($json, true);
    echo '<option value="" disabled selected >' . __("Select", "golf") . '</option>';
    foreach ($quan_huyen as $key => $value) {
      if ($type) {
        echo "<option value='" . $value["name_with_type"] . "'>" . $value["name_with_type"] . "</option>";
      } else {
        echo "<option value='" . $key . "'>" . $value["name_with_type"] . "</option>";
      }
    }
  }
  die();
}
/**
 * AJAX load danh sách xã phường khi select tỉnh thành phố
 */
add_action('wp_ajax_load_xa_phuong', 'load_xa_phuong');
function load_xa_phuong() {
  $quan_huyen = $_POST['id'];
  $json_file  = get_stylesheet_directory() . "/json/xa-phuong/" . $quan_huyen . ".json";
  if (file_exists($json_file)) {
    $json      = file_get_contents($json_file);
    $xa_phuong = json_decode($json, true);
    foreach ($xa_phuong as $key => $value) {
      echo "<option value='" . $key . "'>" . $value["name_with_type"] . "</option>";
    }
  }
  die();
}
/**
 *
 * Get địa chỉ của user bởi id
 * Nếu chưa update địa chỉ, thì gán mặc định là: '90 Đường Lê Lợi, Phường Bến Thành, Quận 1, Thành phố Hồ Chí Minh'
 */
function get_address_by_id_user($user_id = null) {
  if (!$user_id) {
    $user_id = get_current_user_id();
  }
  $province_address = get_user_meta($user_id, "province_address", true);
  if ($province_address) {
    return json_decode($province_address, true);
  }
  return array(
    'province' => 79,
    'district' => 760,
    'ward'     => 26743,
    'street'   => '90 Đường Lê Lợi',
  );
}
/**
 * Get địa chỉ text
 * @return array
 */
function atw_load_province_address($user_id = null) {
  $province = '';
  $district = '';
  $ward     = '';
  if (!$user_id) {
    $user_id = get_current_user_id();
  }
  $province_address = get_address_by_id_user($user_id);
  if ($province_address && is_array($province_address)) {
    $json_file = get_stylesheet_directory() . "/json/tinh_tp.json";
    if (file_exists($json_file)) {
      $json_tinh_tp = file_get_contents($json_file);
      $tinh_thanh   = json_decode($json_tinh_tp, true);
      foreach ($tinh_thanh as $key => $value) {
        if ($key == $province_address['province']) {
          $province = $tinh_thanh[$key]['name'];
          break;
        }
      }
    }
    if ($province_address['province']):
      $json_file = get_stylesheet_directory() . "/json/quan-huyen/" . $province_address['province'] . ".json";
      if (file_exists($json_file)) {
        $json_quan_huyen = file_get_contents($json_file);
        $quan_huyen      = json_decode($json_quan_huyen, true);
        foreach ($quan_huyen as $key => $value) {
          if ($key == $province_address['district']) {
            $district = $quan_huyen[$key]['name_with_type'];
            break;
          }
        }
      }
    endif;
    if ($province_address['district']):
      $json_file = get_stylesheet_directory() . "/json/xa-phuong/" . $province_address['district'] . ".json";
      if (file_exists($json_file)) {
        $json_xa_phuong = file_get_contents($json_file);
        $xa_phuong      = json_decode($json_xa_phuong, true);
        foreach ($xa_phuong as $key => $value) {
          if ($key == $province_address['ward']) {
            $ward = $xa_phuong[$key]['name_with_type'];
            break;
          }
        }
      }
    endif;
  }
  return array(
    'province' => $province,
    'district' => $district,
    'ward'     => $ward,
    'street'   => $province_address['street'],
  );
}
/**
 *
 * Crop image
 */
function resize_image($method, $image_loc, $new_loc, $width, $height) {
  $exif = exif_read_data($image_loc);
  if (isset($exif['Orientation']) && $exif['Orientation'] === 6) {
    $rotate = -90;
  } else if (isset($exif['Orientation']) && $exif['Orientation'] === 3) {
    $rotate = 180;
  } else if (isset($exif['Orientation']) && $exif['Orientation'] === 8) {
    $rotate = 90;
  }
  if (!is_array(@$GLOBALS['errors'])) {$GLOBALS['errors'] = array();}
  if (!in_array($method, array('force', 'max', 'crop'))) {$GLOBALS['errors'][] = 'Invalid method selected.';}
  if (!$image_loc) {$GLOBALS['errors'][] = 'No source image location specified.';} else {
    if ((substr(strtolower($image_loc), 0, 7) == 'http://') || (substr(strtolower($image_loc), 0, 7) == 'https://')) { /*don't check to see if file exists since it's not local*/} elseif (!file_exists($image_loc)) {$GLOBALS['errors'][] = 'Image source file does not exist.';}
    $extension = strtolower(substr($image_loc, strrpos($image_loc, '.')));
    if (!in_array($extension, array('.jpg', '.jpeg', '.png', '.gif', '.bmp'))) {$GLOBALS['errors'][] = 'Invalid source file extension!';}
  }
  if (!$new_loc) {$GLOBALS['errors'][] = 'No destination image location specified.';} else {
    $new_extension = strtolower(substr($new_loc, strrpos($new_loc, '.')));
    if (!in_array($new_extension, array('.jpg', '.jpeg', '.png', '.gif', '.bmp'))) {$GLOBALS['errors'][] = 'Invalid destination file extension!';}
  }
  $width = abs(intval($width));
  if (!$width) {$GLOBALS['errors'][] = 'No width specified!';}
  $height = abs(intval($height));
  if (!$height) {$GLOBALS['errors'][] = 'No height specified!';}
  if (count($GLOBALS['errors']) > 0) {echo_errors();return false;}
  if (in_array($extension, array('.jpg', '.jpeg'))) {$image = @imagecreatefromjpeg($image_loc);} elseif ($extension == '.png') {$image = @imagecreatefrompng($image_loc);} elseif ($extension == '.gif') {$image = @imagecreatefromgif($image_loc);} elseif ($extension == '.bmp') {$image = @imagecreatefromwbmp($image_loc);}
  if (!$image) {$GLOBALS['errors'][] = 'Image could not be generated!';} else {
    $current_width  = imagesx($image);
    $current_height = imagesy($image);
    if ((!$current_width) || (!$current_height)) {$GLOBALS['errors'][] = 'Generated image has invalid dimensions!';}
  }
  if (count($GLOBALS['errors']) > 0) {
    @imagedestroy($image);
    echo_errors();return false;}
  if ($method == 'force') {$new_image = resize_image_force($image, $width, $height);} elseif ($method == 'max') {$new_image = resize_image_max($image, $width, $height);} elseif ($method == 'crop') {$new_image = resize_image_crop($image, $width, $height);}
  if ((!$new_image) && (count($GLOBALS['errors'] == 0))) {$GLOBALS['errors'][] = 'New image could not be generated!';}
  if (count($GLOBALS['errors']) > 0) {
    @imagedestroy($image);
    echo_errors();return false;}
  $save_error = false;
  if (in_array($extension, array('.jpg', '.jpeg'))) {
    if (isset($rotate)) {$new_image = imagerotate($new_image, $rotate, 0);}
    imagejpeg($new_image, $new_loc) or ($save_error = true);} elseif ($extension == '.png') {
    if (isset($rotate)) {$new_image = imagerotate($new_image, $rotate, 0);}
    imagepng($new_image, $new_loc) or ($save_error = true);} elseif ($extension == '.gif') {imagegif($new_image, $new_loc) or ($save_error = true);} elseif ($extension == '.bmp') {imagewbmp($new_image, $new_loc) or ($save_error = true);}
  if ($save_error) {$GLOBALS['errors'][] = 'New image could not be saved!';}
  if (count($GLOBALS['errors']) > 0) {
    @imagedestroy($image);@imagedestroy($new_image);
    echo_errors();return false;}
  imagedestroy($image);
  imagedestroy($new_image);
  return true;
}
function echo_errors() {
  if (!is_array(@$GLOBALS['errors'])) {$GLOBALS['errors'] = array('Unknown error!');}
  foreach ($GLOBALS['errors'] as $error) {echo '<p style="color:red;font-weight:bold;">Error: ' . $error . '</p>';}
}
function resize_image_force($image, $width, $height) {
  $w = @imagesx($image); //current width
  $h = @imagesy($image); //current height
  if ((!$w) || (!$h)) {$GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.';return false;}
  if (($w == $width) && ($h == $height)) {return $image;} //no resizing needed
  $image2 = imagecreatetruecolor($width, $height);
  imagecopyresampled($image2, $image, 0, 0, 0, 0, $width, $height, $w, $h);
  return $image2;
}
function resize_image_max($image, $max_width, $max_height) {
  $w = imagesx($image); //current width
  $h = imagesy($image); //current height
  if ((!$w) || (!$h)) {$GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.';return false;}
  if (($w <= $max_width) && ($h <= $max_height)) {return $image;} //no resizing needed
  //try max width first...
  $ratio = $max_width / $w;
  $new_w = $max_width;
  $new_h = $h * $ratio;
  //if that didn't work
  if ($new_h > $max_height) {
    $ratio = $max_height / $h;
    $new_h = $max_height;
    $new_w = $w * $ratio;
  }
  $new_image = imagecreatetruecolor($new_w, $new_h);
  imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);
  return $new_image;
}
function resize_image_crop($image, $width, $height) {
  $w = @imagesx($image); //current width
  $h = @imagesy($image); //current height
  if ((!$w) || (!$h)) {$GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.';return false;}
  if (($w == $width) && ($h == $height)) {return $image;} //no resizing needed
  //try max width first...
  $ratio = $width / $w;
  $new_w = $width;
  $new_h = $h * $ratio;
  //if that created an image smaller than what we wanted, try the other way
  if ($new_h < $height) {
    $ratio = $height / $h;
    $new_h = $height;
    $new_w = $w * $ratio;
  }
  $image2 = imagecreatetruecolor($new_w, $new_h);
  imagecopyresampled($image2, $image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);
  //check to see if cropping needs to happen
  if (($new_h != $height) || ($new_w != $width)) {
    $image3 = imagecreatetruecolor($width, $height);
    if ($new_h > $height) {
      //crop vertically
      $extra = $new_h - $height;
      $x     = 0; //source x
      $y     = round($extra / 2); //source y
      imagecopyresampled($image3, $image2, 0, 0, $x, $y, $width, $height, $width, $height);
    } else {
      $extra = $new_w - $width;
      $x     = round($extra / 2); //source x
      $y     = 0; //source y
      imagecopyresampled($image3, $image2, 0, 0, $x, $y, $width, $height, $width, $height);
    }
    imagedestroy($image2);
    return $image3;
  } else {
    return $image2;
  }
}
function upload_image($file) {
  $targetDir      = wp_upload_dir()["basedir"] . '/image-files/';
  $allowTypes     = array('jpg', 'png', 'jpeg');
  $fileName       = round(microtime(true)) . "_" . basename($file['name']);
  $targetFilePath = $targetDir . $fileName;
  // Check whether file type is valid
  $fileType = pathinfo($targetFilePath, PATHINFO_EXTENSION);
  if (in_array($fileType, $allowTypes)) {
    if ($file["size"] > 10000000) {
      return array("status" => "error", "content" => "Maximum 10Mb");
    }
    if (move_uploaded_file($file['tmp_name'], $targetFilePath)) {
      resize_image('crop', $targetDir . $fileName, $targetDir . '200x200/' . $fileName, 200, 200);
      $file_id = umm_model_insert_img($fileName);
      return array("status" => "success", "content" => $file_id);
    }
  } else {
    return array("status" => "error", "content" => "Allow jpg, png, jpeg");
  }
}
function umm_model_insert_img($file_name) {
  global $wpdb;
  $table  = $wpdb->prefix . 'images';
  $data   = array('image_name' => $file_name, 'user_id' => get_current_user_id());
  $format = array('%s', '%d');
  $wpdb->insert($table, $data, $format);
  return $wpdb->insert_id;
}
function get_image_url_by_id($id, $size = "full") {
  $url = wp_get_upload_dir()["baseurl"] . "/image-files/";
  if ($size != "full") {
    $url = wp_get_upload_dir()["baseurl"] . "/image-files/200x200/";
  }
  global $wpdb;
  $table  = $wpdb->prefix . "images";
  $result = $wpdb->get_results($wpdb->prepare(" SELECT image_name  FROM  {$table} WHERE id = %d ", $id), ARRAY_A, 1);
  return $url . $result[0]["image_name"];
}
/**
 *
 * Delete uploaded images file, database
 */
function delete_img_by_id($img_id) {
  global $wpdb;
  $table     = $wpdb->prefix . "images";
  $result    = $wpdb->get_results($wpdb->prepare(" SELECT image_name  FROM  {$table} WHERE id = %d ", $img_id), ARRAY_A, 1);
  $file_name = $result[0]["image_name"];
  $folder    = wp_upload_dir()["basedir"] . '/image-files/';
  unlink($folder . $file_name);
  unlink($folder . "200x200/" . $file_name);
  $wpdb->delete($table, array('id' => $img_id), array('%d'));
}
/**
 *
 * Get image url avatar  by user id
 */
function get_url_avatar($user_id = '') {
  if ($user_id === '') {
    $user_id = get_current_user_id();
  }
  $id_avatar = get_user_meta($user_id, 'id_img_avatar', true);
  if ($id_avatar) {
    return get_image_url_by_id($id_avatar, 'thumbnail');
  }
  return AVATAR_DF;
}
/**
 *
 * Check user exists
 * @return boolean
 */
function is_user_exist($user_id) {
  $user       = get_userdata($user_id);
  $user_roles = !empty($user) ? $user->roles[0] : "";
  if ($user === false or $user_roles != USER) {
    return false;
  } else {
    return true;
  }
}
/**
 *
 * Check View other account
 * @return boolean
 */
function is_view_other_account() {
  if (is_page('account') && isset($_GET['id']) && intval($_GET['id']) !== get_current_user_id()) {
    return true;
  }
  return false;
}
/**
 *
 * Get list user follow
 * @return array
 */
function list_user_follow($user_id = null) {
  if (!$user_id) {
    $user_id = get_current_user_id();
  }
  $list_user_follow = get_user_meta($user_id, 'list_user_follow', true);
  if (!$list_user_follow) {
    return array();
  }
  return json_decode($list_user_follow, true);
}
/**
 *
 * Nhận danh sách người theo dõi tôi
 * @return array
 */
function get_list_follower($current_user_id = null) {
  if (!$current_user_id) {
    $current_user_id = get_current_user_id();
  }
  $args              = array('role' => USER);
  $users             = get_users($args);
  $list_follower_arr = [];
  foreach ($users as $value) {
    $user_id         = $value->ID;
    $list_follow_arr = list_user_follow($user_id);
    if ($list_follow_arr):
      if (in_array($current_user_id, $list_follow_arr)) {
        $list_follower_arr[] = $user_id;
      }
    endif;
  }
  return $list_follower_arr;
}
/**
 *
 * Nhận tổng số người tôi đang theo dõi
 * @return int
 */
function get_total_following($current_user_id = null) {
  if (!$current_user_id) {
    $current_user_id = get_current_user_id();
  }
  return count(list_user_follow($current_user_id));
}
/**
 * tăng lên 1 so tổng thông báo mới hiện tại của user ID
 */
function update_total_notify_user($user_id){
  $total = (int)get_user_meta( $user_id, 'total_notify', true ) + 1;
  update_user_meta( $user_id, 'total_notify', $total);
}
// ==
function get_market_image_url($img_id){
  $url = wp_get_upload_dir()["baseurl"]."/market-images/";
  global $wpdb;
  $table = $wpdb->prefix."bj_market_image";
  $result = $wpdb->get_results ( $wpdb->prepare(" SELECT image_name FROM  {$table} WHERE id = %d ",$img_id) ,ARRAY_A  );
  if(!empty($result)){
    return $url."__".$result[0]["image_name"];
  }else{
    return THEME_URL."assets/images/default.jpg";
  }
}
function market_upload_image($file){
  $targetDir = wp_upload_dir()["basedir"].'/market-images/'; 
  $allowTypes = array( 'jpg', 'png', 'jpeg'); 
  $fileName = round(microtime(true))."_".basename($file['name']);
  $targetFilePath = $targetDir.$fileName; 
    // Check whether file type is valid 
  $fileType = pathinfo($targetFilePath, PATHINFO_EXTENSION); 
  if(in_array($fileType, $allowTypes)){ 
    if($file["size"] > 5000000) return array("status" => "error","content" => "Maximum 5Mb");
    if(move_uploaded_file($file['tmp_name'], $targetFilePath)){ 
      $result = resize_image('max',$targetDir.$fileName,$targetDir.'__'.$fileName,600,4000);
      if($result == true){
        $file_id = add_market_image_to_db($fileName);
        unlink($targetDir.$fileName);
        return array("status" => "success","content" => $file_id);
      }
    }else{
      return array("status" => "error","content" => "Unknow");
    } 
  }else{
    return array("status" => "error","content" => "Allow jpg, png, jpeg");
  }
}
function add_market_image_to_db($file_name){
  global $wpdb;
  $table = $wpdb->prefix."bj_market_image";
  $wpdb->insert($table,
    array("image_name" => $file_name),
    array("%s")
  );
  return $wpdb->insert_id;
}
/**
 * Like Post Community
 */
add_action( 'wp_ajax_like_post', 'like_post' );
function like_post(){
  $current_user_id = get_current_user_id();
  if( !isset( $_POST['token']) or !wp_verify_nonce($_POST['token'],AT_NONCE_KEY.$current_user_id)) die("Token");
  $post_id = $_POST['post_id'];
  $author_is_post = $_POST['author'];
  $current_list_like_post_arr = json_decode( get_post_meta($post_id,"list_user_like",true),true );
  if(empty($current_list_like_post_arr)) $current_list_like_post_arr = [];
  if (!in_array($current_user_id, $current_list_like_post_arr)) {
    array_push($current_list_like_post_arr,$current_user_id);
    update_post_meta($post_id,"list_user_like",json_encode($current_list_like_post_arr));
    if ($current_user_id != $author_is_post) {
      global $bj_controller;
      $model = $bj_controller->Model("notification");
      $id = $model->create_notification(
        array(
          "from" => $current_user_id,
          "to" => $author_is_post,
          "type" => "has_like",
          "content" => $post_id,
        )
      );
      if ($id) update_total_notify_user($author_is_post);
    }
  }
  echo count(json_decode( get_post_meta($post_id,"list_user_like",true),true ));
  wp_die();
}
/**
 * DisLike Post Community
 */
add_action( 'wp_ajax_dislike_post', 'dislike_post' );
function dislike_post(){
  $current_user_id = get_current_user_id();
  $post_id = $_POST['post_id'];
  $author_is_post = $_POST['author'];
  if( !isset( $_POST['token']) or !wp_verify_nonce($_POST['token'],AT_NONCE_KEY.$current_user_id)) die("Token");
  $current_list_like_post_arr = json_decode( get_post_meta($post_id,"list_user_like",true),true );
  if (($key = array_search($current_user_id, $current_list_like_post_arr)) !== false) {
    unset($current_list_like_post_arr[$key]);
    global $bj_controller;
    $model = $bj_controller->Model("notification");
    $result = $model->del_notification_exact(
      array(
        "from" => $current_user_id,
        "to" => $author_is_post,
        "type" => "has_like",
        "content" => $post_id,
      )
    );
  }
  update_post_meta($post_id,"list_user_like",json_encode($current_list_like_post_arr));
  echo count(json_decode( get_post_meta($post_id,"list_user_like",true),true ));
  wp_die();
}

C:\xampp\htdocs\wordpress8\wp-content\themes\addframwork\js\frontend.js

function replaceUrlParam(url, paramName, paramValue) {
  var href = new URL(url);
  href.searchParams.set(paramName, paramValue);
  return href.toString();
}
jQuery(document).ready(function($) {
  $('.menu-tab .tab-a').click(function(e) {
    e.preventDefault();
    $('.menu-tab li').removeClass('active')
    $(".tab").removeClass('tab-active');
    $(".tab[data-tab-id='" + $(this).attr('data-id') + "']").addClass("tab-active");
    $(".tab-a").removeClass('active');
    $(this).parent().addClass('active');
  });
  $('body').on('click', '.show-hiden', function(e) {
    const isInput = $(this).prev();
    const typeAttr = isInput.attr("type");
    if (typeAttr == 'password') {
      isInput.attr("type", "text");
      $(this).text('Hidden');
    } else {
      isInput.attr("type", "password");
      $(this).text('Show');
    }
  });
  // Load danh sách tỉnh thành
  $("body").on("change", ".province-select", function(e) {
    $(".ward-select").html("");
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'load_quan_huyen',
        id: $(this).val(),
      },
      beforeSend: function() {
        $(".district-select").prop("disabled", true);
      },
      success: function(output) {
        $(".district-select").html(output);
        $(".district-select").prop("disabled", false);
      },
    });
  });
  // Load danh sách xã phường
  $("body").on("change", ".district-select", function() {
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'load_xa_phuong',
        id: $(this).val(),
      },
      beforeSend: function() {
        $(".ward-select").prop("disabled", true);
      },
      success: function(output) {
        $(".ward-select").html(output);
        $(".ward-select").prop("disabled", false);
      },
    });
  });
  // Preview avatar upload
  const inputImg = $('input#image-avatar')
  const imgPreview = $('#preview-img')
  $('body').on('click', '.btn-upload', (e) => {
    inputImg.click();
  })
  $('.box-preview-img').on('change', inputImg, function(e) {
    const file = e.target.files[0]
    const reader = new FileReader();
    reader.onload = function(e) {
      imgPreview.attr('src', e.target.result);
    }
    reader.readAsDataURL(file);
  })
  // add follow
  $('body').on('click', 'button.btn-follow__add', function(e) {
    e.preventDefault();
    const $this = $(this);
    const user_id = $this.data('id');
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'app_add_follow',
        token: $('#nonce_token').val(),
        id: user_id,
      },
      beforeSend: function() {
        $this.addClass('loading');
      },
      success: function(response) {
        $this.removeClass('loading')
        if (response == true) {
          $this.text(app.unfollow);
          $this.removeClass('btn-follow__add');
          $this.addClass('btn-follow__remove');
        }
      },
      error: function() {
        $this.removeClass('loading');
        alert('Error');
      }
    });
  });
  // Unfollow
  $('body').on('click', 'button.btn-follow__remove', function(e) {
    e.preventDefault();
    const $this = $(this);
    const user_id = $this.data('id');
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'app_un_follow',
        token: $('#nonce_token').val(),
        id: user_id,
      },
      beforeSend: function() {
        $this.addClass('loading');
      },
      success: function(response) {
        $this.removeClass('loading')
        if (response == true) {
          $this.text(app.follow);
          $this.removeClass('btn-follow__remove');
          $this.addClass('btn-follow__add');
        }
      },
      error: function() {
        $this.removeClass('loading');
        alert('Error');
      }
    });
  });
  $("body").on("click", "a.posts__item__like", function(e) {
    var $this = $(this);
    e.preventDefault();
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'like_post',
        token: $(this).data("token"),
        post_id: $(this).data("post-id"),
        author: $(this).data("author"),
      },
      beforeSend: function() {
        $this.addClass('no-click');
      },
      success: function(response) {
        $this.removeClass('posts__item__like');
        $this.addClass('posts__item__dislike');
        $this.removeClass('no-click');
        $this.find('.posts__item__like__count').text(response);
      },
      error: function() {
        alert('error');
      }
    });
  });
  $("body").on("click", "a.posts__item__dislike", function(e) {
    var $this = $(this);
    e.preventDefault();
    $.ajax({
      url: app.ajaxUrl,
      type: "post",
      dataType: "text",
      data: {
        action: 'dislike_post',
        token: $(this).data("token"),
        post_id: $(this).data("post-id"),
        author: $(this).data("author"),
      },
      beforeSend: function() {
        $this.addClass('no-click');
      },
      success: function(response) {
        $this.removeClass('posts__item__dislike');
        $this.addClass('posts__item__like');
        $this.removeClass('no-click');
        $this.find('.posts__item__like__count').text(response);
      },
      error: function() {
        alert('error');
      }
    });
  });
});
// add multiple images delete option
jQuery(document).ready(function($) {
  var xp = 0;
  var input_btn = 0;
  var dts = [];
  var l = $(".at-gr-input-file"),
    t = $(".form-group.list_attach");
  function cl() {
    $(".form-group", l).length <= 5 && 0 <= $(".form-group", l).length ? t.addClass("show-btn") : t.removeClass("show-btn");
  }
  $(document).on("click", ".at-add-image-btn", function(e) {
    //cl();
    let leg_current = $(".at-gr-input-file .at-form-group").length;
    if (leg_current >= 6) {
      alert("Maximum 6 images");
      return;
    } else {
      input_btn++;
      $(".list_input").append(
        "<input type='file' style='display:none;' name='upload_files[]' id='filenumber" +
        input_btn +
        "' class='img_file upload_files' accept='.gif,.jpg,.jpeg,.png,' multiple/>"
      );
      $("#filenumber" + input_btn).click();
    }
  });
  $(document).on("change", ".upload_files", function(e) {
    $('.btn-upload').addClass('hidden');
    let leg_current = $(".at-gr-input-file .at-form-group").length;
    files = e.target.files;
    filesLength = files.length;
    if (filesLength + leg_current >= 7) {
      alert("Maximum 6 images");
      return
    }
    for (var i = 0; i < filesLength; i++) {
      xp++;
      var f = files[i];
      var res_ext = files[i].name.split(".");
      var img_or_video = res_ext[res_ext.length - 1];
      var fileReader = new FileReader();
      fileReader.name = f.name;
      fileReader.onload = function(e) {
        var file = e.target;
        $(".at-gr-input-file").append(
          "<div class='at-form-group at-form-group" +
          xp +
          "'><i deltsid='" + 0 + "' data-title='" + file.name + "' class='cancel_mutile_image fa fa-times at-remove-input' title='Remove' aria-hidden='true'><svg width='40' height='41'><use href='#icon-close'></use></svg></i><div class='at_item_image background_v" +
          xp +
          "' style='background-image: url(" +
          e.target.result +
          ")'></div></div>"
        );
      };
      fileReader.readAsDataURL(f);
    }
  });
  var rty = 0;
  $(document).on("click", ".cancel_mutile_image.at-remove-input", function(e) {
    $('.cancel_mutile_image').each(function() {
      chk_id = $(this).attr('deltsid');
      if (chk_id == 0) {
        rty++;
        $(this).attr('deltsid', rty);
      }
    });
    //deltsid = $(this).attr('data-title');
    deltsid = $(this).attr('deltsid');
    dts.push(deltsid);
    $(this).closest(".at-form-group").remove();
    $('#remove_image_title').val(dts);
    //cl();
  });
  // delete image update post
  var arr_img_delete = [];
  $(".single").on("click", ".remove-img", function(e) {
    var data_id = $(this).data('id-img');
    arr_img_delete.push(data_id);
    $(this).parent(".at-form-group").remove();
    $('#remove_image').val(arr_img_delete);
  });
});

C:\xampp\htdocs\wordpress8\wp-content\themes\addframwork\single-community.php

<?php get_header();?>
<?php  
  $post_id = get_the_ID();
  $author_id = $post->post_author;
  $current_user = wp_get_current_user();
  $id_user_current = get_current_user_id();
  $is_author = false;
  $url_back = SITE_URL . '?appt=X';
  if ($author_id == $id_user_current ){
    $is_author = true;
    $url_back .= '&data=' . $post_id;
  }
?>
<div class="page-community single-community container mt-4">
  <div class="d-flex align-items-center justify-content-between action-sigle position-relative mb-4">
    <a href="<?php echo $url_back ?>" class="btn btn-bank d-flex align-items-center p-0">
      <svg width="20" height="20">
        <use href="#icon-back"></use>
      </svg>
    </a>
    <?php if ($author_id == $id_user_current) : ?>
      <div class="dropdown">
        <a class="btn" href="#" id="dropdownAction" data-bs-toggle="dropdown">
          <svg width="16" height="5">
            <use href="#icon-dots"></use>
          </svg>
        </a>
        <ul class="dropdown-menu" aria-labelledby="dropdownAction">
          <li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#ModalEdit"> <?php _e('Edit post', 'umm'); ?> </a></li>
          <li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#modelDeletePost"> <?php _e('Delete', 'umm'); ?> </a></li>
        </ul>
      </div>
    <?php endif ?>
  </div>
  <div class="list-posts__item" data-post-id="<?php echo $post_id; ?>">
    <div class="list-posts__item__head d-flex align-items-center justify-content-start">
        <a href="<?php echo SITE_URL ?>account?id=<?php echo $author_id; ?>&appt=N" class="d-block">
          <img src="<?php echo get_url_avatar($author_id); ?>" class="rounded-circle" width="35" height="35">
        </a>
        <div class="list-posts__item__name ml-2">
          <div class="d-flex align-items-center">
            <div class="user_name font-weight-600">
              <?php echo get_the_author_meta('display_name', $author_id); ?>
            </div>
            <div class="mx-1"> in </div>
            <div class="post_address font-weight-600">
              <?php echo wp_strip_all_tags(get_the_excerpt(), true); ?>
            </div>
          </div>
          <div class="post-date">
            <?php the_time('l, j F, Y'); ?>
          </div>
        </div>
    </div>
    <div class="list-posts__item__content mt-2">
      <?php the_content(); ?>
      <div class="box-image">
        <?php if (get_post_meta($post_id, 'img_single_community', true)) : ?>
          <?php  
            $list_images_post_arr = json_decode(get_post_meta($post_id, "img_single_community", true), true);
            $count_images = count($list_images_post_arr);
            if ($count_images == 1) {
                echo '<a href="' . get_image_url_by_id(reset($list_images_post_arr)) . '" data-fancybox>';
                echo '<img class="thumb w-100" src="' . get_image_url_by_id(reset($list_images_post_arr)) . '" /></a>';
            } else {
              echo '<div class="grid grid-cols-2">';
                foreach ($list_images_post_arr as $key => $value) {
                  echo '<a href="' . get_image_url_by_id($value) . '" data-fancybox="gallery-' . $post_id . '">';  
                  echo '<img class="thumb w-100" src="' . get_image_url_by_id($value, 'thumbnail') . '" /></a>';
                }
              echo '</div>';
            }
          ?>
        <?php endif ?>
      </div>
    </div>
    <?php
      $list_like_post_arr = !empty(get_post_meta(get_the_ID(), "list_user_like", true)) ? json_decode(get_post_meta(get_the_ID(), "list_user_like", true), true) : [];
      if (!in_array($id_user_current, $list_like_post_arr)) {
        $class = "posts__item__like";// ajax-nonce
      } else {
        $class = "posts__item__dislike";
      }
      $count_like = count($list_like_post_arr);
      ?>
      <div class="list-posts__item__act d-flex align-items-center justify-content-center my-2">
        <a href="#" data-post-id="<?php echo get_the_ID(); ?>" data-author="<?php echo $author_id ?>" data-token="<?php echo wp_create_nonce(AT_NONCE_KEY . $id_user_current) ?>" class="<?php echo $class ?> flex-fill d-flex align-items-center justify-content-center p-2">
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M13.9205 2.19948C13.5784 1.81921 13.1722 1.51755 12.7252 1.31174C12.2782 1.10593 11.799 1 11.3151 1C10.8312 1 10.3521 1.10593 9.90504 1.31174C9.45801 1.51755 9.05185 1.81921 8.70976 2.19948L7.99982 2.9883L7.28988 2.19948C6.5989 1.43172 5.66172 1.0004 4.68453 1.0004C3.70733 1.0004 2.77016 1.43172 2.07917 2.19948C1.38819 2.96724 1 4.00854 1 5.09432C1 6.18009 1.38819 7.22139 2.07917 7.98915L2.78911 8.77798L7.99982 14.5677L13.2105 8.77798L13.9205 7.98915C14.2627 7.60906 14.5342 7.15777 14.7194 6.66107C14.9047 6.16436 15 5.63197 15 5.09432C15 4.55666 14.9047 4.02427 14.7194 3.52757C14.5342 3.03086 14.2627 2.57957 13.9205 2.19948Z" fill="#808080" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
          </svg>
          <div class="posts__item__like__count ml-1"> <?php echo $count_like ?> </div>
        </a>
        <div class="v-line"></div>
        <a href="javascript:void(0)" class="posts__item__comment flex-fill d-flex align-items-center justify-content-center p-2">
          <svg width="16" height="16">
            <use href="#icon-comment"></use>
          </svg>
          <div class="posts__item__comment__count ml-1"> <?php echo get_comments_number(get_the_ID()); ?> </div>
        </a>
      </div>
  </div>
</div>
<?php if ($author_id == $id_user_current) : ?>
  <div class="page-add-post modal fade" id="ModalEdit" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-fullscreen">
      <div class="modal-content">
        <div class="modal-header justify-content-start align-items-center">
          <button type="button" class="btn" data-bs-dismiss="modal" aria-label="Close">
            <svg width="20" height="20">
              <use href="#icon-back"></use>
            </svg>
          </button>
          <div class="font-weight-600 size-22"> <?php _e('Edit Post', 'umm'); ?> </div>
        </div>
        <div class="modal-body">
          <form id="form-update-post" class="form-add-post pb-4" action="" method="POST" enctype="multipart/form-data">
            <div class="form-group">
              <textarea class="form-control" rows="5" name="message" placeholder="<?php _e('Message', 'umm');  ?>"><?php echo get_the_content(); ?></textarea>
            </div>
            <div class="form-group">
              <input type="text" name="location" minlength="3" class="form-control location" value="<?php echo wp_strip_all_tags( get_the_excerpt(), true ); ?>" placeholder="<?php _e('Add Location', 'umm');  ?>" required autocomplete="off">
            </div>
            <div class="form-group">
              <div class="at-gr-input-file box-select-img box-preview-img d-flex align-items-center cursor">
                <img class="at-add-image-btn" src="<?php echo THEME_URL . 'images/add-img.png' ?>" width="88" height="90">
                <?php 
                    if ( isset($list_images_post_arr) && $list_images_post_arr ){
                      foreach ($list_images_post_arr as $value) {
                        echo '<div class="at-form-group">';
                          echo '<i class="fa fa-times at-remove-input remove-img" data-id-img="'.$value.'" title="Remove" aria-hidden="true"><svg width="40" height="41">';
                            echo '<use href="#icon-close"></use></svg></i>';
                          echo '<img src="'.get_image_url_by_id($value, 'thumbnail').'">';
                        echo '</div>';
                      }
                    } else {
                      echo '<div class="btn-upload p-4">'.__('Add photo', 'umm').'</div>';
                    }
                  ?>
                <div class="list_input"></div>
              </div>
            </div>
            <div class="notifi__update my-3 alert alert-warning hidden" role="alert"><?php _e('Successful', 'umm');  ?></div>
            <input type="hidden" name="list-remove-images" id="remove_image_title">
            <input type="hidden" id="remove_image" name="remove_image" value="">
            <input type="hidden" id="post_id" name="post_id" value="<?php the_ID() ?>">
            <div><?php wp_nonce_field(AT_NONCE_KEY . 'edit-community' . $id_user_current, 'edit-community-token'); ?></div>
            <button type="submit" class="btn btn__add w-100 at-rounded-14 bg-primary font-weight-500 text-white mt-3"><?php _e("Update", "umm") ?></button>
          </form>
        </div>
      </div>
    </div>
  </div>
<?php endif ?>
<?php get_footer(); ?>

Last updated