Merge pull request #23258 from civicrm/5.49
[civicrm-core.git] / CRM / Import / Forms.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * This class helps the forms within the import flow access submitted & parsed values.
20 */
21 class CRM_Import_Forms extends CRM_Core_Form {
22
23 /**
24 * Get the submitted value, accessing it from whatever form in the flow it is submitted on.
25 * @param string $fieldName
26 *
27 * @return mixed|null
28 */
29 public function getSubmittedValue(string $fieldName) {
30 $mappedValues = [
31 'skipColumnHeader' => 'DataSource',
32 'fieldSeparator' => 'DataSource',
33 'uploadFile' => 'DataSource',
34 'contactType' => 'DataSource',
35 'dateFormats' => 'DataSource',
36 'savedMapping' => 'DataSource',
37 'dataSource' => 'DataSource',
38 ];
39 if (array_key_exists($fieldName, $mappedValues)) {
40 return $this->controller->exportValue($mappedValues[$fieldName], $fieldName);
41 }
42 return parent::getSubmittedValue($fieldName);
43
44 }
45
46 /**
47 * Get the available datasource.
48 *
49 * Permission dependent, this will look like
50 * [
51 * 'CRM_Import_DataSource_CSV' => 'Comma-Separated Values (CSV)',
52 * 'CRM_Import_DataSource_SQL' => 'SQL Query',
53 * ]
54 *
55 * The label is translated.
56 *
57 * @return array
58 */
59 protected function getDataSources(): array {
60 $dataSources = [];
61 foreach (['CRM_Import_DataSource_SQL', 'CRM_Import_DataSource_CSV'] as $dataSourceClass) {
62 $object = new $dataSourceClass();
63 if ($object->checkPermission()) {
64 $dataSources[$dataSourceClass] = $object->getInfo()['title'];
65 }
66 }
67 return $dataSources;
68 }
69
70 /**
71 * Get the name of the datasource class.
72 *
73 * This function prioritises retrieving from GET and POST over 'submitted'.
74 * The reason for this is the submitted array will hold the previous submissions
75 * data until after buildForm is called.
76 *
77 * This is problematic in the forward->back flow & option changing flow. As in....
78 *
79 * 1) Load DataSource form - initial default datasource is set to CSV and the
80 * form is via ajax (this calls DataSourceConfig to get the data).
81 * 2) User changes the source to SQL - the ajax updates the html but the
82 * form was built with the expectation that the csv-specific fields would be
83 * required.
84 * 3) When the user submits Quickform calls preProcess and buildForm and THEN
85 * retrieves the submitted values based on what has been added in buildForm.
86 * Only the submitted values for fields added in buildForm are available - but
87 * these have to be added BEFORE the submitted values are determined. Hence
88 * we look in the POST or GET to get the updated value.
89 *
90 * Note that an imminent refactor will involve storing the values in the
91 * civicrm_user_job table - this will hopefully help with a known (not new)
92 * issue whereby the previously submitted values (eg. skipColumnHeader has
93 * been checked or sql has been filled in) are not loaded via the ajax request.
94 *
95 * @return string|null
96 *
97 * @throws \CRM_Core_Exception
98 */
99 protected function getDataSourceClassName(): ?string {
100 $className = CRM_Utils_Request::retrieveValue(
101 'dataSource',
102 'String'
103 );
104 if (!$className) {
105 $className = $this->getSubmittedValue('dataSource');
106 }
107 if (!$className) {
108 $className = $this->getDefaultDataSource();
109 }
110 if ($this->getDataSources()[$className]) {
111 return $className;
112 }
113 throw new CRM_Core_Exception('Invalid data source');
114 }
115
116 /**
117 * Allow the datasource class to add fields.
118 *
119 * This is called as a snippet in DataSourceConfig and
120 * also from DataSource::buildForm to add the fields such
121 * that quick form picks them up.
122 *
123 * @throws \CRM_Core_Exception
124 */
125 protected function buildDataSourceFields(): void {
126 $className = $this->getDataSourceClassName();
127 if ($className) {
128 $dataSourceClass = new $className();
129 $dataSourceClass->buildQuickForm($this);
130 }
131 }
132
133 /**
134 * Get the default datasource.
135 *
136 * @return string
137 */
138 protected function getDefaultDataSource(): string {
139 return 'CRM_Import_DataSource_CSV';
140 }
141
142 }