Skip to content

Commit

Permalink
APIv4 - Add useTrash option to soft-delete contacts
Browse files Browse the repository at this point in the history
This sets Contact::delete to move contacts to the trash by default.
  • Loading branch information
colemanw committed Nov 30, 2021
1 parent ef0a997 commit a0edf1c
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 7 deletions.
37 changes: 37 additions & 0 deletions Civi/Api4/Action/Contact/Delete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Action\Contact;

/**
* Deletes a contact, by default moving to trash. Set `useTrash = FALSE` for permanent deletion.
* @inheritDoc
*/
class Delete extends \Civi\Api4\Generic\DAODeleteAction {
use \Civi\Api4\Generic\Traits\SoftDelete;

/**
* @param $items
* @return array
* @throws \API_Exception
*/
protected function deleteObjects($items) {
foreach ($items as $item) {
if (!\CRM_Contact_BAO_Contact::deleteContact($item['id'], FALSE, !$this->useTrash, $this->checkPermissions)) {
throw new \API_Exception("Could not delete {$this->getEntityName()} id {$item['id']}");
}
$ids[] = ['id' => $item['id']];
}
return $ids;
}

}
9 changes: 9 additions & 0 deletions Civi/Api4/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
*/
class Contact extends Generic\DAOEntity {

/**
* @param bool $checkPermissions
* @return Action\Contact\Delete
*/
public static function delete($checkPermissions = TRUE) {
return (new Action\Contact\Delete(__CLASS__, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param bool $checkPermissions
* @return Action\Contact\GetChecksum
Expand Down
27 changes: 27 additions & 0 deletions Civi/Api4/Generic/Traits/SoftDelete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Generic\Traits;

/**
* This trait is used by entities with a "move to trash" option.
* @method $this setUseTrash(bool $useTrash) Pass FALSE to force delete and bypass trash
* @method bool getUseTrash()
*/
trait SoftDelete {

/**
* Should $ENTITY be moved to the trash instead of permanently deleted?
* @var bool
*/
protected $useTrash = TRUE;

}
4 changes: 4 additions & 0 deletions Civi/Test/Api3TestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ public function runApi4Legacy($v3Entity, $v3Action, $v3Params = []) {
}
}

if (isset($actionInfo[0]['params']['useTrash'])) {
$v4Params['useTrash'] = empty($v3Params['skip_undelete']);
}

// Build where clause for 'getcount', 'getsingle', 'getvalue', 'get' & 'replace'
if ($v4Action == 'get' || $v3Action == 'replace') {
foreach ($v3Params as $key => $val) {
Expand Down
13 changes: 9 additions & 4 deletions tests/phpunit/api/v3/ContactTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3154,27 +3154,32 @@ public function testContactCreationPermissions(int $version): void {

/**
* Test that delete with skip undelete respects permissions.
* TODO: Api4
*
* @param int $version
*
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
* @dataProvider versionThreeAndFour
*/
public function testContactDeletePermissions(): void {
public function testContactDeletePermissions(int $version): void {
$this->_apiversion = $version;
$contactID = $this->individualCreate();
$tag = $this->callAPISuccess('Tag', 'create', ['name' => 'to be deleted']);
$this->quickCleanup(['civicrm_entity_tag', 'civicrm_tag']);
$tag = $this->callAPISuccess('Tag', 'create', ['name' => uniqid('to be deleted')]);
$this->callAPISuccess('EntityTag', 'create', ['entity_id' => $contactID, 'tag_id' => $tag['id']]);
CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM'];
$this->callAPIFailure('Contact', 'delete', [
'id' => $contactID,
'check_permissions' => 1,
'skip_undelete' => 1,
]);
$this->callAPISuccessGetCount('EntityTag', ['entity_id' => $contactID], 1);
$this->callAPISuccess('Contact', 'delete', [
'id' => $contactID,
'check_permissions' => 0,
'skip_undelete' => 1,
]);
$this->callAPISuccessGetCount('EntityTag', ['entity_id' => $contactID], 0);
$this->quickCleanup(['civicrm_entity_tag', 'civicrm_tag']);
}

/**
Expand Down
11 changes: 8 additions & 3 deletions tests/phpunit/api/v4/Entity/ConformanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,15 @@ protected function checkDeletionAllowed($entityClass, $id, $entity) {
$this->assertEquals(0, $this->checkAccessCounts["{$entity}::delete"]);
$isReadOnly = $this->isReadOnly($entityClass);

$deleteResult = $entityClass::delete()
$deleteAction = $entityClass::delete()
->setCheckPermissions(!$isReadOnly)
->addWhere('id', '=', $id)
->execute();
->addWhere('id', '=', $id);

if (property_exists($deleteAction, 'useTrash')) {
$deleteAction->setUseTrash(FALSE);
}

$deleteResult = $deleteAction->execute();

// should get back an array of deleted id
$this->assertEquals([['id' => $id]], (array) $deleteResult);
Expand Down

0 comments on commit a0edf1c

Please sign in to comment.