HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: /var/www/html/insiders/wp-load/wp-content/plugins/internal-links/helper/ajax.php
<?php
namespace ILJ\Helper;

use ILJ\Backend\AdminMenu;
use ILJ\Backend\BatchInfo;
use ILJ\Backend\Editor;
use ILJ\Backend\Environment;
use ILJ\Backend\MenuPage\Tools;
use ILJ\Backend\User;
use ILJ\Cache\Transient_Cache;
use ILJ\Core\IndexBuilder;
use ILJ\Core\Options as CoreOptions;
use ILJ\Data\Content;
use ILJ\Database\Keywords;
use ILJ\Database\DatabaseCollation;
use ILJ\Database\Postmeta;
use ILJ\Enumeration\Content_Type;
use ILJ\Helper\IndexAsset;
use ILJ\Database\Linkindex;
use ILJ\Helper\BatchInfo as HelperBatchInfo;
use ILJ\Statistics\Link;
use ILJ\Type\KeywordList;

/**
 * Ajax toolset
 *
 * Methods for handling AJAX requests
 *
 * @package ILJ\Helper
 *
 * @since 1.0.0
 */
class Ajax {
	const ILJ_FILTER_AJAX_SEARCH_POSTS = 'ilj_ajax_search_posts';
	const ILJ_FILTER_AJAX_SEARCH_TERMS = 'ilj_ajax_search_terms';
	
	private static $cached_html = null;

	

	/**
	 * Searches the posts for a given phrase
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public static function searchPostsAction() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-search-posts-action')) {
			die();
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		if (!isset($_POST['search']) && !isset($_POST['per_page']) && !isset($_POST['page'])) {
			wp_die();
		}

		$search   = sanitize_text_field(wp_unslash($_POST['search']));
		$per_page = (int) $_POST['per_page'];
		$page     = (int) $_POST['page'];

		$args = array(
			's'              => $search,
			'posts_per_page' => $per_page,
			'paged'          => $page,
		);

		$query = new \WP_Query($args);

		$data = array();

		foreach ($query->posts as $post) {
			$data[] = array(
				'id'   => $post->ID,
				'text' => $post->post_title,
			);
		}

		/**
		 * Filters the output of ajax post search
		 *
		 * @since 1.1.6
		 *
		 * @param object $data The return data (found posts)
		 * @param array  $args The arguments for the post query
		 */
		$data = apply_filters(self::ILJ_FILTER_AJAX_SEARCH_POSTS, $data, $args);

