<?php

class CRM_ConstituentsOnly_BAO_ConstituentsOnly {

  /**
   * Alter Quick search query.
   *
   * @param string $query
   *
   */
  public static function getQuickSearchQuery($query) {
    $joinQuery = str_replace('WHERE ', 'WHERE (cc.do_not_trade = 1) AND ', $query);
    $sqls[] = "CREATE TEMPORARY TABLE quick_temp_table_1
      {$joinQuery}
    ";

    $sqls[] = "
      CREATE TEMPORARY TABLE quick_temp_table_2
        SELECT MAX(contact_a.id) AS contact_id, cc.id AS og_contact_id, MAX(cc.sort_name) AS og_sort_name
        FROM civicrm_contact contact_a
          INNER JOIN civicrm_relationship cr
            ON (cr.contact_id_a = contact_a.id OR cr.contact_id_b = contact_a.id)
            AND contact_a.is_deleted = 0
            AND (contact_a.do_not_trade = 0 OR contact_a.do_not_trade IS NULL)
            AND cr.is_active = 1
          INNER JOIN civicrm_contact cc
            ON (cr.contact_id_a = cc.id OR cr.contact_id_b = cc.id)
            AND contact_a.id <> cc.id
            AND cc.id IN (SELECT id FROM quick_temp_table_1)
            AND cc.do_not_trade = 1
        GROUP BY cc.id
    ";

    foreach ($sqls as $sql) {
      CRM_Core_DAO::executeQuery($sql);
    }
    $startPoint = stripos($query, 'from');
    $endPoint = stripos($query, 'union');
    $firstQuery = substr($query, $startPoint, ($endPoint - $startPoint));
    $firstQuery = substr($firstQuery, stripos($firstQuery, 'select'));
    $firstQuery = substr($firstQuery, 0, stripos($firstQuery, 'where'));
    $firstQuery = str_replace(
      'sort_name, ',
      "CONCAT(cc.sort_name, ' (', og_sort_name, ')'), ",
      $firstQuery
    );

    $strToReplace = "
      UNION
        (
          $firstQuery
          INNER JOIN quick_temp_table_2 temp ON temp.contact_id = cc.id
        )
      ) t
    ";

    $replace = 'WHERE (cc.do_not_trade IS NULL OR cc.do_not_trade = 0) AND ';
    $query = str_replace('WHERE ', $replace, $query);
    $query = str_replace(') t', $strToReplace, $query);
    return $query;
  }

  /**
   * Rebuild search result rows.
   *
   * @param string $query
   *
   */
  public static function updateSearchRows($rows) {
    $contactIds = array_keys($rows);
    $sql = "SELECT MAX(contact_a.id) AS contact_id, cc.id AS og_contact_id
      FROM civicrm_contact contact_a
      INNER JOIN civicrm_relationship cr
        ON (cr.contact_id_a = contact_a.id OR cr.contact_id_b = contact_a.id)
        AND contact_a.is_deleted = 0
        AND (contact_a.do_not_trade = 0 OR contact_a.do_not_trade IS NULL)
        AND cr.is_active = 1
      INNER JOIN civicrm_contact cc
        ON (cr.contact_id_a = cc.id OR cr.contact_id_b = cc.id)
        AND contact_a.id <> cc.id
        AND cc.id IN (" . implode(',', $contactIds) . ")
        AND cc.do_not_trade = 1
      GROUP BY cc.id
    ";
    $result = CRM_Core_DAO::executeQuery($sql);
    $relContactIds = [];

    while ($result->fetch()) {
      $relContactIds[$result->og_contact_id] = $result->contact_id;
    }

    if (!empty($relContactIds)) {
      $formValues = ['contact_id' => $relContactIds];
      $queryParams = CRM_Contact_BAO_Query::convertFormValues($formValues);
      $selector = new CRM_Contact_Selector(
        '',
        $queryParams,
        $queryParams
      );
      list($select, $from, $where, $having) = $selector->getQuery()->query();
      $newRows = $selector->getRows('', '', '', '');
      foreach ($relContactIds as $ogContactId => $cid) {
        if (empty($newRows[$cid])) {
          continue;
        }
        $newRows[$cid]['sort_name'] .= "({$rows[$ogContactId]['sort_name']})";
        $rows[$ogContactId] = $newRows[$cid];
      }
    }
    return $rows;
  }

}