Skip to content

Commit

Permalink
APIv4 - Deprecate and stop using PreSaveSubscriber
Browse files Browse the repository at this point in the history
The PreSaveSubscriber allowed APIs to tweak inputs before saving a record,
but it was unreliable because:
- It would run for Create and Update but not Save actions
- It would run before pseudoconstant suffixes had been resolved
- It would run before any formatting or internal processing had taken place

Meanwhile, a new pattern of overriding the create/save/update actions and sharing a trait
has become more common and while a bit more cumbersome to implement, it does not share
those limitations.

This removes all uses of PreSaveSubscriber, refactors those bits into Save traits, and
adds a deprecation warning in case any extension in the Universe happens to have implemented it.
  • Loading branch information
colemanw committed Jan 28, 2022
1 parent bc8a85d commit ed3f587
Show file tree
Hide file tree
Showing 37 changed files with 360 additions and 226 deletions.
3 changes: 2 additions & 1 deletion Civi/Api4/Action/Address/AddressSaveTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
namespace Civi\Api4\Action\Address;

/**
* @inheritDoc
* Code shared by Address create/update/save actions
*
* @method bool getStreetParsing()
* @method $this setStreetParsing(bool $streetParsing)
* @method bool getSkipGeocode()
Expand Down
46 changes: 46 additions & 0 deletions Civi/Api4/Action/Contact/ContactSaveTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?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;

/**
* Code shared by Contact create/update/save actions
*/
trait ContactSaveTrait {

/**
* @param array $items
* @return array
*/
protected function write(array $items) {
foreach ($items as &$contact) {
// For some reason the contact BAO requires this for updates
if (!empty($contact['id'])) {
$contact['contact_id'] = $contact['id'];
}
elseif (empty($contact['contact_type'])) {
// Guess which type of contact is being created
if (!empty($contact['organization_name'])) {
$contact['contact_type'] = 'Organization';
}
elseif (!empty($contact['household_name'])) {
$contact['contact_type'] = 'Household';
}
else {
$contact['contact_type'] = 'Individual';
}
}
}
return parent::write($items);
}

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/Contact/Create.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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;

/**
* @inheritDoc
*/
class Create extends \Civi\Api4\Generic\DAOCreateAction {
use ContactSaveTrait;

}
17 changes: 1 addition & 16 deletions Civi/Api4/Action/Contact/Save.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,6 @@
* @inheritDoc
*/
class Save extends \Civi\Api4\Generic\DAOSaveAction {

/**
* @param array $items
* @return array
*/
protected function write(array $items) {
$saved = [];
foreach ($items as $item) {
// For some reason the contact BAO requires this for updates
if (!empty($item['id']) && !\CRM_Utils_System::isNull($item['id'])) {
$item['contact_id'] = $item['id'];
}
$saved[] = \CRM_Contact_BAO_Contact::create($item);
}
return $saved;
}
use ContactSaveTrait;

}
15 changes: 1 addition & 14 deletions Civi/Api4/Action/Contact/Update.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@
* @inheritDoc
*/
class Update extends \Civi\Api4\Generic\DAOUpdateAction {

/**
* @param array $items
* @return array
*/
protected function write(array $items) {
$saved = [];
foreach ($items as $item) {
// For some reason the contact BAO requires this for updates
$item['contact_id'] = $item['id'];
$saved[] = \CRM_Contact_BAO_Contact::create($item);
}
return $saved;
}
use ContactSaveTrait;

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Event\Subscriber;
namespace Civi\Api4\Action\Contribution;

use Civi\Api4\Generic\AbstractAction;

class ContributionPreSaveSubscriber extends Generic\PreSaveSubscriber {

public function modify(&$record, AbstractAction $request) {
// Required by Contribution BAO
$record['skipCleanMoney'] = TRUE;
}
/**
* Code shared by Contribution create/update/save actions
*/
trait ContributionSaveTrait {

public function applies(AbstractAction $request) {
return $request->getEntityName() === 'Contribution';
/**
* @inheritDoc
*/
protected function write(array $items) {
foreach ($items as &$item) {
// Required by Contribution BAO
$item['skipCleanMoney'] = TRUE;
}
return parent::write($items);
}

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/Contribution/Create.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\Contribution;

/**
* @inheritDoc
*/
class Create extends \Civi\Api4\Generic\DAOCreateAction {
use ContributionSaveTrait;

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/Contribution/Save.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\Contribution;

/**
* @inheritDoc
*/
class Save extends \Civi\Api4\Generic\DAOSaveAction {
use ContributionSaveTrait;

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/Contribution/Update.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\Contribution;

/**
* @inheritDoc
*/
class Update extends \Civi\Api4\Generic\DAOUpdateAction {
use ContributionSaveTrait;

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/CustomField/Create.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\CustomField;

/**
* @inheritDoc
*/
class Create extends \Civi\Api4\Generic\DAOCreateAction {
use CustomFieldSaveTrait;

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,35 @@
+--------------------------------------------------------------------+
*/

namespace Civi\Api4\Event\Subscriber;
namespace Civi\Api4\Action\CustomField;

use Civi\Api4\Generic\AbstractAction;

class CustomFieldPreSaveSubscriber extends Generic\PreSaveSubscriber {
/**
* Code shared by CustomField create/update/save actions
*/
trait CustomFieldSaveTrait {

/**
* @var string
* @inheritDoc
*/
public $supportedOperation = 'create';
protected function write(array $items) {
foreach ($items as &$field) {
if (empty($field['id'])) {
self::formatOptionValues($field);
}
}
return parent::write($items);
}

public function modify(&$field, AbstractAction $request) {
/**
* If 'option_values' have been supplied, reformat it according to the expectations of the BAO
*
* @param array $field
*/
private static function formatOptionValues(array &$field): void {
$field['option_type'] = !empty($field['option_values']);
if (!empty($field['option_values'])) {
$weight = $key = 0;
$field['option_label'] = $field['option_value'] = $field['option_status'] = $field['option_weight'] = [];
$weight = 0;
$field['option_label'] = $field['option_value'] = $field['option_status'] = $field['option_weight'] =
$field['option_name'] = $field['option_color'] = $field['option_description'] = $field['option_icon'] = [];
foreach ($field['option_values'] as $key => $value) {
// Translate simple key/value pairs into full-blown option values
Expand All @@ -34,22 +48,16 @@ public function modify(&$field, AbstractAction $request) {
'id' => $key,
];
}
$weight++;
$field['option_label'][] = $value['label'] ?? $value['name'];
$field['option_name'][] = $value['name'] ?? NULL;
$field['option_value'][] = $value['id'];
$field['option_status'][] = $value['is_active'] ?? 1;
$field['option_weight'][] = $value['weight'] ?? $weight;
$field['option_weight'][] = $value['weight'] ?? ++$weight;
$field['option_color'][] = $value['color'] ?? NULL;
$field['option_description'][] = $value['description'] ?? NULL;
$field['option_icon'][] = $value['icon'] ?? NULL;
}
}
$field['option_type'] = !empty($field['option_values']);
}

public function applies(AbstractAction $request) {
return $request->getEntityName() === 'CustomField';
}

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/CustomField/Save.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\CustomField;

/**
* @inheritDoc
*/
class Save extends \Civi\Api4\Generic\DAOSaveAction {
use CustomFieldSaveTrait;

}
21 changes: 21 additions & 0 deletions Civi/Api4/Action/CustomField/Update.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\CustomField;

/**
* @inheritDoc
*/
class Update extends \Civi\Api4\Generic\DAOUpdateAction {
use CustomFieldSaveTrait;

}
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\Create
*/
public static function create($checkPermissions = TRUE) {
return (new Action\Contact\Create(__CLASS__, __FUNCTION__))
->setCheckPermissions($checkPermissions);
}

/**
* @param bool $checkPermissions
* @return Action\Contact\Update
Expand Down
Loading

0 comments on commit ed3f587

Please sign in to comment.