CiviCRM Core issueshttps://lab.civicrm.org/dev/core/-/issues2018-10-14T22:43:57Zhttps://lab.civicrm.org/dev/core/-/issues/97Improve the process and documentation for "How to Contribute" so that Proposa...2018-10-14T22:43:57Zjustinfreeman (Agileware)Improve the process and documentation for "How to Contribute" so that Proposals can be discussed, reviewed and accepted (rejected) before a PR is createdCreating this issue to start the discussion about how we as a community can improve the process and documentation for "How to Contribute", the relevant pages are:
* https://docs.civicrm.org/dev/en/latest/core/contributing/
* https://doc...Creating this issue to start the discussion about how we as a community can improve the process and documentation for "How to Contribute", the relevant pages are:
* https://docs.civicrm.org/dev/en/latest/core/contributing/
* https://docs.civicrm.org/dev/en/latest/tools/issue-tracking/#guidelines
This specifically relates to adding new features to CiviCRM core or changing existing features in CiviCRM core (I'll just call these collectively "Proposal"). It could equally apply to CiviCRM extensions, since the approach is the same - just the ecosystem is more distributed.
The current documented process revolves around submitting a PR on Github with the associated code. The problem with this process is it has high potential to be rejected, because no prior process of discussion, review or approval has been sought for the Proposal. When you think about it the current state, it's a bit backwards. So this is incredibly frustrating for people wishing to contribute to the project and a huge waste of time. If the PR never had a chance of being accepted conceptually, then there is no point at all in spending time on writing code, testing it, documenting it etc. PRs cost money to produce and no one likes wasting money!
So the process change I would like to see is to move away from PRs being the initial step for the Proposal. The PR should be the resultant of the Proposal process.
A Proposal should be created in Gitlab (not a PR in Github). The reasoning for the change and the proposed approach for implementing the change should be documented with the Proposal.
The Proposal should be available for review and feedback on Gitlab for a set period of time, 2 to 4 weeks maximum (for example). This step is important, Proposals should not languish, unattended.
At the conclusion of that time, the Proposal should be: Accepted, Rejected or Require Further Review; by a **new team** (CiviCRM Proposal Team) responsible for reviewing Proposals. **This should not be the responsibility of the existing CiviCRM Core Team, which are currently under resourced and over worked**. For the CiviCRM Proposal Team, we need new people to step up and own this process, so that the work load can be shared between Proposals and PRs. CiviCRM Core Team should not have to do both processes - we want to reduce their work load. This is why I think establishing a new CiviCRM Proposal Team to review Proposals is fundamental to this improvement.
If the Proposal is Accepted then related PR(s) can be created and they individually can go through the code review process.
The key change here is that the PR(s) for this Proposal will be accepted following passing code reviews. Any debate about the merits of the change or new features should occur on the Proposal, during the Proposal review stage. Not during a review of the PRs.
Proposals are for planning and implementation.
PRs are for code management.
This issue has also been raised on separate the discussion being had on this PR, https://github.com/civicrm/civicrm-core/pull/11956#issuecomment-385849221
Thanks @eileen
Let's discuss!justinfreeman (Agileware)justinfreeman (Agileware)https://lab.civicrm.org/dev/core/-/issues/98Searching by any Address fields with location type other than primary throw D...2018-05-03T18:23:08ZMonish DebSearching by any Address fields with location type other than primary throw DB errorSteps to replicate:
1. Go to `Search Builder`
2. Choose Contact >> Street Address (or any address field) >> Home (as location type) >> NOT EMPTY (or any other operator)
3. Submit
Throw DB Error:
```
Database Error Code: Unknown column '...Steps to replicate:
1. Go to `Search Builder`
2. Choose Contact >> Street Address (or any address field) >> Home (as location type) >> NOT EMPTY (or any other operator)
3. Submit
Throw DB Error:
```
Database Error Code: Unknown column 'Home-location_type.id' in 'field list', 1054
Additional Details:
Array
(
[callback] => Array
(
[0] => CRM_Core_Error
[1] => handle
)
[code] => -19
[message] => DB Error: no such field
[mode] => 16
[debug_info] => SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, `Home-location_type`.id as `Home-location_type_id`, `Home-location_type`.name as `Home-location_type`, `Home-address`.id as `Home-address_id`, `Home-address`.street_address as `Home-street_address` FROM civicrm_contact contact_a LEFT JOIN civicrm_address `Home-address` ON ( contact_a.id = `Home-address`.contact_id ) and `Home-address`.location_type_id = 1 WHERE ( ( (NULLIF(LOWER(`Home-address`.street_address), '') IS NOT NULL) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'Home-location_type.id' in 'field list']
[type] => DB_Error
[user_info] => SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, `Home-location_type`.id as `Home-location_type_id`, `Home-location_type`.name as `Home-location_type`, `Home-address`.id as `Home-address_id`, `Home-address`.street_address as `Home-street_address` FROM civicrm_contact contact_a LEFT JOIN civicrm_address `Home-address` ON ( contact_a.id = `Home-address`.contact_id ) and `Home-address`.location_type_id = 1 WHERE ( ( (NULLIF(LOWER(`Home-address`.street_address), '') IS NOT NULL) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'Home-location_type.id' in 'field list']
[to_string] => [db_error: message="DB Error: no such field" code=-19 mode=callback callback=CRM_Core_Error::handle prefix="" info="SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, `Home-location_type`.id as `Home-location_type_id`, `Home-location_type`.name as `Home-location_type`, `Home-address`.id as `Home-address_id`, `Home-address`.street_address as `Home-street_address` FROM civicrm_contact contact_a LEFT JOIN civicrm_address `Home-address` ON ( contact_a.id = `Home-address`.contact_id ) and `Home-address`.location_type_id = 1 WHERE ( ( (NULLIF(LOWER(`Home-address`.street_address), '') IS NOT NULL) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'Home-location_type.id' in 'field list']"]
)
```Monish DebMonish Debhttps://lab.civicrm.org/dev/core/-/issues/99Search builder doesn't retain selected (boolean) option after searching2018-05-06T01:04:55ZMonish DebSearch builder doesn't retain selected (boolean) option after searchingSteps to replicate:
1. Go to `Search Builder`
2. Choose Contact >> Do not email (or any other Boolean field) >> = >> Select `Yes`
3. Submit
After submit, you will see the select option is replaced by text field with 1 as it's value:
![t...Steps to replicate:
1. Go to `Search Builder`
2. Choose Contact >> Do not email (or any other Boolean field) >> = >> Select `Yes`
3. Submit
After submit, you will see the select option is replaced by text field with 1 as it's value:
![test-multiple-before](/uploads/eea36e30389dcb871e0765137fc81150/test-multiple-before.gif)5.3.0Monish DebMonish Debhttps://lab.civicrm.org/dev/core/-/issues/100Membership Detail report throw DB error2018-05-25T05:45:46ZyashodhaMembership Detail report throw DB errorMembership Detail report throw DB error due to acl clause applied twice.Membership Detail report throw DB error due to acl clause applied twice.5.3.0yashodhayashodhahttps://lab.civicrm.org/dev/core/-/issues/101Allow further customization of search form in hooks2018-06-18T20:13:57ZmichaelAllow further customization of search form in hooksThe contact search form uses the template `templates/CRM/Contact/Form/Search/Criteria/Basic.tpl`. In the template there are already some conditionals to hide certain fields, such as
```
{if $form.group}
<td>
...
{/if}
```
However o...The contact search form uses the template `templates/CRM/Contact/Form/Search/Criteria/Basic.tpl`. In the template there are already some conditionals to hide certain fields, such as
```
{if $form.group}
<td>
...
{/if}
```
However only some fields are covered. For an extension developer who wants to hide more fields here it is difficult without causing warnings or breaking the layout.
It is now possible to override the fields on the basic search template by altering the fields array assigned to the template in a hook
---
Core PR: https://github.com/civicrm/civicrm-core/pull/120785.4.0https://lab.civicrm.org/dev/core/-/issues/102Rename Cache Templates from Contact Name to Contact ID2022-06-24T03:21:19ZjohnffRename Cache Templates from Contact Name to Contact IDIt is observed that smarty cache files are created for each contact with the name of the contact as the cached file's name. In our view it would be better from a Data Protection perspective for these to be contact ID numbers. This suppor...It is observed that smarty cache files are created for each contact with the name of the contact as the cached file's name. In our view it would be better from a Data Protection perspective for these to be contact ID numbers. This supports the "right to erasure" enforceable under GDPR - as users will not be likely to know that these cached files contain the contact's name it's possible that these could remain for some time.https://lab.civicrm.org/dev/core/-/issues/103Bug: extension forms do not display elements2018-05-08T03:02:59ZjohnffBug: extension forms do not display elementsIn Civi v5.0.0, forms generated by extension do not appear to be rendering elements. This was encountered with both a new and an old extension. There are no warnings or errors generated, and the form hook is being processed, just the ele...In Civi v5.0.0, forms generated by extension do not appear to be rendering elements. This was encountered with both a new and an old extension. There are no warnings or errors generated, and the form hook is being processed, just the elements are not being rendered.https://lab.civicrm.org/dev/core/-/issues/104Get Tests to pass on PHP7.22018-12-10T03:36:53ZseamusleeGet Tests to pass on PHP7.2This is a meta issue for getting our tests to run against PHP7.2 ping @monish.deb @eileen @tottenThis is a meta issue for getting our tests to run against PHP7.2 ping @monish.deb @eileen @totten5.10seamusleeseamusleehttps://lab.civicrm.org/dev/core/-/issues/105Manage PCP URL Wrong for the notification email under wordpress2018-05-15T07:19:09ZaniesshsethhManage PCP URL Wrong for the notification email under wordpress5.3.0https://lab.civicrm.org/dev/core/-/issues/3570When creating a CiviMail it is possible to select this mailing as a "previous...2023-06-26T19:32:24ZlolcodeWhen creating a CiviMail it is possible to select this mailing as a "previous mailing" in the recipients listWhen creating a CiviMail it is possible to select this mailing as a "previous mailing" in the recipients list. I have not tested what it does but it makes no sense from a user point of view.
To reproduce just name the mailing and then o...When creating a CiviMail it is possible to select this mailing as a "previous mailing" in the recipients list. I have not tested what it does but it makes no sense from a user point of view.
To reproduce just name the mailing and then open the recipients list. In fact before the mailing is named it still shows in the list but with the name "null".
![bug-first-mailing](/uploads/ea99f69608bb75993b467f1e77795480/bug-first-mailing.jpg)
![null-mailing](/uploads/61df71ab974462ffded69b02aba4046f/null-mailing.jpg)https://lab.civicrm.org/dev/core/-/issues/106Search builder error on contact, group 'equals', and possibly other operators2018-07-23T14:06:06ZAndryg8Search builder error on contact, group 'equals', and possibly other operatorsIn 5.0.0 and 5.0.2rc we are observing a bug when Search Builder is set with a line like this:
Contacts Groups = [any group]
The log shows as below. We have seen the same thing with other operators too.
The same error appears to b...In 5.0.0 and 5.0.2rc we are observing a bug when Search Builder is set with a line like this:
Contacts Groups = [any group]
The log shows as below. We have seen the same thing with other operators too.
The same error appears to be happening on the Drupal Civi 4.7 demo site.
Thanks
`May 08 18:57:44 [info] $Fatal Error Details = Array
(
[callback] => Array
(
[0] => CRM_Core_Error
[1] => handle
)
[code] => -19
[message] => DB Error: no such field
[mode] => 16
[debug_info] => SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`,
CONCAT_WS(',',
GROUP_CONCAT(DISTINCT IF(civicrm_group_contact.status = 'Added', civicrm_group_contact.group_id, '')),
GROUP_CONCAT(DISTINCT civicrm_group_contact_cache.group_id)
)
as groups FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-121` ON (contact_a.id = `civicrm_group_contact-121`.contact_id AND `civicrm_group_contact-121`.status IN ('Added')) WHERE ( ( ( ( `civicrm_group_contact-121`.group_id = 121 ) ) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'civicrm_group_contact.status' in 'field list']
[type] => DB_Error
[user_info] => SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`,
CONCAT_WS(',',
GROUP_CONCAT(DISTINCT IF(civicrm_group_contact.status = 'Added', civicrm_group_contact.group_id, '')),
GROUP_CONCAT(DISTINCT civicrm_group_contact_cache.group_id)
)
as groups FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-121` ON (contact_a.id = `civicrm_group_contact-121`.contact_id AND `civicrm_group_contact-121`.status IN ('Added')) WHERE ( ( ( ( `civicrm_group_contact-121`.group_id = 121 ) ) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'civicrm_group_contact.status' in 'field list']
[to_string] => [db_error: message="DB Error: no such field" code=-19 mode=callback callback=CRM_Core_Error::handle prefix="" info="SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`,
CONCAT_WS(',',
GROUP_CONCAT(DISTINCT IF(civicrm_group_contact.status = 'Added', civicrm_group_contact.group_id, '')),
GROUP_CONCAT(DISTINCT civicrm_group_contact_cache.group_id)
)
as groups FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-121` ON (contact_a.id = `civicrm_group_contact-121`.contact_id AND `civicrm_group_contact-121`.status IN ('Added')) WHERE ( ( ( ( `civicrm_group_contact-121`.group_id = 121 ) ) ) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ORDER BY UPPER(LEFT(contact_a.sort_name, 1)) asc [nativecode=1054 ** Unknown column 'civicrm_group_contact.status' in 'field list']"]
)
`https://lab.civicrm.org/dev/core/-/issues/107After creating a new case, the assignee for each activity must be selected ma...2022-09-13T05:03:46ZreneolivoAfter creating a new case, the assignee for each activity must be selected manually### Issue
After you create a new case multiples activities are created with it, but the assignee must be manually chosen for each one of them which takes considerable time since this must be done by editing each activity one at a time.
...### Issue
After you create a new case multiples activities are created with it, but the assignee must be manually chosen for each one of them which takes considerable time since this must be done by editing each activity one at a time.
![default-assignee-issue](/uploads/987455f62441d6f77bc1892b930b4a90/default-assignee-issue.png)
There are references for the roles and relationships that are interesting for the particular case, but those are there for reference, the assignee still must be selected manually.
### Solution
Allow administrators to define rules for selecting a default assignee for each one of the activities. The rules would be based on the following options:
* By relationship to case client (ex: parent, manager, or spouse of case client).
* User creating the case.
* Specific contact.
* No default assignee.
When creating a new case each case activity should be created and assigned based on these rules. The case manager could then modify the assignees as usual.
----
Core PR:
https://github.com/civicrm/civicrm-core/pull/11998https://lab.civicrm.org/dev/core/-/issues/108unable to create new event location without impacting other events2018-07-12T14:34:52Zlcdwebunable to create new event location without impacting other eventsto reproduce this issue:
* create an event. on the location tab, create a new location with the street address "test address 1"
* return to the manage event screen. click more > copy to copy the newly created event
* select the location...to reproduce this issue:
* create an event. on the location tab, create a new location with the street address "test address 1"
* return to the manage event screen. click more > copy to copy the newly created event
* select the location tab -- it will already have "test address 1" selected. click the option to "create new location" and add a street address "test address 2". save the event.
* return to the event management screen and click configure > location for the first event. note that the address now references "test address 2"
you should be able to create a new location for an event and it should have no effect on existing events that previously shared the location.lcdweblcdwebhttps://lab.civicrm.org/dev/core/-/issues/109Categorizing case types2022-08-12T05:03:24ZreneolivoCategorizing case types#### Issue
Currently case types can have a name, but can't be grouped by a common category. Right now you can have multiple case types dealing with vacancies, (Ex: Publish available position, Conduct interview with candidate, Start recr...#### Issue
Currently case types can have a name, but can't be grouped by a common category. Right now you can have multiple case types dealing with vacancies, (Ex: Publish available position, Conduct interview with candidate, Start recruitment campaign, etc.), but there's no way to tell that these case types belong in a common conceptual group that differentiates them from other case types.
#### Proposed solution
Adding a *category* field to the *CaseType* schema.
#### Use cases
* Separating the administration of case types, such as the ones from application/vacancies.
* Using the case category to run specific actions when a new case is created or it's closed. For example, if a case with the category "Funds Raising" is closed, send a special notification to the accounts department. (this would be implemented on the extension side).
#### Core PR
https://github.com/civicrm/civicrm-core/pull/12098https://lab.civicrm.org/dev/core/-/issues/110Fix in CRM-14065 for status/date mismatch warning on activities doesn't seem ...2019-03-26T04:18:10ZDaveDFix in CRM-14065 for status/date mismatch warning on activities doesn't seem to workAnd on the public demo it doesn't seem to work either. The problem is the use of setHours() in activityStatus in templates/CRM/Activity/Form/ActivityJS.tpl.
Where it says
` var
// Ignore time, only compare dates
today = new Date()....And on the public demo it doesn't seem to work either. The problem is the use of setHours() in activityStatus in templates/CRM/Activity/Form/ActivityJS.tpl.
Where it says
` var
// Ignore time, only compare dates
today = new Date().setHours(0,0,0,0),
activityStatusId = cj('#status_id').val();`
it should be
` var
// Ignore time, only compare dates
today = new Date(),
activityStatusId = cj('#status_id').val();
today.setHours(0,0,0,0);`
because setHours() returns a timestamp and updates the object directly, and doesn't return a new Date object.https://lab.civicrm.org/dev/core/-/issues/111Support Custom Data for MembershipType entity2019-05-15T04:24:49Zmattwiremjw@mjwconsult.co.ukSupport Custom Data for MembershipType entityConvert MembershipType form to use API (for custom data support): https://github.com/civicrm/civicrm-core/pull/12118Convert MembershipType form to use API (for custom data support): https://github.com/civicrm/civicrm-core/pull/12118https://lab.civicrm.org/dev/core/-/issues/112CiviCRM locking may not account for multiple CiviCRM sites per server2018-05-13T07:14:33ZxurizaemonCiviCRM locking may not account for multiple CiviCRM sites per server* [MySQL's `GET_LOCK()` uses server-wide lock names.](https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock)
* [CiviCRM's lock name generation does not seem to include the current CiviCRM site / DB name /...* [MySQL's `GET_LOCK()` uses server-wide lock names.](https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock)
* [CiviCRM's lock name generation does not seem to include the current CiviCRM site / DB name / identifier](https://github.com/eileenmcnaughton/civicrm-core/blob/b551edf53eff0019a9daed7cc950cf86f70f2e6f/CRM/Core/Lock.php#L111)
* Therefore, multiple CiviCRM sites on the same DB server may compete for the same lock names.
https://lab.civicrm.org/dev/core/-/issues/113Add new api handler 'current_domain' along the lines of 'user_contact_id'2022-06-13T01:56:11ZeileenAdd new api handler 'current_domain' along the lines of 'user_contact_id'Several api accept domain_id & in almost all cases the value passed is the current domain id. I think we should be able to set that as a default for api like membership type, instead of requiring it to be passed in as is currently the ca...Several api accept domain_id & in almost all cases the value passed is the current domain id. I think we should be able to set that as a default for api like membership type, instead of requiring it to be passed in as is currently the case.
With this we could change
```
function _civicrm_api3_membership_type_create_spec(&$params) {
// todo could set default here probably
$params['domain_id']['api.required'] = 1;
```
to
```
function _civicrm_api3_membership_type_create_spec(&$params) {
$params['domain_id']['api.default'] = 'current_domain';
```
We have a similar thing in place for 'user_contact_id' here
https://github.com/eileenmcnaughton/civicrm-core/blob/fee14197b427c1781e369e5bfd36816afad6d7ee/api/v3/utils.php#L2086 and I feel we could expand that piece of code.
Pinging @totten because Tim re-wrote that earlier handling of user_contact_id & may have some points he wishes to interjecthttps://lab.civicrm.org/dev/core/-/issues/114Email-Invoices fails since 4.7.31 because of invalid From-Addresses2018-05-16T02:43:17Zthomas_SYSTOPIAEmail-Invoices fails since 4.7.31 because of invalid From-AddressesReproduce:
1. Enable Tax and Invoicing (in "CiviContribute Component Settings")
2. Setup a From-Email-Adress
3. Create a Contribution
4. Use "Email Invoice" to send an Invoice.
You get: "**Validation failed for: from-email-address**"
T...Reproduce:
1. Enable Tax and Invoicing (in "CiviContribute Component Settings")
2. Setup a From-Email-Adress
3. Create a Contribution
4. Use "Email Invoice" to send an Invoice.
You get: "**Validation failed for: from-email-address**"
The reason could be found in CRM/Contribute/Form/Task/Invoice.php[460:465]:
```
$fromEmail = CRM_Core_BAO_Email::getFromEmail();
// from email address
if (isset($params['from_email_address'])) \{
$fromEmailAddress = CRM_Utils_Array::value($params['from_email_address'], $fromEmail);
}
```
The values of $fromEmail are html-escaped versions of the email-adresses. They might be useful for Select-Options in HTML-Forms. But they won't work for real email-headers.5.2.0https://lab.civicrm.org/dev/core/-/issues/115Proposal - create fields array standard & generic field template/s for it & f...2022-10-11T15:26:36ZeileenProposal - create fields array standard & generic field template/s for it & for fields, work towards generic entity form templateWe have a generalised issue where we want people to write extensions to alter CiviCRM but in many cases the way CiviCRM is structured makes that difficult and unmaintainable. As part of pushing people out to extensions we also need to wo...We have a generalised issue where we want people to write extensions to alter CiviCRM but in many cases the way CiviCRM is structured makes that difficult and unmaintainable. As part of pushing people out to extensions we also need to work to improve core code to support that purpose.
In the 5.x series we have made it easier for extension writers to store entity specific data by extending custom fields to (almost) all entities via the api*. However, it is still very difficult for extension writers to inject these fields, or other fields, into forms or to remove or re-order them. In general our approach has been to make things more metadata driven but we have not really standardised how to do this for templates. Conversely we already have examples in our code of templates that have been re-written to support output being modified by a php hook - (notably it is possible to alter the Billing fields on the payment form & the output columns in the contribution search from a php hook because metadata is assigned to the template & processed in the template) but we have not standardised those approaches into a recommendation.
To be clear - this proposal is NOT about going through all our forms and altering them to be more editable - it's about agreeing what we are working towards when we ARE editing forms. Currently it is possible to say
* "we are working towards replacing jcalendar.tpl with datepicker fields and when we touch date fields we should attempt to convert them"
* "we are working towards replacing non-metadata ways of adding fields to a form with addField and when we touch fields not added that way we should attempt to convert them"
Conversely we would say "if you are trying to fix the way a datefield is handling date defaults and the field is a jcalendar field we expect the fix to be converting it to a datepicker field rather than adding extra mangling for the legacy method".
In this case we would say
* "we are working towards assigning a standardised array of fields to a form & a tpl way of handling them and when we are working on a form we should seek to convert them"
(Generally we do require that PRs are improving the consistency & quality of our codebase & compliance with code-directions when we merge them)
I would note that complex forms like Contribution & Event forms might make poor candidates for tpl standardisation but a lot of our forms are simple settings forms or editing basic entities and these are good candidates for being generic & standardised. (This is allied with fixing the forms such that IF custom data is enabled on the entity THEN it can be altered via the form - which I will cover separately)
There are 2 open PRs which revolve around making tpls more generic, more metadata driven & more form-alterable
https://github.com/civicrm/civicrm-core/pull/12128/files#diff-1f76de158e02dfb7afa76303ef60e9ebR27
and https://github.com/civicrm/civicrm-core/pull/12078
The proposal would be that where it is possible to iterate through fields we assign them to the tpl in an array that looks like
```
$this-assign('entityFields', [
'field_1' => [
'name' => 'field_1',
'description' => ts("description to show below field"),
'help' => ['id' => 'id-field_1, 'file' => 'CRM/Contact/Form/Contact',
'is_add_translate_dialog' => 1,
],
'field_1' => ['name' => 'field_1'],
'money_field' => ['name' => 'money', 'formatter' => 'crmMoney'],
'weird_looking_field' => [
'name' => 'weird_looking_field',
'template' => CRM/Member/Form/MembershipType/weird_looking_field.tpl',
```
In practice some helpers would be involved in building the array so that fields like is_add_translate_dialog are derived from existing metadata. That would also potentially apply to keys like description, help & formatter. It is expected that if a field were to use a field specific template it would be under the path of the form.
The form template would then work towards looking more like
```
{foreach from=$entityFields item=fieldSpec}
{assign var=fieldName value=$fieldSpec.name}
<tr class="crm-{$entityInClassFormat}-form-block-{$fieldName}">
{include file="CRM/Core/Form/Field.tpl"}
</tr>
{/foreach}
```
With the tpl being
```
{if $fieldSpec.template}
{include file=$fieldSpec.template}
{else}
<td class="label">{$form.$fieldName.label}
{if $fieldSpec.help}{assign var=help value=$fieldSpec.help}{capture assign=helpFile}{if $fieldSpec.help}
{$fieldSpec.help}
{else}''{/if}
{/capture}{help id=$help.id file=$help.file}{/if}
{if $action == 2 && $fieldSpec.is_add_translate_dialog}{include file='CRM/Core/I18n/Dialog.tpl' table=$entityTable field=$fieldName id=$entityID}{/if}
</td>
<td>{if $form.$fieldName.html}{if $fieldSpec.formatter === 'crmMoney'}{$form.$fieldName.html|crmMoney}{else}{$form.$fieldName.html}{/if}{else}{$fieldSpec.place_holder}{/if}<br />
{if $fieldSpec.description}<span class="description">{$fieldSpec.description}</span>{/if}
</td>
{/if}
```
In some cases it might be too hard to make the form iterate through an array but individual fields could be converted - either in order to make that field hook alterable - (ie. the hook could then change the description metadata, or suppress a field) or as part of chipping away at the conversion
```
{assign var=fieldName value='my_converted_field'}
<tr class="crm-{$entityInClassFormat}-form-block-{$fieldName}">
{include file="CRM/Core/Form/Field.tpl"}
</tr>
```
* Note to enable custom data for a new type in an extension use code like the following
```
$optionValues = civicrm_api3('OptionValue', 'get', [
'option_group_id' => 'cg_extend_objects',
'name' => 'civicrm_relationship_type'
]);
if (!$optionValues['count']) {
civicrm_api3('OptionValue', 'create', [
'option_group_id' => 'cg_extend_objects',
'name' => 'civicrm_relationship_type',
'label' => ts('Relationship Type'),
'value' => 'RelationshipType',
]);
}
```