mirror of
https://codeberg.org/artfulrobot/contactcats.git
synced 2025-06-26 21:37:17 +02:00
Support updating a single contact
This commit is contained in:
parent
8d0a9d0926
commit
016ca2a735
2 changed files with 37 additions and 9 deletions
|
@ -13,6 +13,15 @@ use Civi\ContactCats\Processor;
|
||||||
*/
|
*/
|
||||||
class Sync extends \Civi\Api4\Generic\AbstractAction {
|
class Sync extends \Civi\Api4\Generic\AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contact ID
|
||||||
|
*
|
||||||
|
* Force sync for given contact only.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $contact_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usually this will not act unless the time is right.
|
* Usually this will not act unless the time is right.
|
||||||
*
|
*
|
||||||
|
@ -24,7 +33,8 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
|
||||||
public function _run(Result $result) {
|
public function _run(Result $result) {
|
||||||
ini_set('memory_limit', '256M');
|
ini_set('memory_limit', '256M');
|
||||||
Civi::log()->debug('Begin', ['=start' => 'ContactCatSync', '=timed' => 1]);
|
Civi::log()->debug('Begin', ['=start' => 'ContactCatSync', '=timed' => 1]);
|
||||||
if (!$this->force) {
|
|
||||||
|
if (!$this->force && !$this->contact_id) {
|
||||||
$nextRun = Civi::settings()->get('contactcats_next_run') ?? 0;
|
$nextRun = Civi::settings()->get('contactcats_next_run') ?? 0;
|
||||||
if (time() < $nextRun) {
|
if (time() < $nextRun) {
|
||||||
// not needed yet.
|
// not needed yet.
|
||||||
|
@ -33,7 +43,7 @@ class Sync extends \Civi\Api4\Generic\AbstractAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$processor = new Processor();
|
$processor = new Processor($this->contact_id);
|
||||||
$result->exchangeArray($processor->run());
|
$result->exchangeArray($processor->run());
|
||||||
|
|
||||||
// Limit to running every 24 hours; we actually want it to be stable within one day.
|
// Limit to running every 24 hours; we actually want it to be stable within one day.
|
||||||
|
|
|
@ -18,7 +18,11 @@ class Processor {
|
||||||
|
|
||||||
protected array $searchDetails = [];
|
protected array $searchDetails = [];
|
||||||
|
|
||||||
public function __construct() {
|
protected ?int $contact_id = NULL;
|
||||||
|
|
||||||
|
public function __construct(?int $contact_id = NULL) {
|
||||||
|
|
||||||
|
$this->contact_id = $contact_id;
|
||||||
|
|
||||||
$this->categories = ContactCategoryDefinition::get(FALSE)
|
$this->categories = ContactCategoryDefinition::get(FALSE)
|
||||||
->addOrderBy('execution_order')
|
->addOrderBy('execution_order')
|
||||||
|
@ -106,12 +110,16 @@ class Processor {
|
||||||
return $summary;
|
return $summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates change activities and actually updates the current category data.
|
||||||
|
*/
|
||||||
protected function createChangeActivities() {
|
protected function createChangeActivities() {
|
||||||
|
$singleContactClause = $this->contact_id ? "AND id = $this->contact_id" : "";
|
||||||
Civi::log()->debug("Calculate changes", ['=' => 'timed', '=start' => "changes"]);
|
Civi::log()->debug("Calculate changes", ['=' => 'timed', '=start' => "changes"]);
|
||||||
$changes = CRM_Core_DAO::executeQuery(<<<SQL
|
$changes = CRM_Core_DAO::executeQuery(<<<SQL
|
||||||
SELECT id, category_definition_id, next_category
|
SELECT id, category_definition_id, next_category
|
||||||
FROM civicrm_contact_category
|
FROM civicrm_contact_category
|
||||||
WHERE next_category <> category_definition_id
|
WHERE next_category <> category_definition_id $singleContactClause
|
||||||
ORDER BY category_definition_id, next_category
|
ORDER BY category_definition_id, next_category
|
||||||
SQL);
|
SQL);
|
||||||
$lastChange = [0, 0];
|
$lastChange = [0, 0];
|
||||||
|
@ -163,10 +171,11 @@ class Processor {
|
||||||
Civi::log()->debug('Apply changes', ['=change' => 'applyChanges', '=timed' => 1]);
|
Civi::log()->debug('Apply changes', ['=change' => 'applyChanges', '=timed' => 1]);
|
||||||
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category
|
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category
|
||||||
SET category_definition_id = next_category
|
SET category_definition_id = next_category
|
||||||
WHERE category_definition_id IS NULL OR category_definition_id <> next_category")->free();
|
WHERE (category_definition_id IS NULL OR category_definition_id <> next_category) $singleContactClause")->free();
|
||||||
Civi::log()->debug('', ['=pop' => 1]);
|
Civi::log()->debug('', ['=pop' => 1]);
|
||||||
|
|
||||||
$summary = CRM_Core_DAO::executeQuery("SELECT next_category, count(*) from civicrm_contact_category GROUP BY next_category")->fetchAll();
|
$singleContactClause = $this->contact_id ? "WHERE id = $this->contact_id" : "";
|
||||||
|
$summary = CRM_Core_DAO::executeQuery("SELECT next_category, count(*) from civicrm_contact_category $singleContactClause GROUP BY next_category")->fetchAll();
|
||||||
$summary['changes'] = $n;
|
$summary['changes'] = $n;
|
||||||
$_ = memory_get_peak_usage(TRUE);
|
$_ = memory_get_peak_usage(TRUE);
|
||||||
$summary['memory_use'] = @round($_ / pow(1024, ($i = floor(log($_, 1024)))), 2) . ' ' . ['b', 'kb', 'mb', 'gb', 'tb', 'pb'][$i];
|
$summary['memory_use'] = @round($_ / pow(1024, ($i = floor(log($_, 1024)))), 2) . ' ' . ['b', 'kb', 'mb', 'gb', 'tb', 'pb'][$i];
|
||||||
|
@ -194,11 +203,14 @@ class Processor {
|
||||||
protected function resetTable() {
|
protected function resetTable() {
|
||||||
Civi::log()->debug('Resetting table', ['=' => 'start,timed']);
|
Civi::log()->debug('Resetting table', ['=' => 'start,timed']);
|
||||||
|
|
||||||
|
$singleContactClause = $this->contact_id ? "WHERE cat.id = $this->contact_id" : "";
|
||||||
|
|
||||||
// Delete our data for deleted contacts.
|
// Delete our data for deleted contacts.
|
||||||
$dao = CRM_Core_DAO::executeQuery(<<<SQL
|
$dao = CRM_Core_DAO::executeQuery(<<<SQL
|
||||||
DELETE cat
|
DELETE cat
|
||||||
FROM civicrm_contact_category cat
|
FROM civicrm_contact_category cat
|
||||||
INNER JOIN civicrm_contact ct ON ct.id = cat.id AND ct.is_deleted = 1
|
INNER JOIN civicrm_contact ct ON ct.id = cat.id AND ct.is_deleted = 1
|
||||||
|
$singleContactClause
|
||||||
SQL);
|
SQL);
|
||||||
if ($dao->N) {
|
if ($dao->N) {
|
||||||
Civi::log()->debug("Deleted category data for {$dao->N} trashed contacts");
|
Civi::log()->debug("Deleted category data for {$dao->N} trashed contacts");
|
||||||
|
@ -206,16 +218,17 @@ class Processor {
|
||||||
$dao->free();
|
$dao->free();
|
||||||
|
|
||||||
// Zero our internal next_category field.
|
// Zero our internal next_category field.
|
||||||
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category SET next_category = 0;")->free();
|
CRM_Core_DAO::executeQuery("UPDATE civicrm_contact_category cat SET next_category = 0 $singleContactClause;")->free();
|
||||||
Civi::log()->debug('stage 2');
|
Civi::log()->debug('stage 2');
|
||||||
|
|
||||||
// ensure we have all our contacts covered.
|
// ensure we have all our contacts covered.
|
||||||
// Q: is it quicker to do a WHERE NOT EXISTS? A: nope.
|
// Q: is it quicker to do a WHERE NOT EXISTS? A: nope.
|
||||||
|
$singleContactClause = $this->contact_id ? "AND id = $this->contact_id" : "";
|
||||||
CRM_Core_DAO::executeQuery(<<<SQL
|
CRM_Core_DAO::executeQuery(<<<SQL
|
||||||
INSERT INTO civicrm_contact_category
|
INSERT INTO civicrm_contact_category
|
||||||
SELECT id, NULL AS category_definition_id, 0 AS next_category
|
SELECT id, NULL AS category_definition_id, 0 AS next_category
|
||||||
FROM civicrm_contact
|
FROM civicrm_contact
|
||||||
WHERE is_deleted = 0
|
WHERE is_deleted = 0 $singleContactClause
|
||||||
AND NOT EXISTS (SELECT id FROM civicrm_contact_category WHERE id = civicrm_contact.id)
|
AND NOT EXISTS (SELECT id FROM civicrm_contact_category WHERE id = civicrm_contact.id)
|
||||||
SQL)->free();
|
SQL)->free();
|
||||||
Civi::log()->debug('Done resetting table', ['=' => 'pop']);
|
Civi::log()->debug('Done resetting table', ['=' => 'pop']);
|
||||||
|
@ -233,11 +246,12 @@ class Processor {
|
||||||
Civi::log()->debug($group['title'] . ($isSmart ? '(smart)' : ''), ['=' => 'timed', '=start' => "group$groupID"]);
|
Civi::log()->debug($group['title'] . ($isSmart ? '(smart)' : ''), ['=' => 'timed', '=start' => "group$groupID"]);
|
||||||
$table = $isSmart ? 'civicrm_group_contact_cache' : 'civicrm_group_contact';
|
$table = $isSmart ? 'civicrm_group_contact_cache' : 'civicrm_group_contact';
|
||||||
$statusWhere = $isSmart ? '' : 'AND gc.status = "Added"';
|
$statusWhere = $isSmart ? '' : 'AND gc.status = "Added"';
|
||||||
|
$andContactIdCriterion = $this->contact_id ? "AND cc.id=$this->contact_id" : '';
|
||||||
$sql = <<<SQL
|
$sql = <<<SQL
|
||||||
UPDATE civicrm_contact_category cc
|
UPDATE civicrm_contact_category cc
|
||||||
INNER JOIN $table gc ON gc.contact_id = cc.id AND group_id = $groupID $statusWhere
|
INNER JOIN $table gc ON gc.contact_id = cc.id AND group_id = $groupID $statusWhere
|
||||||
SET next_category = {$cat['id']}
|
SET next_category = {$cat['id']}
|
||||||
WHERE next_category = 0
|
WHERE next_category = 0 $andContactIdCriterion
|
||||||
SQL;
|
SQL;
|
||||||
CRM_Core_DAO::executeQuery($sql)->free();
|
CRM_Core_DAO::executeQuery($sql)->free();
|
||||||
Civi::log()->debug('', ['=' => 'pop']);
|
Civi::log()->debug('', ['=' => 'pop']);
|
||||||
|
@ -255,6 +269,10 @@ class Processor {
|
||||||
$contactIdKey = 'id';
|
$contactIdKey = 'id';
|
||||||
// We only need the ID.
|
// We only need the ID.
|
||||||
$apiParams['select'] = ['id'];
|
$apiParams['select'] = ['id'];
|
||||||
|
if ($this->contact_id) {
|
||||||
|
// Limit to one contact.
|
||||||
|
$apiParams['where'][] = ['id', '=', $this->contact_id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new CRM_Core_Exception("can't figure out contactID in search: " . json_encode($search));
|
throw new CRM_Core_Exception("can't figure out contactID in search: " . json_encode($search));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue