Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM_Utils_Array::value - remove "todo" which we don't actually want to do #27812

Merged
merged 2 commits into from
Oct 14, 2023

Conversation

highfalutin
Copy link
Contributor

@highfalutin highfalutin commented Oct 13, 2023

This function is very widely called within the CiviCRM universe and is tantalizingly close to being identical to the PHP null-coalescing operator, ??.

The old "todo" in the code comments would make the function less similar to ??, and would break a lot of things inside and outside core, and create a lot of work. Instead we'll focus on moving away from using this function in the first place.

@civibot
Copy link

civibot bot commented Oct 13, 2023

🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷

Introduction for new contributors...
  • If this is your first PR, an admin will greenlight automated testing with the command ok to test or add to whitelist.
  • A series of tests will automatically run. You can see the results at the bottom of this page (if there are any problems, it will include a link to see what went wrong).
  • A demo site will be built where anyone can try out a version of CiviCRM that includes your changes.
  • If this process needs to be repeated, an admin will issue the command test this please to rerun tests and build a new demo site.
  • Before this PR can be merged, it needs to be reviewed. Please keep in mind that reviewers are volunteers, and their response time can vary from a few hours to a few weeks depending on their availability and their knowledge of this particular part of CiviCRM.
  • A great way to speed up this process is to "trade reviews" with someone - find an open PR that you feel able to review, and leave a comment like "I'm reviewing this now, could you please review mine?" (include a link to yours). You don't have to wait for a response to get started (and you don't have to stop at one!) the more you review, the faster this process goes for everyone 😄
  • To ensure that you are credited properly in the final release notes, please add yourself to contributor-key.yml
  • For more information about contributing, see CONTRIBUTING.md.
Quick links for reviewers...

➡️ Online demo of this PR 🔗

@civibot civibot bot added the master label Oct 13, 2023
@colemanw
Copy link
Member

@highfalutin we've been hesitant to do this because the ?? operator basically calls isset(), which behaves slightly differently to array_key_exists().

My efforts have been toward removing usages of this function rather than try to improve it. I guess CRM_Utils_Array::value() is like a bad relationship: you can't change them, but you can leave them!

See: https://github.com/civicrm/civicrm-core/pulls?q=+is%3Apr+author%3Acolemanw+CRM_Utils_Array

@highfalutin
Copy link
Contributor Author

Thanks @Coleman. Good to know. I was curious to see which tests would fail.

@colemanw
Copy link
Member

@highfalutin one would "hope" tests would catch it but they might not because

  1. The difference is subtle and tests don't test every little thing
  2. A lot of quickforms don't have test coverage (or not very much anyway)

return $list->offsetExists($key) ? $list[$key] : $default;
}
// @todo - eliminate these from core & uncomment this line.
// CRM_Core_Error::deprecatedFunctionWarning('You have passed an invalid parameter for the "list"');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe as a first pass it would be interesting to uncomment this line and see what tests fail...

Copy link
Contributor Author

@highfalutin highfalutin Oct 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colemanw I agree it would be interesting to know which callers are passing in non-arrays in the $list param, although it doesn't get at the existing difference between this function and ??. Uncommenting this line would actually make this function more strict than ??. I wonder if there's reason to do that?

@highfalutin
Copy link
Contributor Author

@colemanw see #27830

@highfalutin highfalutin changed the title Simplify the second-most-called function because we don't use php5 anymore WIP: Simplify CRM_Utils_Array::value() Oct 14, 2023
@highfalutin
Copy link
Contributor Author

highfalutin commented Oct 14, 2023

Since I had to force-push in order to do the experiment that Coleman suggested, I'll note: the first version of this PR changed the body of this function to just

return $list[$key] ?? $default;

and no tests failed as a result. What this means is that no core tests depend on the special behavior of CRM_Utils_Array::value(). (I introduced a test to correct that — #27830.)

As Coleman points out, there still may be code that depends on the special behavior.

@colemanw
Copy link
Member

@highfalutin re-thinking my earlier comment, this function hails from the PHPv4 era, before strict type checking was a thing, and when PHP was competing hard with Javascript for the "sloppiest language" championship title. So the chances that someone implemented this function to intentionally use (or had any clue about) the difference between isset and array_key_exists are quite low IMO. In fact, in a lot of recent refactoring I've noticed potential bugs that might be caused by the clueless use of this function that would be fixed with null-coalescing ??. (and as an aside, I've also noticed a lot of clueless uses of this function that do nothing at all, because the array key is definitely set in that scope and could be accessed directly without any guards; ah the joys of refactoring).

So I'm now a soft +1 on merging the original version of this PR. Tests were happy with it, and it's consistent with how the function is being refactored out.

