From 12ae6afeea0944b5d92368ce3af47343ab41d89a Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Mon, 5 Jun 2023 13:32:03 +1200 Subject: [PATCH] Cleanup on PriceSetCustom search Having fixed up the test on this I also fixed a couple of bits of red and also replaced calls to internal Core CiviCRM functions with api calls --- .../CRM/Contact/Form/Search/Custom/Base.php | 39 +++++- .../Contact/Form/Search/Custom/PriceSet.php | 115 ++++++++---------- .../CRM/Contact/Selector/Custom.php | 8 +- .../CRM/Contact/Form/Search/Custom.tpl | 2 +- 4 files changed, 96 insertions(+), 68 deletions(-) diff --git a/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/Base.php b/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/Base.php index 2ff571d5a2..fa5eddcd28 100644 --- a/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/Base.php +++ b/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/Base.php @@ -22,6 +22,16 @@ class CRM_Contact_Form_Search_Custom_Base { protected $_stateID; + /** + * Does the search class handle the prev next cache saving. + * + * This can be set to yes as long as a UI test works, and the deprecation + * notice will disappear. + * + * @var bool + */ + public $searchClassHandlesPrevNextCache = FALSE; + /** * The title of this form * @var string @@ -185,10 +195,8 @@ class CRM_Contact_Form_Search_Custom_Base { /** * @param $sql * @param bool $onlyWhere - * - * @throws Exception */ - public function validateUserSQL(&$sql, $onlyWhere = FALSE) { + public function validateUserSQL($sql, $onlyWhere = FALSE): void { $includeStrings = ['contact_a']; $excludeStrings = ['insert', 'delete', 'update']; @@ -260,4 +268,29 @@ class CRM_Contact_Form_Search_Custom_Base { return []; } + /** + * Fill the prevNextCache with the found contacts + * + * @return bool TRUE if the search was able to process it. + */ + public function fillPrevNextCache($cacheKey, $start, $end, $sort): bool { + if ($this->searchClassHandlesPrevNextCache) { + $sql = $this->sql( + '"' . $cacheKey . '" as cache_key, contact_a.id as id, contact_a.sort_name', + $start, + $end, + $sort + ); + $this->validateUserSQL($sql); + Civi::service('prevnext')->fillWithSql($cacheKey, $sql); + if (Civi::service('prevnext') instanceof CRM_Core_PrevNextCache_Sql) { + // SQL-backed prevnext cache uses an extra record for pruning the cache. + // Also ensure that caches stay alive for 2 days as per previous code + Civi::cache('prevNextCache')->set($cacheKey, $cacheKey, 60 * 60 * 24 * CRM_Core_PrevNextCache_Sql::cacheDays); + } + return TRUE; + } + return FALSE; + } + } diff --git a/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/PriceSet.php b/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/PriceSet.php index 444f84ce2d..544af45fb0 100644 --- a/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/PriceSet.php +++ b/ext/legacycustomsearches/CRM/Contact/Form/Search/Custom/PriceSet.php @@ -9,6 +9,9 @@ +--------------------------------------------------------------------+ */ +use Civi\Api4\PriceFieldValue; +use Civi\Api4\PriceSetEntity; + /** * * @package CRM @@ -16,12 +19,22 @@ */ class CRM_Contact_Form_Search_Custom_PriceSet extends CRM_Contact_Form_Search_Custom_Base implements CRM_Contact_Form_Search_Interface { - protected $_eventID = NULL; - protected $_aclFrom = NULL; - protected $_aclWhere = NULL; - protected $_tableName = NULL; + protected $eventID; + protected $_aclFrom; + protected $_aclWhere; + protected $_tableName; public $_permissionedComponent; + /** + * Does the search class handle the prev next cache saving. + * + * This can be set to yes as long as a UI test works, and the deprecation + * notice will disappear. + * + * @var bool + */ + public $searchClassHandlesPrevNextCache = TRUE; + /** * Class constructor. * @@ -30,13 +43,14 @@ class CRM_Contact_Form_Search_Custom_PriceSet extends CRM_Contact_Form_Search_Cu public function __construct(&$formValues) { parent::__construct($formValues); - $this->_eventID = CRM_Utils_Array::value('event_id', + $this->eventID = (int) CRM_Utils_Array::value('event_id', $this->_formValues ); $this->setColumns(); - if ($this->_eventID) { + // Actually impossible for it to not be set... + if ($this->eventID) { $this->buildTempTable(); $this->fillTable(); } @@ -45,22 +59,13 @@ class CRM_Contact_Form_Search_Custom_PriceSet extends CRM_Contact_Form_Search_Cu $this->_permissionedComponent = 'CiviEvent'; } - public function __destruct() { - /* - if ( $this->_eventID ) { - $sql = "DROP TEMPORARY TABLE {$this->_tableName}"; - CRM_Core_DAO::executeQuery( $sql ); - } - */ - } - - public function buildTempTable() { + public function buildTempTable(): void { $sql = 'id int unsigned NOT NULL AUTO_INCREMENT, contact_id int unsigned NOT NULL, participant_id int unsigned NOT NULL, '; - foreach ($this->_columns as $dontCare => $fieldName) { + foreach ($this->_columns as $fieldName) { if (in_array($fieldName, [ 'contact_id', 'participant_id', @@ -71,14 +76,14 @@ class CRM_Contact_Form_Search_Custom_PriceSet extends CRM_Contact_Form_Search_Cu $sql .= "{$fieldName} int default 0,\n"; } - $sql .= " + $sql .= ' PRIMARY KEY ( id ), - UNIQUE INDEX unique_participant_id ( participant_id )"; + UNIQUE INDEX unique_participant_id ( participant_id )'; $this->_tableName = CRM_Utils_SQL_TempTable::build()->setCategory('priceset')->setMemory()->createWithColumns($sql)->getName(); } - public function fillTable() { + public function fillTable(): void { $sql = " REPLACE INTO {$this->_tableName} ( contact_id, participant_id ) @@ -91,7 +96,7 @@ WHERE p.contact_id = c.id AND p.status_id NOT IN (4,11,12) AND ( c.is_deleted = 0 OR c.is_deleted IS NULL ) "; - CRM_Core_DAO::executeQuery($sql, [1 => [$this->_eventID, 'Positive']]); + CRM_Core_DAO::executeQuery($sql, [1 => [$this->eventID, 'Positive']]); $sql = " SELECT c.id as contact_id, @@ -113,12 +118,11 @@ WHERE p.contact_id = c.id ORDER BY c.id, l.price_field_value_id; "; - $dao = CRM_Core_DAO::executeQuery($sql, [1 => [$this->_eventID, 'Positive']]); + $dao = CRM_Core_DAO::executeQuery($sql, [1 => [$this->eventID, 'Positive']]); // first store all the information by option value id $rows = []; while ($dao->fetch()) { - $contactID = $dao->contact_id; $participantID = $dao->participant_id; if (!isset($rows[$participantID])) { $rows[$participantID] = []; @@ -141,11 +145,10 @@ WHERE participant_id = $participantID; } /** - * @param int $eventID * * @return Object */ - public function priceSetDAO($eventID = NULL) { + public function priceSetDAO() { // get all the events that have a price set associated with it $sql = " @@ -158,17 +161,7 @@ FROM civicrm_event e, WHERE p.entity_table = 'civicrm_event' AND p.entity_id = e.id "; - - $params = []; - if ($eventID) { - $params[1] = [$eventID, 'Integer']; - $sql .= " AND e.id = $eventID"; - } - - $dao = CRM_Core_DAO::executeQuery($sql, - $params - ); - return $dao; + return CRM_Core_DAO::executeQuery($sql); } /** @@ -207,42 +200,40 @@ AND p.entity_id = e.id $form->assign('elements', ['event_id']); } - public function setColumns() { + /** + * @throws \Civi\API\Exception\UnauthorizedException + * @throws \CRM_Core_Exception + */ + public function setColumns(): void { $this->_columns = [ ts('Contact ID') => 'contact_id', ts('Participant ID') => 'participant_id', ts('Name') => 'display_name', ]; - if (!$this->_eventID) { + if (!$this->eventID) { return; } // for the selected event, find the price set and all the columns associated with it. // create a column for each field and option group within it - $dao = $this->priceSetDAO($this->_formValues['event_id']); - - if ($dao->fetch() && - !$dao->price_set_id - ) { - throw new CRM_Core_Exception(ts('There are no events with Price Sets')); - } - - // get all the fields and all the option values associated with it - $priceSet = CRM_Price_BAO_PriceSet::getSetDetail($dao->price_set_id); - if (is_array($priceSet[$dao->price_set_id])) { - foreach ($priceSet[$dao->price_set_id]['fields'] as $key => $value) { - if (is_array($value['options'])) { - foreach ($value['options'] as $oKey => $oValue) { - $columnHeader = $value['label'] ?? NULL; - if (CRM_Utils_Array::value('html_type', $value) != 'Text') { - $columnHeader .= ' - ' . $oValue['label']; - } - - $this->_columns[$columnHeader] = "price_field_{$oValue['id']}"; - } + $priceSetEntity = PriceSetEntity::get() + ->addWhere('entity_table', '=', 'civicrm_event') + ->addWhere('entity_id', '=', $this->eventID) + ->addSelect('price_set_id') + ->execute()->first(); + $priceSetID = $priceSetEntity['price_set_id']; + $priceFieldValues = PriceFieldValue::get() + ->addWhere('price_field_id.price_set_id', '=', $priceSetID) + ->addSelect('label', 'price_field_id.html_type', 'price_field_id.label') + ->execute(); + + foreach ($priceFieldValues as $value) { + $columnHeader = $value['price_field_id.label'] ?? NULL; + if ($value['price_field_id.html_type'] !== 'Text') { + $columnHeader .= ' - ' . $value['label']; } - } + $this->_columns[$columnHeader] = "price_field_{$value['id']}"; } } @@ -294,7 +285,7 @@ contact_a.display_name as display_name"; /** * @return string */ - public function from() { + public function from(): string { $this->buildACLClause('contact_a'); $from = " FROM civicrm_contact contact_a @@ -343,7 +334,7 @@ INNER JOIN {$this->_tableName} tempTable ON ( tempTable.contact_id = contact_a.i * @param string $tableAlias */ public function buildACLClause($tableAlias = 'contact') { - list($this->_aclFrom, $this->_aclWhere) = CRM_Contact_BAO_Contact_Permission::cacheClause($tableAlias); + [$this->_aclFrom, $this->_aclWhere] = CRM_Contact_BAO_Contact_Permission::cacheClause($tableAlias); } } diff --git a/ext/legacycustomsearches/CRM/Contact/Selector/Custom.php b/ext/legacycustomsearches/CRM/Contact/Selector/Custom.php index 7c0a3b50f3..b58922b0e5 100644 --- a/ext/legacycustomsearches/CRM/Contact/Selector/Custom.php +++ b/ext/legacycustomsearches/CRM/Contact/Selector/Custom.php @@ -74,8 +74,9 @@ class CRM_Contact_Selector_Custom extends CRM_Contact_Selector { protected $_fields; /** - * The object that implements the search interface - * @var object + * The object that implements the search interface. + * + * @var CRM_Contact_Form_Search_Custom_Base */ protected $_search; @@ -425,6 +426,9 @@ class CRM_Contact_Selector_Custom extends CRM_Contact_Selector { * @throws \CRM_Core_Exception */ public function fillPrevNextCache($sort, $cacheKey, $start = 0, $end = self::CACHE_SIZE): void { + if ($this->_search->fillPrevNextCache($cacheKey, $start, $end, $sort)) { + return; + } $sql = $this->_search->contactIDs($start, $end, $sort, TRUE); // CRM-9096 diff --git a/ext/legacycustomsearches/templates/CRM/Contact/Form/Search/Custom.tpl b/ext/legacycustomsearches/templates/CRM/Contact/Form/Search/Custom.tpl index 4a1a7bfdf9..89d6c23cfe 100644 --- a/ext/legacycustomsearches/templates/CRM/Contact/Form/Search/Custom.tpl +++ b/ext/legacycustomsearches/templates/CRM/Contact/Form/Search/Custom.tpl @@ -54,7 +54,7 @@ {include file="CRM/common/pager.tpl" location="top"} {* Include alpha pager if defined. *} - {if $atoZ} + {if $aToZ} {include file="CRM/common/pagerAToZ.tpl"} {/if} -- 2.25.1