		wp_send_json($data);
		wp_die();
	}

	/**
	 * Rebuilds the link index
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function indexRebuildAction() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-dashboard')) {
			die();
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		try {
			do_action(IndexBuilder::ILJ_INITIATE_BATCH_REBUILD);

			$response = array(
				'status'  => 'success',
				'message' => sprintf('<p class="message">' . __('Index rebuild successfully scheduled.', 'internal-links') . '</p>'),
			);
		} catch (\Exception $e) {
			$response = array(
				'status'  => 'error',
				'message' => sprintf('<p class="message">' . __('There has been an error in initiating the index rebuild.', 'internal-links') . '</p>'),
			);
		}

		wp_send_json($response);
		wp_die();
	}

	

	/**
	 * Renders the statistics for the links
	 *
	 * @since 1.2.5
	 *
	 * @param int $start_count Determine what index to start counting
	 * @param int $chunk_size  The size of the batch to loop into
	 * @return String
	 */
	public static function render_links_statistic_action($start_count, $chunk_size) {
		$statistics = Statistic::getLinkStatistics();

		if (!count($statistics) && 0 == $start_count) {
			return;
		} elseif (!count($statistics) && 0 < $start_count) {
			return null;
		}

		for ($i = $start_count; $i < min($start_count + $chunk_size, count($statistics)); $i++) {
			$statistic = $statistics[$i];
			$asset_data = IndexAsset::getMeta($statistic->asset_id, $statistic->asset_type);

			if (!$asset_data) {
				continue;
			}

			$edit_link  = sprintf('<a href="%s" class="tip" title="' . __('Edit', 'internal-links') . '">%s</a>', $asset_data->url_edit, '<span class="dashicons dashicons-edit"></span>');
			$asset_link = sprintf('<a href="%s" class="tip" title="' . __('Open', 'internal-links') . '" target="_blank" rel="noopener">%s</a>', $asset_data->url, '<span class="dashicons dashicons-external"></span>');

			$elements_to   = $statistic->elements_to ? '<a title="' . __('Show incoming links', 'internal-links') . '" class="tip ilj-statistic-detail" data-id="' . $statistic->asset_id . '" data-type="' . $statistic->asset_type . '" data-direction="to">' . $statistic->elements_to . '</a>' : '-';
			$elements_from = $statistic->elements_from ? '<a title="' . __('Show outgoing links', 'internal-links') . '" class="tip ilj-statistic-detail" data-id="' . $statistic->asset_id . '" data-type="' . $statistic->asset_type . '" data-direction="from">' . $statistic->elements_from . '</a>' : '-';

			$type = IndexAsset::getDetailedType($statistic->asset_id, $statistic->asset_type);

			self::$cached_html .= '<tr>';
			self::$cached_html .= '<td class="asset-title">' . $asset_data->title . '</td>';
			self::$cached_html .= '<td>' . Statistic::getConfiguredKeywordsCountForAsset($statistic->asset_id, $statistic->asset_type) . '</td>';
			self::$cached_html .= '<td class="type" data-search="' .  $statistic->asset_type . ';' . $type . '"><span data-type="' . $statistic->asset_type . '">' . $type . '</span></td>';
			self::$cached_html .= '<td>' . $elements_to . '</td>';
			self::$cached_html .= '<td>' . $elements_from . '</td>';
			self::$cached_html .= '<td>' . $edit_link . ' ' . $asset_link . '</td>';
			self::$cached_html .= '</tr>';
		}
		echo wp_kses_post(self::$cached_html);
	}

	/**
	 * Renders the statistics for the anchor texts
	 *
	 * @since 1.2.5
	 *
	 * @param  array $request Data of the datatable form send to server for populating datagrid
	 * @return array
	 */
	public static function render_anchors_statistic($request) {
		$record_data = array();
		$statistics = Statistic::get_anchor_statistics($request);
		foreach ($statistics['data'] as $statistic) {
			$record_data[] = array(esc_html($statistic->anchor), intval(strlen($statistic->anchor)), intval(count(explode(' ', $statistic->anchor))), '<a title="' . __('Show usage', 'internal-links') . '" class="tip ilj-statistic-detail" data-anchor="' . esc_attr($statistic->anchor) . '">' . esc_html($statistic->frequency) . '</a>');
		}
		$statistics['data'] = $record_data;
		return $statistics;
	}

	/**
	 * Retrieves link data for a specific asset by a given direction (in- or outgoing)
	 *
	 * @since 1.1.0
	 *
	 * @return void
	 */
	public static function renderLinkDetailStatisticAction() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-dashboard') || !current_user_can('manage_options')) {
			die();
		}
		if (!isset($_POST['id']) || !isset($_POST['type']) || !isset($_POST['direction'])) {
			wp_die();
		}

		$id        = (int) $_POST['id'];
		$type      = sanitize_text_field(wp_unslash($_POST['type']));
		$direction = sanitize_text_field(wp_unslash($_POST['direction']));

		$directive_links = Linkindex::getDirectiveLinks($id, $type, $direction);

		if (!count($directive_links)) {
			wp_die();
		}

		$direction_header = '';

		if ('from' == $direction) {
			$direction_header = __('Target', 'internal-links');
		} elseif ('to' == $direction) {
			$direction_header = __('Source', 'internal-links');
		}

		$data = '<table class="ilj-statistic-detail-table display"><thead><tr><th>' . $direction_header . '</th><th>' . __('Type', 'internal-links') . '</th><th>' . __('Anchor text', 'internal-links') . '</th></tr></thead>';
		$data .= '<tbody>';

		$row_counter = 0;

		for ($i=0; $i < count($directive_links); $i++) {
			$directive_link = $directive_links[$i];

			{
       if ($i >= 3) {
   					break;
   				}
   }

			if (!property_exists($directive_link, 'link_' . $direction) || !property_exists($directive_link, 'type_' . $direction) || !property_exists($directive_link, 'anchor')) {
				continue;
			}

			if ('from' == $direction) {
				$reverse_direction = 'to';
			} elseif ('to' == $direction) {
				$reverse_direction = 'from';
			}

			$type = IndexAsset::getDetailedType($directive_link->{'link_' . $reverse_direction}, $directive_link->{'type_' . $reverse_direction});
			$asset_data = IndexAsset::getMeta($directive_link->{'link_' . $reverse_direction}, $directive_link->{'type_' . $reverse_direction});

			if (!$asset_data) {
				continue;
			}

			$data .= '<tr class="' . ((0 === $row_counter % 2) ? 'even' : 'odd') . '"><td><a href="' . $asset_data->url . '" rel="noopener" target="_blank">' . $asset_data->title . '</a></td><td class="type"><span data-type="' . $directive_link->{'type_' . $reverse_direction} . '">' . $type . '</span></td><td>' . $directive_link->anchor . '</td></tr>';

			$row_counter++;
		}

		$data .= '</tbody>';
		$data .= '</table>';

		{
      if (count($directive_links) > 3) {
   				$data .= '<div class="ilj-statistic-detail-hidden spacer">';
   				$data .= '	<div class="more"><span class="dashicons dashicons-lock"></span> and ' . (count($directive_links) - 3) . ' more</div>';
   				$data .= '  <div class="upgrade">';
   				$data .= '      <p>'.__('With the free basic version you can view the first 3 links in the detail view.', 'internal-links').'</p>';
   				$data .= '      <a href="' . get_admin_url(null, 'admin.php?page=' . AdminMenu::ILJ_MENUPAGE_SLUG . '-pricing') . '"><span class="dashicons dashicons-unlock"></span> ' . __('Upgrade to Pro and view all', 'internal-links') . '</a>';
   				$data .= '  </div>';
   				$data .= '</div>';
   			}
  }

		echo wp_kses_post($data);
		wp_die();
	}

	/**
	 * Renders link details for a specific anchor text
	 *
	 * @since  1.1.0
	 * @return void
	 */
	public static function renderAnchorDetailStatisticAction() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-dashboard') || !current_user_can('manage_options')) {
			die();
		}
		if (!isset($_POST['anchor'])) {
			wp_die();
		}

		$data = '';

		

		{
      $data = '<div class="ilj-statistic-detail-hidden">';
      $data .= '  <div class="upgrade">';
      $data .= '      <p>'.__('The detail view for anchor texts is part of the Pro version.', 'internal-links').'</p>';
      $data .= '      <a href="' . get_admin_url(null, 'admin.php?page=' . AdminMenu::ILJ_MENUPAGE_SLUG . '-pricing') . '"><span class="dashicons dashicons-unlock"></span> ' . __('Upgrade to Pro and view all', 'internal-links') . '</a>';
      $data .= '  </div>';
      $data .= '</div>';
  }

		echo wp_kses_post($data);
		wp_die();
	}

	/**
	 * Hides the promo box in the sidebar
	 *
	 * @since  1.1.2
	 * @return void
	 */
	public static function hidePromo() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-general-nonce')) {
			die;
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		User::update('hide_promo', true);
		wp_die();
	}

	/**
	 * Handles upload of import files
	 *
	 * @since  1.2.0
	 * @return void
	 */
	public static function uploadImport() {
		if (!isset($_POST['nonce']) || !isset($_POST['file_type'])) {
			wp_send_json_error(null, 400);
		}

		$nonce = sanitize_text_field(wp_unslash($_POST['nonce']));
		$file_type = sanitize_text_field(wp_unslash($_POST['file_type']));

		if (!in_array($file_type, array('settings', 'keywords'))) {
			wp_send_json_error(null, 400);
		}

		if (!wp_verify_nonce($nonce, 'ilj-tools') || !current_user_can('manage_options')) {
			wp_send_json_error(null, 400);
		}

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- It's File upload not user input.
		$uploaded_file = isset($_FILES['file_data']) ? $_FILES['file_data'] : array();

		$upload_overrides = array(
			'test_form' => false,
			'test_type' => false,
		);

		if ('keywords' == $file_type) {
			$uploaded_file['name'] = uniqid(wp_rand(), true) . '.csv';
		}

		$file_upload = wp_handle_upload($uploaded_file, $upload_overrides);

		if (!$file_upload || isset($file_upload['error'])) {
			wp_send_json_error(__('Your web host does not allow file uploads.', 'internal-links') . ' ' . __('Please fix the problem and try again.', 'internal-links'), 400);
		}

		switch ($file_type) {
			case 'settings':
			// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local file.
			$file_content = file_get_contents($file_upload['file']);
			wp_delete_file($file_upload['file']);
			$file_json = Encoding::jsonToArray($file_content);

			if (false === $file_json) {
					wp_send_json_error(null, 400);
			}

			set_transient('ilj_upload_settings', $file_json, HOUR_IN_SECONDS * 12);
				break;
			case 'keywords':
			set_transient('ilj_upload_keywords', $file_upload, HOUR_IN_SECONDS * 12);
				break;
		}

		wp_send_json_success(null, 200);
	}

	/**
	 * Initiates the import of already uploaded and prepared files
	 *
	 * @since  1.2.0
	 * @return void
	 */
	public static function startImport() {
		if (!isset($_POST['nonce']) || !isset($_POST['file_type'])) {
			wp_send_json_error(null, 400);
		}

		$nonce = sanitize_text_field(wp_unslash($_POST['nonce']));
		$file_type = sanitize_text_field(wp_unslash($_POST['file_type']));

		if (!in_array($file_type, array('settings', 'keywords'))) {
			wp_send_json_error(null, 400);
		}

		if (!wp_verify_nonce($nonce, 'ilj-tools') || !current_user_can('manage_options')) {
			wp_send_json_error(null, 400);
		}

		$upload_transient = get_transient('ilj_upload_' . $file_type);

		if (!$upload_transient) {
			wp_send_json_error(__('Timeout.', 'internal-links') . ' ' . __('Please try to upload again', 'internal-links'), 400);
		}

		switch ($file_type) {
			case 'settings':
			$import_count = CoreOptions::importOptions($upload_transient);
				break;
			case 'keywords':
			if (!isset($upload_transient['file']) || !file_exists($upload_transient['file'])) {
					wp_send_json_error(null, 400);
			}
			$import_count = Keyword::importKeywordsFromFile($upload_transient['file']);
			wp_delete_file($upload_transient['file']);
				break;
		}

		if (0 === $import_count) {
			wp_send_json_error(__('Nothing to import or no data for import found.', 'internal-links'), 400);
		}

		do_action(IndexBuilder::ILJ_INITIATE_BATCH_REBUILD);

		delete_transient('ilj_upload_' . $file_type);
		wp_send_json_success(null, 200);
	}

	

	/**
	 * Renders the Status and info of the Batch Build
	 *
	 * @since 1.3.10
	 *
	 * @return void
	 */
	public static function renderBatchInfo() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-general-nonce')) {
			die();
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		$batch_build_info = new HelperBatchInfo();
		$info = $batch_build_info->getBatchInfo();

		wp_send_json($info);
		wp_die();
	}

	/**
	 * Handles clear all transient ajax action
	 *
	 * @return void
	 */
	public static function clear_all_transient() {
		if (!check_admin_referer('ilj_clear_all_transient') || !current_user_can('manage_options')) {
			return;
		}
		Transient_Cache::delete_all();
		\ILJ\ilj_fs()->add_sticky_admin_message(__('The Caches were cleared.', 'internal-links'), 'ilj_clear_all_transient_notice');
		wp_safe_redirect(wp_get_referer());
		die();
	}

	/**
	 * Loads chunks of links statistics data to table
	 *
	 * @since 2.23.4
	 *
	 * @return array
	 */
	public static function load_link_statistics() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-dashboard') || !current_user_can('manage_options')) {
			die();
		}

		$table_columns = array('title', 'keywords_count', 'type', 'incoming_links', 'outgoing_links');
		$sort_by = 'title';
		if (isset($_REQUEST['order'][0]['column'])) {
			$sort_column_index = intval($_REQUEST['order'][0]['column']);
			if ($sort_column_index < count($table_columns)) {
				$sort_by = $table_columns[$sort_column_index];
			}
		}

		$sort_direction = 'ASC';
		if (isset($_REQUEST['order'][0]['dir']) && 'desc' === $_REQUEST['order'][0]['dir']) {
			$sort_direction = 'DESC';
		}

		$link_statistics = new Link(array(
			'sort_by' => $sort_by,
			'sort_direction' => $sort_direction,
			'limit' => isset($_REQUEST['length']) ? intval($_REQUEST['length']) : 10,
			'offset' => isset($_REQUEST['start']) ? intval($_REQUEST['start']) : 0,
			'search' => isset($_REQUEST['search']['value']) && is_string($_REQUEST['search']['value']) ? sanitize_text_field(wp_unslash($_REQUEST['search']['value'])) : '',
			'main_types' => isset($_REQUEST['main_types']) && !empty($_REQUEST['main_types']) && is_string($_REQUEST['main_types']) ? explode(',', sanitize_text_field(wp_unslash($_REQUEST['main_types']))) : array(),
			'sub_types' => isset($_REQUEST['sub_types']) && !empty($_REQUEST['sub_types']) && is_string($_REQUEST['sub_types']) ? explode(',', sanitize_text_field(wp_unslash($_REQUEST['sub_types']))) : array(),

		));


		$total = $link_statistics->get_total();


		/**
		 * `recordsTotal`, `recordsFiltered` are standard property names for pagination in data tables
		 *
		 * @see https://datatables.net/examples/data_sources/server_side
		 */
		echo wp_json_encode(array(
			'recordsTotal' => $total,
			'recordsFiltered' => $link_statistics->get_filtered_results_count(),
			'data' => $link_statistics->get_statistics(),
			'draw' => isset($_REQUEST['draw']) ? intval($_REQUEST['draw']) : 0
		));
		die();
	}

	/**
	 * Handles clear single transient ajax action
	 *
	 * @return void
	 */
	public static function clear_single_transient() {
		if (!check_admin_referer('ilj_clear_single_transient') || !current_user_can('manage_options')) {
			return;
		}
		$id   = isset($_REQUEST['ilj_transient_id']) ? sanitize_text_field(wp_unslash($_REQUEST['ilj_transient_id'])) : '';
		$type = isset($_REQUEST['ilj_transient_type']) ? sanitize_text_field(wp_unslash($_REQUEST['ilj_transient_type'])) : '';
		if (!$id || !in_array($type, array('post', 'term'), true)) {
			return;
		}
		Transient_Cache::delete_cache_for_content(intval($id), $type);
		/* Dont print notice because the ui using this flag will have inbuilt feedback instead of printing the notice */
		if (!isset($_REQUEST['ilj_skip_notice'])) {
			/* translators: %s: Post Type */
			$message = 'post' === $type ? sprintf(__('The cache for the %s has been cleared.', 'internal-links'), get_post_type($id)) : __('The cache for the term has been cleared.', 'internal-links');
			\ILJ\ilj_fs()->add_sticky_admin_message($message, 'ilj_clear_single_transient_notice');
			wp_safe_redirect(wp_get_referer());
		}
		die();
	}

	/**
	 * Loads chunks of anchor statistics data to table
	 *
	 * @since 2.23.4
	 *
	 * @return void
	 */
	public static function load_anchor_statistics_chunk_callback() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-dashboard')) {
			die();
		}

		if (!current_user_can('manage_options')) {
			return;
		}
		$request = $_POST;
		$html_chunk = Ajax::render_anchors_statistic($request);
		echo wp_json_encode($html_chunk);
		die();
	}

	/**
	 * Cancels the index rebuild schedules
	 *
	 * @since 2.23.5
	 *
	 * @return void
	 */
	public static function cancel_all_schedules() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-cancel-all-schedule-action')) {
			die();
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		Cleanup::clean_scheduled_actions();
		HelperBatchInfo::reset_batch_info();

		wp_send_json_success(null, 200);
		wp_die();
	}
	
	

	

	/**
	 * Fix database collation issues
	 *
	 * @since 2.24.4
	 *
	 * @return void
	 */
	public static function fix_database_collation() {
		if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'ilj-fix-database-collation-action')) {
			die();
		}
		if (!current_user_can('manage_options')) {
			return;
		}
		DatabaseCollation::modify_collation();

		wp_send_json_success(null, 200);
		wp_die();
	}
}