Merge pull request #20375 from JMAConsulting/core-65
[civicrm-core.git] / Civi / Api4 / Generic / DAOGetFieldsAction.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
6 | |
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
10 +--------------------------------------------------------------------+
11 */
12
13 /**
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 */
18
19
20 namespace Civi\Api4\Generic;
21
22 /**
23 * @inheritDoc
24 * @method bool getIncludeCustom()
25 */
26 class DAOGetFieldsAction extends BasicGetFieldsAction {
27
28 /**
29 * Include custom fields for this entity, or only core fields?
30 *
31 * @var bool
32 */
33 protected $includeCustom = TRUE;
34
35 /**
36 * Get fields for a DAO-based entity.
37 *
38 * @return array
39 */
40 protected function getRecords() {
41 $fieldsToGet = $this->_itemsToGet('name');
42 /** @var \Civi\Api4\Service\Spec\SpecGatherer $gatherer */
43 $gatherer = \Civi::container()->get('spec_gatherer');
44 // Any fields name with a dot in it is either custom or an implicit join
45 if ($fieldsToGet) {
46 $this->includeCustom = strpos(implode('', $fieldsToGet), '.') !== FALSE;
47 }
48 $spec = $gatherer->getSpec($this->getEntityName(), $this->getAction(), $this->includeCustom, $this->values);
49 $fields = $this->specToArray($spec->getFields($fieldsToGet));
50 foreach ($fieldsToGet ?? [] as $fieldName) {
51 if (empty($fields[$fieldName]) && strpos($fieldName, '.') !== FALSE) {
52 $fkField = $this->getFkFieldSpec($fieldName, $fields);
53 if ($fkField) {
54 $fkField['name'] = $fieldName;
55 $fields[] = $fkField;
56 }
57 }
58 }
59 return $fields;
60 }
61
62 /**
63 * @param \Civi\Api4\Service\Spec\FieldSpec[] $fields
64 *
65 * @return array
66 */
67 protected function specToArray($fields) {
68 $fieldArray = [];
69
70 foreach ($fields as $field) {
71 if ($this->loadOptions) {
72 $field->getOptions($this->values, $this->loadOptions, $this->checkPermissions);
73 }
74 $fieldArray[$field->getName()] = $field->toArray();
75 }
76
77 return $fieldArray;
78 }
79
80 /**
81 * @param string $fieldName
82 * @param array $fields
83 * @return array|null
84 * @throws \API_Exception
85 */
86 private function getFkFieldSpec($fieldName, $fields) {
87 $fieldPath = explode('.', $fieldName);
88 // Search for the first segment alone plus the first and second
89 // No field in the schema contains more than one dot in its name.
90 $searchPaths = [$fieldPath[0], $fieldPath[0] . '.' . $fieldPath[1]];
91 $fkFieldName = array_intersect($searchPaths, array_keys($fields))[0] ?? NULL;
92 if ($fkFieldName && !empty($fields[$fkFieldName]['fk_entity'])) {
93 $newFieldName = substr($fieldName, 1 + strlen($fkFieldName));
94 return civicrm_api4($fields[$fkFieldName]['fk_entity'], 'getFields', [
95 'checkPermissions' => $this->checkPermissions,
96 'where' => [['name', '=', $newFieldName]],
97 'loadOptions' => $this->loadOptions,
98 'action' => $this->action,
99 ])->first();
100 }
101 }
102
103 public function fields() {
104 $fields = parent::fields();
105 $fields[] = [
106 'name' => 'help_pre',
107 'data_type' => 'String',
108 ];
109 $fields[] = [
110 'name' => 'help_post',
111 'data_type' => 'String',
112 ];
113 $fields[] = [
114 'name' => 'column_name',
115 'data_type' => 'String',
116 ];
117 $fields[] = [
118 'name' => 'custom_field_id',
119 'data_type' => 'Integer',
120 ];
121 $fields[] = [
122 'name' => 'custom_group_id',
123 'data_type' => 'Integer',
124 ];
125 return $fields;
126 }
127
128 }