Merge pull request #20471 from eileenmcnaughton/schema
[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 * Get fields for a DAO-based entity.
30 *
31 * @return array
32 */
33 protected function getRecords() {
34 $fieldsToGet = $this->_itemsToGet('name');
35 $typesToGet = $this->_itemsToGet('type');
36 /** @var \Civi\Api4\Service\Spec\SpecGatherer $gatherer */
37 $gatherer = \Civi::container()->get('spec_gatherer');
38 $includeCustom = TRUE;
39 if ($typesToGet) {
40 $includeCustom = in_array('Custom', $typesToGet, TRUE);
41 }
42 elseif ($fieldsToGet) {
43 // Any fields name with a dot in it is either custom or an implicit join
44 $includeCustom = strpos(implode('', $fieldsToGet), '.') !== FALSE;
45 }
46 $spec = $gatherer->getSpec($this->getEntityName(), $this->getAction(), $includeCustom, $this->values);
47 $fields = $this->specToArray($spec->getFields($fieldsToGet));
48 foreach ($fieldsToGet ?? [] as $fieldName) {
49 if (empty($fields[$fieldName]) && strpos($fieldName, '.') !== FALSE) {
50 $fkField = $this->getFkFieldSpec($fieldName, $fields);
51 if ($fkField) {
52 $fkField['name'] = $fieldName;
53 $fields[] = $fkField;
54 }
55 }
56 }
57 return $fields;
58 }
59
60 /**
61 * @param \Civi\Api4\Service\Spec\FieldSpec[] $fields
62 *
63 * @return array
64 */
65 protected function specToArray($fields) {
66 $fieldArray = [];
67
68 foreach ($fields as $field) {
69 if ($this->loadOptions) {
70 $field->getOptions($this->values, $this->loadOptions, $this->checkPermissions);
71 }
72 $fieldArray[$field->getName()] = $field->toArray();
73 }
74
75 return $fieldArray;
76 }
77
78 /**
79 * @param string $fieldName
80 * @param array $fields
81 * @return array|null
82 * @throws \API_Exception
83 */
84 private function getFkFieldSpec($fieldName, $fields) {
85 $fieldPath = explode('.', $fieldName);
86 // Search for the first segment alone plus the first and second
87 // No field in the schema contains more than one dot in its name.
88 $searchPaths = [$fieldPath[0], $fieldPath[0] . '.' . $fieldPath[1]];
89 $fkFieldName = array_intersect($searchPaths, array_keys($fields))[0] ?? NULL;
90 if ($fkFieldName && !empty($fields[$fkFieldName]['fk_entity'])) {
91 $newFieldName = substr($fieldName, 1 + strlen($fkFieldName));
92 return civicrm_api4($fields[$fkFieldName]['fk_entity'], 'getFields', [
93 'checkPermissions' => $this->checkPermissions,
94 'where' => [['name', '=', $newFieldName]],
95 'loadOptions' => $this->loadOptions,
96 'action' => $this->action,
97 ])->first();
98 }
99 }
100
101 public function fields() {
102 $fields = parent::fields();
103 $fields[] = [
104 'name' => 'help_pre',
105 'data_type' => 'String',
106 ];
107 $fields[] = [
108 'name' => 'help_post',
109 'data_type' => 'String',
110 ];
111 $fields[] = [
112 'name' => 'column_name',
113 'data_type' => 'String',
114 ];
115 $fields[] = [
116 'name' => 'custom_field_id',
117 'data_type' => 'Integer',
118 ];
119 $fields[] = [
120 'name' => 'custom_group_id',
121 'data_type' => 'Integer',
122 ];
123 $fields[] = [
124 'name' => 'sql_filters',
125 'data_type' => 'Array',
126 '@internal' => TRUE,
127 ];
128 return $fields;
129 }
130
131 }