@highfalutin
Copy link
Contributor Author

highfalutin commented Oct 14, 2023

@colemanw ha! I was just starting to lean in the other direction. It seems like the function is different enough from ?? to justify its use in one particular kind of situation: where you want to get a non-null $default back only if $key doesn't exist on the array.

But thinking about that... why would you want to do that? Rather than breaking our brains trying to answer that question, we could

  • log those usages and see if they ever pop up in production.
  • forget about it; lightly deprecate the function but don't change how it works

@colemanw
Copy link
Member

Well those test failures are certainly interesting!

@highfalutin
Copy link
Contributor Author

The test failures are interesting, yes! They definitely point to the type-sloppiness you were talking about.

I think, if anything, they tell us to remove the deprecation code (which is already commented out in master) and the comment above it. Let's drop the idea of making this function stricter than ??. It would just create a lot of unnecessary work.

However, the idea of making this function equivalent to ?? could stay on the table.

@highfalutin
Copy link
Contributor Author

Also @colemanw I hear you on the refactoring. I will review when I have a chance. I think what I understand now is that there is a slight chance of breaking things by refactoring when $default is not null. You'd have to figure out whether the calling code wants a distinction between not-set and null.

-- throwing this error would break a lot of things.
@highfalutin
Copy link
Contributor Author

For the record, here are the tests that failed when we turned on error-throwing for $lists that aren't array/ArrayAccess:

