->addWhere('entity_id', '=', $event->id)
->execute();
}
+ // When an entity is updated, update the timestamp in corresponding Managed record
+ elseif ($event->action === 'edit' && $event->id && self::isApi4ManagedType($event->entity)) {
+ CRM_Core_DAO::executeQuery('UPDATE civicrm_managed SET entity_modified_date = CURRENT_TIMESTAMP WHERE entity_type = %1 AND entity_id = %2', [
+ 1 => [$event->entity, 'String'],
+ 2 => [$event->id, 'Integer'],
+ ]);
+ }
}
/**
*
* Generated from xml/schema/CRM/Core/Managed.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:c8697305b613f6ca6854638025df2fd7)
+ * (GenCodeChecksum:ca11b419bcdf2bce26609d9488527023)
*/
/**
*/
public $cleanup;
+ /**
+ * When the managed entity was changed from its original settings.
+ *
+ * @var timestamp
+ */
+ public $entity_modified_date;
+
/**
* Class constructor.
*/
'where' => 'civicrm_managed.id',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'html' => [
'type' => 'Number',
'where' => 'civicrm_managed.module',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'add' => '4.2',
],
'where' => 'civicrm_managed.name',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'add' => '4.2',
],
'where' => 'civicrm_managed.entity_type',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'add' => '4.2',
],
'where' => 'civicrm_managed.entity_id',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'add' => '4.2',
],
'where' => 'civicrm_managed.cleanup',
'table_name' => 'civicrm_managed',
'entity' => 'Managed',
- 'bao' => 'CRM_Core_DAO_Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
'localizable' => 0,
'html' => [
'type' => 'Select',
],
'add' => '4.5',
],
+ 'entity_modified_date' => [
+ 'name' => 'entity_modified_date',
+ 'type' => CRM_Utils_Type::T_TIMESTAMP,
+ 'title' => ts('Entity Modified Date'),
+ 'description' => ts('When the managed entity was changed from its original settings.'),
+ 'required' => FALSE,
+ 'where' => 'civicrm_managed.entity_modified_date',
+ 'default' => NULL,
+ 'table_name' => 'civicrm_managed',
+ 'entity' => 'Managed',
+ 'bao' => 'CRM_Core_BAO_Managed',
+ 'localizable' => 0,
+ 'add' => '5.45',
+ ],
];
CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
}
* Entity specification (per hook_civicrm_managedEntities).
*/
protected function updateExistingEntity($dao, $todo) {
- $policy = CRM_Utils_Array::value('update', $todo, 'always');
+ $policy = $todo['update'] ?? 'always';
$doUpdate = ($policy === 'always');
if ($doUpdate && $todo['params']['version'] == 3) {
civicrm_api4($dao->entity_type, 'update', $params);
}
- if (isset($todo['cleanup'])) {
- $dao->cleanup = $todo['cleanup'];
+ if (isset($todo['cleanup']) || $doUpdate) {
+ $dao->cleanup = $todo['cleanup'] ?? NULL;
+ // Reset the `entity_modified_date` timestamp if reverting record.
+ $dao->entity_modified_date = $doUpdate ? 'null' : NULL;
$dao->update();
}
}
if ($result['is_error']) {
$this->onApiError($dao->entity_type, 'create', $params, $result);
}
+ // Reset the `entity_modified_date` timestamp to indicate that the entity has not been modified by the user.
+ $dao->entity_modified_date = 'null';
+ $dao->update();
}
}
// }
}
- /*
- * Important! All upgrade functions MUST add a 'runSql' task.
- * Uncomment and use the following template for a new upgrade version
- * (change the x in the function name):
+ /**
+ * Upgrade function.
+ *
+ * @param string $rev
*/
-
- // /**
- // * Upgrade function.
- // *
- // * @param string $rev
- // */
- // public function upgrade_5_0_x($rev): void {
- // $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
- // $this->addTask('Do the foo change', 'taskFoo', ...);
- // // Additional tasks here...
- // // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
- // // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
- // }
-
- // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...): bool {
- // return TRUE;
- // }
+ public function upgrade_5_45_alpha1($rev): void {
+ $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+ $this->addTask('Add entity_modified_date column to civicrm_managed', 'addColumn',
+ 'civicrm_managed', 'entity_modified_date', "timestamp NULL DEFAULT NULL COMMENT 'When the managed entity was changed from its original settings.'"
+ );
+ }
}
->setOptionsCallback(['CRM_Core_PseudoConstant', 'getExtensions'])
->setSqlRenderer([__CLASS__, 'renderBaseModule']);
$spec->addFieldSpec($field);
+
+ $field = (new FieldSpec('local_modified_date', $spec->getEntity(), 'Timestamp'))
+ ->setLabel(ts('Locally Modified'))
+ ->setTitle(ts('Locally modified'))
+ ->setColumnName('id')
+ ->setDescription(ts('When the managed entity was changed from its original settings'))
+ ->setType('Extra')
+ ->setReadonly(TRUE)
+ ->setSqlRenderer([__CLASS__, 'renderLocalModifiedDate']);
+ $spec->addFieldSpec($field);
}
/**
return "(SELECT `civicrm_managed`.`module` FROM `civicrm_managed` WHERE `civicrm_managed`.`entity_id` = $id AND `civicrm_managed`.`entity_type` = '$entity' LIMIT 1)";
}
+ /**
+ * Get sql snippet for local_modified_date
+ * @param array $field
+ * return string
+ */
+ public static function renderLocalModifiedDate(array $field): string {
+ $id = $field['sql_name'];
+ $entity = $field['entity'];
+ return "(SELECT `civicrm_managed`.`entity_modified_date` FROM `civicrm_managed` WHERE `civicrm_managed`.`entity_id` = $id AND `civicrm_managed`.`entity_type` = '$entity' LIMIT 1)";
+ }
+
}
$search = SavedSearch::get(FALSE)
->addWhere('name', '=', 'TestManagedSavedSearch')
+ ->addSelect('description', 'local_modified_date')
->execute()->single();
$this->assertEquals('Original state', $search['description']);
+ $this->assertNull($search['local_modified_date']);
SavedSearch::update(FALSE)
->addValue('id', $search['id'])
->addValue('description', 'Altered state')
->execute();
+ $time = $this->getCurrentTimestamp();
$search = SavedSearch::get(FALSE)
->addWhere('name', '=', 'TestManagedSavedSearch')
- ->addSelect('description', 'has_base', 'base_module')
+ ->addSelect('description', 'has_base', 'base_module', 'local_modified_date')
->execute()->single();
$this->assertEquals('Altered state', $search['description']);
// Check calculated fields
$this->assertTrue($search['has_base']);
$this->assertEquals('civicrm', $search['base_module']);
+ // local_modified_date should reflect the update just made
+ $this->assertGreaterThanOrEqual($time, $search['local_modified_date']);
+ $this->assertLessThanOrEqual($this->getCurrentTimestamp(), $search['local_modified_date']);
SavedSearch::revert(FALSE)
->addWhere('name', '=', 'TestManagedSavedSearch')
// Entity should be revered to original state
$result = SavedSearch::get(FALSE)
->addWhere('name', '=', 'TestManagedSavedSearch')
- ->addSelect('description', 'has_base', 'base_module')
+ ->addSelect('description', 'has_base', 'base_module', 'local_modified_date')
->setDebug(TRUE)
->execute();
$search = $result->single();
// Check calculated fields
$this->assertTrue($search['has_base']);
$this->assertEquals('civicrm', $search['base_module']);
+ // local_modified_date should be reset by the revert action
+ $this->assertNull($search['local_modified_date']);
// Check calculated fields for a non-managed entity - they should be empty
$newName = uniqid(__FUNCTION__);
->execute();
$search = SavedSearch::get(FALSE)
->addWhere('name', '=', $newName)
- ->addSelect('label', 'has_base', 'base_module')
+ ->addSelect('label', 'has_base', 'base_module', 'local_modified_date')
->execute()->single();
$this->assertEquals('Whatever', $search['label']);
// Check calculated fields
$this->assertEquals(NULL, $search['base_module']);
$this->assertFalse($search['has_base']);
+ $this->assertNull($search['local_modified_date']);
}
/**
];
}
+ private function getCurrentTimestamp() {
+ return \CRM_Core_DAO::singleValueQuery('SELECT CURRENT_TIMESTAMP');
+ }
+
}
</html>
<add>4.5</add>
</field>
+ <field>
+ <name>entity_modified_date</name>
+ <type>timestamp</type>
+ <comment>When the managed entity was changed from its original settings.</comment>
+ <required>false</required>
+ <default>NULL</default>
+ <add>5.45</add>
+ </field>
<index>
<name>UI_managed_entity</name>
<fieldName>entity_type</fieldName>