diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php index 93e9b556d1ef..392088f66cc1 100644 --- a/CRM/Contact/BAO/Contact.php +++ b/CRM/Contact/BAO/Contact.php @@ -1009,7 +1009,8 @@ public static function deleteContact($id, $restore = FALSE, $skipUndelete = FALS $transaction = new CRM_Core_Transaction(); if ($skipUndelete) { - CRM_Utils_Hook::pre('delete', $contactType, $id, CRM_Core_DAO::$_nullArray); + $hookParams = ['check_permissions' => $checkPermissions]; + CRM_Utils_Hook::pre('delete', $contactType, $id, $hookParams); //delete billing address if exists. CRM_Contribute_BAO_Contribution::deleteAddress(NULL, $id); diff --git a/CRM/Core/BAO/EntityTag.php b/CRM/Core/BAO/EntityTag.php index 88d8ab9fc5be..cbd60e2cd62e 100644 --- a/CRM/Core/BAO/EntityTag.php +++ b/CRM/Core/BAO/EntityTag.php @@ -483,4 +483,38 @@ public static function buildOptions($fieldName, $context = NULL, $props = []) { return $options; } + /** + * This function deletes entity tags when a related entity is called. + * + * It is registered as a listener in \Civi\Core\Container::createEventDispatcher + * + * @param \Civi\Core\DAO\Event\PreDelete $event + */ + public static function preDeleteOtherEntity($event) { + if ( + $event->object instanceof CRM_Core_DAO_EntityTag + // Activity can call the pre hook for delete with no ID - this seems to be isolated to activity.... + // @todo - what is the correct way to standardise activity delete? + || ($event->object instanceof CRM_Activity_DAO_Activity && !$event->object->id) + + ) { + return; + } + // This is probably fairly mild in terms of helping performance - a case could be made to check if tags + // exist before deleting (further down) as delete is a locking action. + $entity = CRM_Core_DAO_AllCoreTables::getBriefName(get_class($event->object)); + if (!isset(Civi::$statics[__CLASS__]['tagged_entities'][$entity])) { + $tableName = CRM_Core_DAO_AllCoreTables::getTableForEntityName($entity); + $used_for = CRM_Core_OptionGroup::values('tag_used_for'); + Civi::$statics[__CLASS__]['tagged_entities'][$entity] = !empty($used_for[$tableName]) ? $tableName : FALSE; + } + + if (Civi::$statics[__CLASS__]['tagged_entities'][$entity]) { + CRM_Core_DAO::executeQuery('DELETE FROM civicrm_entity_tag WHERE entity_table = %1 AND entity_id = %2', + [1 => [Civi::$statics[__CLASS__]['tagged_entities'][$entity], 'String'], 2 => [$event->object->id, 'Integer']] + ); + } + + } + } diff --git a/CRM/Core/DAO/AllCoreTables.php b/CRM/Core/DAO/AllCoreTables.php index 01d9bf73ba63..0fee62521ce1 100644 --- a/CRM/Core/DAO/AllCoreTables.php +++ b/CRM/Core/DAO/AllCoreTables.php @@ -254,6 +254,17 @@ public static function getTableForClass($className) { self::tables()); } + /** + * Convert the entity name into a table name. + * + * @param string $entityBriefName + * + * @return FALSE|string + */ + public static function getTableForEntityName($entityBriefName) { + return self::getTableForClass(self::getFullName($entityBriefName)); + } + /** * Reinitialise cache. * diff --git a/Civi/Core/Container.php b/Civi/Core/Container.php index 73eff1ed1e02..6666ce61fc56 100644 --- a/Civi/Core/Container.php +++ b/Civi/Core/Container.php @@ -335,6 +335,7 @@ public function createEventDispatcher($container) { $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\LocalizationInitializer', 'initialize']); $dispatcher->addListener('hook_civicrm_post', ['\CRM_Core_Transaction', 'addPostCommit'], -1000); $dispatcher->addListener('hook_civicrm_pre', ['\Civi\Core\Event\PreEvent', 'dispatchSubevent'], 100); + $dispatcher->addListener('civi.dao.preDelete', ['\CRM_Core_BAO_EntityTag', 'preDeleteOtherEntity']); $dispatcher->addListener('hook_civicrm_post', ['\Civi\Core\Event\PostEvent', 'dispatchSubevent'], 100); $dispatcher->addListener('hook_civicrm_post::Activity', ['\Civi\CCase\Events', 'fireCaseChange']); $dispatcher->addListener('hook_civicrm_post::Case', ['\Civi\CCase\Events', 'fireCaseChange']);