This commit is contained in:
Rich Lott / Artful Robot 2024-02-28 13:00:56 +00:00
parent 3b393be4f4
commit 0b96026602
17 changed files with 458 additions and 38 deletions

View file

@ -2,9 +2,11 @@
namespace Civi\Api4\Action\ContactCategory;
use Civi;
use Civi\Api4\Generic\AbstractAction;
use Civi\Api4\Activity;
use Civi\Api4\Generic\Result;
use Civi\Api4\Group;
use Civi\Api4\OptionValue;
use Civi\Api4\Setting;
use CRM_Core_DAO;
/**
@ -12,56 +14,120 @@ use CRM_Core_DAO;
*
* @see \Civi\Api4\Generic\AbstractAction
*
* @package ContactCategory
*/
class Sync extends \Civi\Api4\Generic\AbstractAction {
public function _run(Result $result) {
$map = [
['groupID' => 5, 'name' => 'Nice', 'categoryID' => 2],
];
$settings = Civi::settings()->get('contact_categories');
$settings = Setting::get(FALSE)
->addSelect('contact_categories')
->execute()->first()['value'] ?? NULL;
if (empty($settings['groupIDs'])) {
throw new \API_Exception('Unconfigured');
}
if ($settings['updateAfter'] > time()) {
// not needed yet.
return;
}
// Load category names
$catNames = OptionValue::get(FALSE)
->addWhere('option_group_id:name', '=', 'contact_categories')
->addSelect('value', 'label')
->execute()->indexBy('value')->column('label');
$groups = Group::get(FALSE)
->addWhere('id', 'IN', $settings['groupIDs'])
->execute()->indexBy('id')->getArrayCopy();
$smartGroups = [];
foreach ($groups as $groupID => $group) {
if (!empty($group['saved_search_id'])) {
$smartGroups[] = $groupID;
}
}
if ($smartGroups) {
\CRM_Contact_BAO_GroupContactCache::loadAll($smartGroups);
}
// clear out temp space.
CRM_Core_DAO::executeQuery("UPDATE civicrm_contactcategory SET next_category = 1;");
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category SET next_category = 0;");
// ensure we have all our contacts covered.
CRM_Core_DAO::executeQuery(<<<SQL
INSERT IGNORE INTO civicrm_contactcategory
SELECT id, 1 as category, 2 next_category
INSERT IGNORE INTO civicrm_contact_category
SELECT id, 0 as category, 0 next_category
FROM civicrm_contact
SQL);
foreach ($map as $row) {
// Get contacts in group.
$cat = (int) $row['categoryID'];
$row['groupID'] = (int) $row['groupID'];
$group = Group::get(FALSE)->addWhere('id', '=', $row['groupID'])->execute()->first();
if (!$group) {
Civi::warning("Group $row[groupID] used for category $row[name] no longer exists.");
foreach ($settings['groupIDs'] as $groupID) {
if ($groupID == 0) {
// The default 'group' isn't a ... group.
continue;
}
$isSmart = !empty($group['saved_search_id']);
// Get contacts in group.
if (!$groups[$groupID]) {
Civi::log()->warning("Group $groupID no longer exists.");
continue;
}
$isSmart = !empty($groups[$groupID]['saved_search_id']);
if (!$isSmart) {
$sql = <<<SQL
UPDATE civicrm_contactcategory cc
INNER JOIN civicrm_group_contact gc ON gc.contact_id = cc.id AND gc.status = 'Added' AND group_id = $row[groupID]
SET next_category = $cat
WHERE next_category = 1
UPDATE civicrm_contact_category cc
INNER JOIN civicrm_group_contact gc ON gc.contact_id = cc.id AND gc.status = 'Added' AND group_id = $groupID
SET next_category = $groupID
WHERE next_category = 0
SQL;
}
else {
// @todo refresh cache
$sql = <<<SQL
UPDATE civicrm_contactcategory cc
INNER JOIN civicrm_group_contact_cache gcc ON gcc.contact_id = cc.id AND group_id = $row[groupID]
SET next_category = $cat
WHERE next_category = 1
UPDATE civicrm_contact_category cc
INNER JOIN civicrm_group_contact_cache gcc ON gcc.contact_id = cc.id AND group_id = $groupID
SET next_category = $groupID
WHERE next_category = 0
SQL;
}
CRM_Core_DAO::executeQuery($sql);
}
$changes = CRM_Core_DAO::executeQuery(<<<SQL
SELECT id, category, next_category
FROM civicrm_contact_category
WHERE next_category <> category
ORDER BY category, next_category
SQL);
$lastChange = [0, 0];
$batch = [];
$n = 0;
$writeBatch = function() use (&$lastChange, &$batch, $catNames) {
if (empty($batch)) {
return;
}
// Create activity
Activity::create(FALSE)
->addValue('target_contact_id', $batch)
->addValue('activity_type_id:name', 'changed_contact_category')
->addValue('source_contact_id', \CRM_Core_BAO_Domain::getDomain()->contact_id)
->addValue('status_id:name', 'Completed')
->addValue('subject', $catNames[$lastChange[0] ?? 0] . ' → ' . $catNames[$lastChange[0] ?? 0])
->execute();
};
while ($changes->fetch()) {
$n++;
if ($lastChange[0] !== $changes->category || $lastChange[1] !== $changes->next_category) {
$writeBatch();
$lastChange = [$changes->category, $changes->next_category];
$batch = [];
}
$batch[] = $changes->id;
}
$writeBatch();
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category
SET category = next_category WHERE category <> next_category");
$summary = CRM_Core_DAO::executeQuery("SELECT next_category, count(*) from civicrm_contact_category group by next_category")->fetchAll();
$summary['changes'] = $n;
$result->exchangeArray($summary);
}
}