full list
api_v3_ACLPermissionTest.testEntitiesGetHookLimitingHookNoCheck with data set #1
api_v3_ACLPermissionTest.testEntitiesGetCoreACLLimitingHookNoCheck with data set #1
api_v3_ACLPermissionTest.testEntitiesGetCoreACLLimitingCheck with data set #1
api_v3_ContactTest.testMergeOrganizations
api_v3_ContactTest.testContactGetWithGroupTitle
api_v3_ContactTest.testContactGetFromGroup
api_v3_ContactTest.testSmartGroupsForRelatedContacts
api_v3_ContributionPageTest.testSubmit
api_v3_ContributionPageTest.testSubmitZeroDollar
api_v3_ContributionPageTest.testSubmitNewBillingNameData
api_v3_ContributionPageTest.testSubmitNewBillingNameDoNotOverwrite
api_v3_ContributionPageTest.testSubmitRecurMultiProcessorInstantPayment
api_v3_ContributionPageTest.testSubmitMembershipBlockNotSeparatePayment
api_v3_ContributionPageTest.testSubmitMembershipBlockNotSeparatePaymentProcessorInstantRenew
api_v3_ContributionPageTest.testSubmitMembershipBlockNotSeparatePaymentWithEmail
api_v3_ContributionPageTest.testSubmitMembershipBlockNotSeparatePaymentZeroDollarsWithEmail
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentPayLaterWithEmail
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePayment
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentWithPayLater
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentWithEmail
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentZeroDollarsPayLaterWithEmail
api_v3_ContributionPageTest.testSubmitMembershipBlockTwoTypesIsSeparatePayment
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNow
api_v3_ContributionPageTest.testSubmitPaymentProcessorFailure
api_v3_ContributionPageTest.testSubmitMembershipPriceSetPaymentPaymentProcessorRecurInstantPaymentYear
api_v3_ContributionPageTest.testSubmitMembershipPriceSetPaymentPaymentProcessorRecurInstantPaymentMonth
api_v3_ContributionPageTest.testSubmitMembershipComplexQuickConfigPaymentPaymentProcessorRecurInstantPayment
api_v3_ContributionPageTest.testSubmitMembershipComplexPriceSetPaymentPaymentProcessorRecurInstantPayment
api_v3_ContributionPageTest.testSubmitMembershipPriceSetPaymentPaymentProcessorSeparatePaymentRecurInstantPayment
api_v3_ContributionPageTest.testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed
api_v3_ContributionPageTest.testSubmitMembershipIsSeparatePaymentNotRecur
api_v3_ContributionPageTest.testSubmitMultiIntervalMembershipContributionPage
api_v3_ContributionPageTest.testSubmitPledgePaymentPaymentProcessorRecurFuturePayment
api_v3_ContributionPageTest.testSubmitPledgePayment
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNowChargesCorrectAmounts with data set #0
api_v3_ContributionPageTest.testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNowChargesCorrectAmounts with data set #1
api_v3_ContributionPageTest.testSubmitContributionPageWithPriceSet with data set #0
api_v3_ContributionPageTest.testSubmitContributionPageWithPriceSet with data set #1
api_v3_ContributionPageTest.testSubmitContributionPageWithPriceSetQuantity with data set #0
api_v3_ContributionPageTest.testSubmitContributionPageWithPriceSetQuantity with data set #1
api_v3_ContributionTest.testCompleteTransaction
api_v3_ContributionTest.testCompleteTransactionEuro
api_v3_ContributionTest.testPayLater
api_v3_ContributionTest.testBillingAddress
api_v3_ContributionTest.testCompleteTransactionFeeAmount
api_v3_ContributionTest.testRepeatTransaction
api_v3_ContributionTest.testRepeatTransactionWithCustomData
api_v3_ContributionTest.testRepeatTransactionLineItems
api_v3_ContributionTest.testRepeatTransactionIsTest
api_v3_ContributionTest.testRepeatTransactionPassedInStatus
api_v3_ContributionTest.testRepeatTransactionAcceptRecurID
api_v3_ContributionTest.testRepeatTransactionTestRecurId
api_v3_ContributionTest.testRepeatTransactionMembershipRenewCompletedContribution
api_v3_ContributionTest.testRepeattransactionRenewMembershipOldMembership
api_v3_ContributionTest.testRepeatTransactionAlteredAmount
api_v3_ContributionTest.testRepeatTransactionPassedInFinancialType
api_v3_ContributionTest.testContributionOrder
api_v3_ContributionTest.testRepeatTransactionPassedInFinancialTypeTwoLineItems
api_v3_ContributionTest.testRepeatTransactionUpdatedFinancialType
api_v3_ContributionTest.testRepeatTransactionPassedInCampaign
api_v3_ContributionTest.testRepeatTransactionUpdatedCampaign
api_v3_ContributionTest.testRepeatTransactionUpdatedFinancialTypeAndNotEquals
api_v3_ContributionTest.testCompleteTransactionNetAmountOK
api_v3_ContributionTest.testCompleteTransactionWithReceiptDateSet
api_v3_ContributionTest.testCompleteTransactionForRecurring
api_v3_ContributionTest.testCompleteTransactionWithEmailReceiptInputTrue
api_v3_ContributionTest.testCompleteTransactionWithTestTemplate
api_v3_ContributionTest.testCompleteTransactionContributionPageFromAddress
api_v3_ContributionTest.testCompleteTransactionUpdatePledgePayment
api_v3_ContributionTest.testRepeatTransactionWithPledgePayment
api_v3_ContributionTest.testCompleteTransactionWithParticipantRecord
api_v3_ContributionTest.testCompleteTransactionMembershipPriceSet
api_v3_ContributionTest.testPendingToCompleteContribution
api_v3_ContributionTest.testCompleteTransactionMembershipPriceSetTwoTerms
api_v3_ContributionTest.testSendMail
api_v3_ContributionTest.testSendConfirmationPayLater
api_v3_ContributionTest.testSendMailEvent
api_v3_ContributionTest.testRepeatTransactionWithNonCreditCardDefault
api_v3_ContributionTest.testRepeatTransactionMembershipCreatePendingContribution
api_v3_ContributionTest.testSendMailWithAPISetFromDetails
api_v3_ContributionTest.testSendMailWithNoFromSetFallToDomain
api_v3_ContributionTest.testSendMailWithRepeatTransactionAPIFalltoDomain
api_v3_ContributionTest.testSendMailWithRepeatTransactionAPIFalltoContributionPage
api_v3_ContributionTest.testSendMailWithRepeatTransactionAPIFalltoSystemFromNoDefaultFrom
api_v3_ContributionTest.testRepeatTransactionWithDifferenceCurrency
api_v3_ContributionTest.testRepeatContributionWithTaxAmount
api_v3_ContributionTest.testPaymentDontChangeReceiveDate
api_v3_ContributionTest.testPaymentVerifyPaymentInstrumentChange
api_v3_ContributionTest.testCheckTaxAmount with data set #0
api_v3_ContributionTest.testCheckTaxAmount with data set #1
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #1
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #2
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #3
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #4
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #6
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #7
api_v3_ContributionTest.testRepeatTransactionMembershipRenewContributionNotCompleted with data set #8
api_v3_ContributionTest.testCompleteTransactionSetStatusToInProgress with data set #0
api_v3_ContributionTest.testCompleteTransactionSetStatusToInProgress with data set #1
api_v3_ContributionTest.testCompleteTransactionSetStatusToInProgress with data set #2
api_v3_ContributionTest.testCompleteTransactionSetStatusToInProgress with data set "receive_date_includes_time"
api_v3_ContributionTest.testRepeatTransactionUpdateNextSchedContributionDate with data set "receive_date_includes_time_with_installments"
api_v3_ContributionTest.testRepeatTransactionUpdateNextSchedContributionDate with data set "receive_date_includes_time_no_installments"
api_v3_FinancialTypeACLTest.testMembershipTypeACLFinancialTypeACL
api_v3_JobProcessMembershipTest.testByDefaultTestsAreExcluded
api_v3_JobProcessMembershipTest.testByDefaultInactiveAreExcluded
api_v3_JobProcessMembershipTest.testByDefaultGraceIsConsidered
api_v3_JobProcessMembershipTest.testByDefaultPendingIsExcluded
api_v3_JobProcessMembershipTest.testByDefaultDeceasedIsExcluded
api_v3_JobProcessMembershipTest.testIncludingTestMembershipsExcludesPending
api_v3_JobProcessMembershipTest.testIncludingTestMembershipsConsidersGrace
api_v3_JobProcessMembershipTest.testIncludingTestMembershipsIgnoresInactive
api_v3_JobProcessMembershipTest.testIncludingTestMembershipsActuallyIncludesThem
api_v3_JobProcessMembershipTest.testIncludingTestMembershipsStillIgnoresDeceased
api_v3_JobProcessMembershipTest.testIncludingInactiveMembershipTypesStillExcludesPending
api_v3_JobProcessMembershipTest.testIncludingInactiveMembershipTypesConsidersGrace
api_v3_JobProcessMembershipTest.testIncludingInactiveMembershipTypesConsidersInactive
api_v3_JobProcessMembershipTest.testIncludingInactiveMembershipTypesStillIgnoresTests
api_v3_JobProcessMembershipTest.testMembershipTypeDeceasedIsExcluded
api_v3_JobProcessMembershipTest.testSpecifyingTheStatusIdsToExcludeStillExcludesDeceased
api_v3_JobProcessMembershipTest.testSpecifyingTheStatusIdsToExcludeStillExcludesTests
api_v3_JobProcessMembershipTest.testSpecifyingTheStatusIdsToExcludeStillExcludesInactive
api_v3_JobProcessMembershipTest.testSpecifyingTheStatusIdsToExcludeGraceIsIncludedByDefault
api_v3_JobProcessMembershipTest.testSpecifyingTheStatusIdsToExcludePendingIsExcludedByDefault
api_v3_JobTest.testCallSendReminderSuccessMoreThanDefaultLimit
api_v3_JobTest.testCallSendReminderLimitToSMS
api_v3_JobTest.testCallSendReminderLimitToSMSWithDeletedProvider
api_v3_JobTest.testBatchMergeWithAssets
api_v3_JobTest.testProcessMembershipDeceased
api_v3_JobTest.testProcessMembershipNoDeceasedStatus
api_v3_JobTest.testProcessMembershipUpdateStatus
api_v3_JobTest.testProcessMembershipIsOverrideNotNullNot1either
api_v3_JobTest.testMailReportForPrint
api_v3_JobTest.testMailReportForPdf
api_v3_JobTest.testMailReportForCsv
api_v3_MailingTest.testMailerSendTest_email
api_v3_MailingTest.testMailerSendTest_group
api_v3_MailingTest.testUnsubscribeGroupList
api_v3_MailingTest.testMailerStats
api_v3_MailingTest.testUrlWithMissingTrackingHash
api_v3_MailingTest.testTrackableURLWithUnicodeSign
api_v3_MembershipPaymentTest.testCreateEmptyParams
api_v3_MembershipPaymentTest.testCreate
api_v3_MembershipPaymentTest.testGet
api_v3_MembershipStatusTest.testGetEmptyParams
api_v3_MembershipStatusTest.testGet
api_v3_MembershipStatusTest.testGetLimit
api_v3_MembershipStatusTest.testCreateDuplicateName
api_v3_MembershipStatusTest.testCreateWithMissingRequired
api_v3_MembershipStatusTest.testCreate
api_v3_MembershipStatusTest.testUpdate
api_v3_MembershipStatusTest.testDeleteEmptyParams
api_v3_MembershipStatusTest.testDeleteWithMissingRequired
api_v3_MembershipStatusTest.testDelete
api_v3_MembershipStatusTest.testDeceasedMembershipInline
api_v3_MembershipStatusTest.testDeleteWithMembershipError
api_v3_MembershipTest.testMembershipDelete
api_v3_MembershipTest.testMembershipDeleteEmpty
api_v3_MembershipTest.testMembershipDeleteInvalidID
api_v3_MembershipTest.testMembershipDeletePreserveContribution
api_v3_MembershipTest.testMultipleMembershipsContribution
api_v3_MembershipTest.testContactMembershipsGet
api_v3_MembershipTest.testGetWithParamsContactId
api_v3_MembershipTest.testGetInSyntax
api_v3_MembershipTest.testGetInSyntaxOnContactID
api_v3_MembershipTest.testGetWithParamsMemberShipTypeId
api_v3_MembershipTest.testGetWithParamsMemberShipTypeIdContactID
api_v3_MembershipTest.testGetWithParamsMemberShipIdAndCustom
api_v3_MembershipTest.testGet
api_v3_MembershipTest.testGetWithId
api_v3_MembershipTest.testGetOnlyActive
api_v3_MembershipTest.testGetNoContactExists
api_v3_MembershipTest.testGetWithRelationship
api_v3_MembershipTest.testCreateWithRelationship
api_v3_MembershipTest.testCreateWithSpouseRelationship
api_v3_MembershipTest.testMembershipGetWithReturn
api_v3_MembershipTest.testCreatePending
api_v3_MembershipTest.testCreatePendingWithSkipStatusCalc
api_v3_MembershipTest.testCreateOverrideNoStatus
api_v3_MembershipTest.testMembershipCreateMissingRequired
api_v3_MembershipTest.testMembershipCreate
api_v3_MembershipTest.testMembershipCreateWithInvalidContact
api_v3_MembershipTest.testCreateWithCustom
api_v3_MembershipTest.testSearchWithCustomDataCRM16036
api_v3_MembershipTest.testMembershipCreateUpdateWithIdNoContact
api_v3_MembershipTest.testMembershipCreateUpdateWithIdNoDates
api_v3_MembershipTest.testMembershipCreateUpdateWithIdNoDatesNoType
api_v3_MembershipTest.testMembershipCreateUpdateWithIDAndSource
api_v3_MembershipTest.testUpdateWithCustom
api_v3_MembershipTest.testMembershipUpdateCreateHookCRM15746
api_v3_MembershipTest.testMembershipCreateInvalidMemData
api_v3_MembershipTest.testMembershipCreateWithMemContact
api_v3_MembershipTest.testMembershipCreateValidMembershipTypeString
api_v3_MembershipTest.testMembershipCreateInValidMembershipTypeString
api_v3_MembershipTest.testEmptyJoinDate
api_v3_MembershipTest.testEmptyStartDateFixed
api_v3_MembershipTest.testEmptyStartEndDateFixedOneYear
api_v3_MembershipTest.testEmptyStartEndDateFixedMultiYear
api_v3_MembershipTest.testMembershipJoinDateFixed
api_v3_MembershipTest.testFixedMultiYearDateSetTwoEmptyStartEndDate
api_v3_MembershipTest.testFixedMultiYearDateSetTwoEmptyEndDate
api_v3_MembershipTest.testFixedSingleYearDateSetTwoEmptyStartEndDate
api_v3_MembershipTest.testFixedSingleYearDateSetTwoEmptyEndDate
api_v3_MembershipTest.testFixedSingleYearDateSetThreeEmptyEndDate
api_v3_MembershipTest.testFixedSingleYearDateSetThreeEmptyStartEndDate
api_v3_MembershipTest.testFixedMultiYearDateSetThreeEmptyEndDate
api_v3_MembershipTest.testFixedMultiYearDateSetThreeEmptyStartEndDate
api_v3_MembershipTest.testEmptyStartDateRolling
api_v3_MembershipTest.testEmptyEndDateFixed
api_v3_MembershipTest.testEmptyEndDateRolling
api_v3_MembershipTest.testMembershipDatesNotOverridden
api_v3_MembershipTest.testMultipleMembershipContribution
api_v3_MembershipTest.testGetOptionsMembershipTypeID
api_v3_MembershipTest.testMembershipCreateWithId with data set "APIv3"
api_v3_MembershipTest.testMembershipCreateWithId with data set "APIv4"
api_v3_MembershipTypeTest.testCreateMembershipTypeAutoRenewBool
api_v3_MembershipTypeTest.testDeleteRelationshipTypesUsedByMembershipType
api_v3_MembershipTypeTest.testMembershipTypeGetList
api_v3_MembershipTypeTest.testEnableMembershipTypeOnContributionPage
api_v3_MembershipTypeTest.testGet with data set "APIv3"
api_v3_MembershipTypeTest.testGet with data set "APIv4"
api_v3_MembershipTypeTest.testCreate with data set "APIv3"
api_v3_MembershipTypeTest.testCreate with data set "APIv4"
api_v3_MembershipTypeTest.testCreateWithoutDomainID with data set "APIv3"
api_v3_MembershipTypeTest.testCreateWithoutDomainID with data set "APIv4"
api_v3_MembershipTypeTest.testUpdate with data set "APIv3"
api_v3_MembershipTypeTest.testUpdate with data set "APIv4"
api_v3_MembershipTypeTest.testDelete with data set "APIv3"
api_v3_MembershipTypeTest.testDelete with data set "APIv4"
api_v3_OrderTest.testAddOrderForMembership
api_v3_OrderTest.testAddOrderForParticipant
api_v3_OrderTest.testAddOrderWithLineItems
api_v3_OrderTest.testCreateWithChainedPayment
api_v3_OrderTest.testOrderWithMixedTax
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #0
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #1
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #2
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #3
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #4
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #5
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #6
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #7
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #8
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #9
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #10
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #11
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #12
api_v3_OrderTest.testAddOrderForMembershipWithDates with data set #13
api_v3_PaymentTest.testMultiplePaymentsForContribution
api_v3_PaymentTest.testPaymentSendContributionReceipt
api_v3_PaymentTest.testPaymentEmailReceiptFullyPaid
api_v3_PaymentTest.testCreatePaymentNoLineItems
api_v3_PaymentTest.testCreatePaymentLineItems
api_v3_PaymentTest.testCreatePaymentPayLater
api_v3_PaymentTest.testCreatePaymentMultipleTrxnID
api_v3_PaymentTest.testCreatePaymentOnFailedContribution
api_v3_PaymentTest.testCreatePaymentPayLaterPartialPayment
api_v3_PaymentTest.testPaymentCreateTrxnIdAndDates
api_v3_PriceFieldValueTest.testCreatePriceFieldValue
api_v3_PriceFieldValueTest.testGetBasicPriceFieldValue
api_v3_PriceFieldValueTest.testDeletePriceFieldValue
api_v3_PriceFieldValueTest.testGetFieldsPriceFieldValue
api_v3_PriceFieldValueTest.testCreatePriceFieldValuewithMultipleTerms
api_v3_PriceFieldValueTest.testGetPriceFieldValuewithMultipleTerms
api_v3_PriceFieldValueTest.testCreatePriceFieldValueWithDisabledFinancialType
api_v3_PriceFieldValueTest.testCreatePriceFieldValueAsDefault
api_v3_ProfileTest.testProfileGetWithoutProfileId
api_v3_ProfileTest.testProfileGetInvalidProfileId
api_v3_ProfileTest.testProfileGet
api_v3_ProfileTest.testProfileGetWithAddressCustomData
api_v3_ProfileTest.testProfileGetMultiple
api_v3_ProfileTest.testProfileGetBillingUseIsBillingLocation
api_v3_ProfileTest.testProfileGetMultipleHasBillingLocation
api_v3_ProfileTest.testProfileGetBillingEmptyContact
api_v3_ProfileTest.testContactActivityGetWithoutActivityId
api_v3_ProfileTest.testContactActivityGetWrongActivityId
api_v3_ProfileTest.testContactActivityGetWrongActivityType
api_v3_ProfileTest.testContactActivityGetSuccess
api_v3_ProfileTest.testGetFields
api_v3_ProfileTest.testGetFieldsParticipantProfile
api_v3_ProfileTest.testGetFieldsMembershipBatchProfile
api_v3_ProfileTest.testGetFieldsAllProfiles
api_v3_ProfileTest.testProfileSubmitWithoutProfileId
api_v3_ProfileTest.testProfileSubmitInvalidProfileId
api_v3_ProfileTest.testProfileSubmitCheckProfileRequired
api_v3_ProfileTest.testProfileSubmit
api_v3_ProfileTest.testProfileSubmitCheckCaching
api_v3_ProfileTest.testMembershipGetFieldsOrder
api_v3_ProfileTest.testProfileSubmitMembershipBatch
api_v3_ProfileTest.testLegacySet
api_v3_ProfileTest.testContactActivitySubmitWithoutActivityId
api_v3_ProfileTest.testContactActivitySubmitWrongActivityId
api_v3_ProfileTest.testContactActivitySubmitWrongActivityType
api_v3_ProfileTest.testContactActivitySubmitSuccess
api_v3_ProfileTest.testProfileApplyWithoutProfileId
api_v3_ProfileTest.testProfileApplyInvalidProfileId
api_v3_ProfileTest.testProfileApply
api_v3_ProfileTest.testSubmitWithTags
api_v3_ProfileTest.testSubmitWithNote
api_v3_ProfileTest.testSubmitGreetingFields
api_v3_RelationshipTest.testGetRelationshipByMembershipTypeDAO with data set "APIv3"
api_v3_RelationshipTest.testGetRelationshipByMembershipTypeDAO with data set "APIv4"
api_v3_RelationshipTest.testCreateRelatedMembership with data set "APIv3"
api_v3_RelationshipTest.testCreateRelatedMembership with data set "APIv4"
api_v3_ReportTemplateTest.testContributionSummaryWithTwoGroups
api_v3_ReportTemplateTest.testContributionSummaryWithSingleContactsInTwoGroups
api_v3_ReportTemplateTest.testContributionSummaryWithTwoGroupsWithIntersection
api_v3_ReportTemplateTest.testContributionAggregateByRelationship
api_v3_ReportTemplateTest.testReportTemplateGetRowsAllReports with data set #40
api_v3_ReportTemplateTest.testReportTemplateGetRowsAllReportsACL with data set #40
api_v3_ReportTemplateTest.testReportTemplateGetStatisticsAllReports with data set #40
api_v3_ReportTemplateTest.testContributionSummaryWithSmartGroupFilter with data set #0
api_v3_ReportTemplateTest.testContributionSummaryWithSmartGroupFilter with data set #1
api_v3_ReportTemplateTest.testContributionSummaryWithSmartGroupFilter with data set #2
api_v3_ReportTemplateTest.testContributionSummaryWithSmartGroupFilter with data set #3
api_v3_ReportTemplateTest.testContributionSummaryWithNotINSmartGroupFilter with data set #0
api_v3_ReportTemplateTest.testContributionSummaryWithNotINSmartGroupFilter with data set #1
api_v3_ReportTemplateTest.testContributionSummaryWithNotINSmartGroupFilter with data set #2
api_v3_ReportTemplateTest.testContributionSummaryWithNotINSmartGroupFilter with data set #3
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilter with data set #0
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilter with data set #1
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilter with data set #2
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilter with data set #3
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilterWithACL with data set #0
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilterWithACL with data set #1
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilterWithACL with data set #2
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilterWithACL with data set #3
api_v3_ReportTemplateTest.testReportsWithNonSmartGroupFilterWithACL with data set #4
api_v3_ReportTemplateTest.testReportsWithNoTInSmartGroupFilter with data set #0
api_v3_ReportTemplateTest.testReportsWithNoTInSmartGroupFilter with data set #1
api_v3_ReportTemplateTest.testReportsWithNoTInSmartGroupFilter with data set #2
api_v3_ReportTemplateTest.testReportsWithNoTInSmartGroupFilter with data set #3
api_v3_SavedSearchTest.testCreateSavedSearchWithSmartGroup
api_v3_SavedSearchTest.testSavedSearchIsDeletedWhenSmartGroupIs
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #4
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #14
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #16
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #22
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #42
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #46
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #47
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #49
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #50
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #51
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #53
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #54
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #55
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #56
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #57
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #58
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #59
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #60
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #61
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #62
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #63
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #64
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #65
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #66
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #67
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #68
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #69
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #70
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #71
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #72
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #73
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #74
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #75
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #76
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #77
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #78
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #79
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #80
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #81
api_v3_SyntaxConformanceTest.testCustomDataGet with data set #82
api_v3_SyntaxConformanceTest.testByIDGet with data set #4
api_v3_SyntaxConformanceTest.testByIDGet with data set #11
api_v3_SyntaxConformanceTest.testByIDGet with data set #18
api_v3_SyntaxConformanceTest.testByIDGet with data set #20
api_v3_SyntaxConformanceTest.testByIDGet with data set #35
api_v3_SyntaxConformanceTest.testByIDGet with data set #62
api_v3_SyntaxConformanceTest.testByIDGet with data set #65
api_v3_SyntaxConformanceTest.testByIDGet with data set #66
api_v3_SyntaxConformanceTest.testByIDGet with data set #67
api_v3_SyntaxConformanceTest.testByIDGet with data set #72
api_v3_SyntaxConformanceTest.testByIDGet with data set #73
api_v3_SyntaxConformanceTest.testByIDGet with data set #74
api_v3_SyntaxConformanceTest.testByIDGet with data set #85
api_v3_SyntaxConformanceTest.testByIDGet with data set #90
api_v3_SyntaxConformanceTest.testByIDGet with data set #94
api_v3_SyntaxConformanceTest.testByIDGet with data set #97
api_v3_SyntaxConformanceTest.testLimit with data set #4
api_v3_SyntaxConformanceTest.testLimit with data set #10
api_v3_SyntaxConformanceTest.testLimit with data set #17
api_v3_SyntaxConformanceTest.testLimit with data set #19
api_v3_SyntaxConformanceTest.testLimit with data set #34
api_v3_SyntaxConformanceTest.testLimit with data set #58
api_v3_SyntaxConformanceTest.testLimit with data set #62
api_v3_SyntaxConformanceTest.testLimit with data set #63
api_v3_SyntaxConformanceTest.testLimit with data set #64
api_v3_SyntaxConformanceTest.testLimit with data set #65
api_v3_SyntaxConformanceTest.testLimit with data set #69
api_v3_SyntaxConformanceTest.testLimit with data set #70
api_v3_SyntaxConformanceTest.testLimit with data set #71
api_v3_SyntaxConformanceTest.testLimit with data set #80
api_v3_SyntaxConformanceTest.testLimit with data set #81
api_v3_SyntaxConformanceTest.testLimit with data set #85
api_v3_SyntaxConformanceTest.testLimit with data set #89
api_v3_SyntaxConformanceTest.testLimit with data set #92
api_v3_SyntaxConformanceTest.testSqlOperators with data set #4
api_v3_SyntaxConformanceTest.testSqlOperators with data set #10
api_v3_SyntaxConformanceTest.testSqlOperators with data set #16
api_v3_SyntaxConformanceTest.testSqlOperators with data set #18
api_v3_SyntaxConformanceTest.testSqlOperators with data set #58
api_v3_SyntaxConformanceTest.testSqlOperators with data set #62
api_v3_SyntaxConformanceTest.testSqlOperators with data set #63
api_v3_SyntaxConformanceTest.testSqlOperators with data set #64
api_v3_SyntaxConformanceTest.testSqlOperators with data set #65
api_v3_SyntaxConformanceTest.testSqlOperators with data set #69
api_v3_SyntaxConformanceTest.testSqlOperators with data set #70
api_v3_SyntaxConformanceTest.testSqlOperators with data set #71
api_v3_SyntaxConformanceTest.testSqlOperators with data set #80
api_v3_SyntaxConformanceTest.testSqlOperators with data set #81
api_v3_SyntaxConformanceTest.testSqlOperators with data set #86
api_v3_SyntaxConformanceTest.testSqlOperators with data set #90
api_v3_SyntaxConformanceTest.testSqlOperators with data set #93
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #4
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #11
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #18
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #20
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #35
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #62
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #65
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #66
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #67
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #72
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #73
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #74
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #85
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #90
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #94
api_v3_SyntaxConformanceTest.testByIDAlias_get with data set #97
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #2
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #7
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #9
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #20
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #39
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #40
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #44
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #45
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #47
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #54
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #58
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #61
api_v3_SyntaxConformanceTest.testCreateSingleValueAlter with data set #64
api\v4\Action\GetActionsTest.testActionPermissionsOverride
api\v4\Entity\ConformanceTest.testConformance with data set "Membership"
api\v4\Entity\ConformanceTest.testConformance with data set "UFField"
api\v4\Entity\GroupTest.testSmartGroupCache
api\v4\Entity\MembershipTest.testUpdateWeights
api\v4\Entity\WorkflowMessageTest.testRenderExamples with data set "workflow/contribution_recurring_edit/AlexCancelled"
Civi\Token\TokenProcessorTest.testRenderDoubleUrl
Civi\Token\TokenProcessorTest.testRenderContributionRecurTokenFromMembership
Civi\Token\TokenProcessorTest.testFilters with data set "HtmlMessages with HtmlData"
Civi\Token\TokenProcessorTest.testFilters with data set "HtmlMessages with TextData"
CivicrmUpgradeTest.CivicrmUpgradeTest.5_39_1-setupsh_mysql_bz2
CivicrmUpgradeTest.CivicrmUpgradeTest.5_45_3-setupsh_mysql_bz2
CivicrmUpgradeTest.CivicrmUpgradeTest.5_47_2-tz_mysql_bz2
CancelTest.testPaypalProCancel
CancelTest.testCancelFromContributionForm
Civi\FlexMailer\FlexMailerSystemTest.testHtmlWithOpenAndUrlTracking
Civi\FlexMailer\FlexMailerSystemTest.testUrlTracking with data set #1
Civi\FlexMailer\FlexMailerSystemTest.testUrlTracking with data set #5
Civi\FlexMailer\FlexMailerSystemTest.testUrlTracking with data set "url_trackin_enabled"
Civi\FlexMailer\FlexMailerSystemTest.testUrlTracking with data set #8
Civi\Financialacls\LineItemTest.testLineItemApiPermissions with data set "APIv3"
Civi\Financialacls\LineItemTest.testLineItemApiPermissions with data set "APIv4"
Civi\Financialacls\MembershipTypesTest.testMembershipTypesHook

@colemanw colemanw changed the title WIP: Simplify CRM_Utils_Array::value() CRM_Utils_Array::value - remove "todo" which we don't actually want to do Oct 14, 2023
@colemanw
Copy link
Member

Now there's a PR we can all agree on!

@colemanw colemanw merged commit 13ce26a into civicrm:master Oct 14, 2023
@colemanw
Copy link
Member

@highfalutin feel free to review any of these too :)

@highfalutin highfalutin deleted the nullcoalesce branch November 3, 2023 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants