3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
18 use Civi\Api4\UserJob
;
21 * This class defines the DataSource interface but must be subclassed to be
24 abstract class CRM_Import_DataSource
{
29 * @param int|null $userJobID
31 public function __construct(int $userJobID = NULL) {
33 $this->setUserJobID($userJobID);
38 * Form fields declared for this datasource.
42 protected $submittableFields = [];
47 * This is the primary key of the civicrm_user_job table which is used to
57 public function getUserJobID(): ?
int {
58 return $this->userJobID
;
64 * @param int $userJobID
66 public function setUserJobID(int $userJobID): void
{
67 $this->userJobID
= $userJobID;
73 * This is the relevant row from civicrm_user_job.
82 * API call to retrieve the userJob row.
86 * @throws \API_Exception
88 protected function getUserJob(): array {
89 if (!$this->userJob
) {
90 $this->userJob
= UserJob
::get()
91 ->addWhere('id', '=', $this->getUserJobID())
95 return $this->userJob
;
99 * Get submitted value.
101 * Get a value submitted on the form.
105 * @throws \API_Exception
107 protected function getSubmittedValue(string $valueName) {
108 return $this->getUserJob()['metadata']['submitted_values'][$valueName];
112 * Get rows as an array.
114 * The array has all values.
121 * @throws \API_Exception
122 * @throws \CRM_Core_Exception
124 public function getRows(int $limit = 0, int $offset = 0) {
125 $query = 'SELECT * FROM ' . $this->getTableName();
127 $query .= ' LIMIT ' . $limit . ($offset ?
(' OFFSET ' . $offset) : NULL);
130 $result = CRM_Core_DAO
::executeQuery($query);
131 while ($result->fetch()) {
132 $values = $result->toArray();
133 /* trim whitespace around the values */
134 foreach ($values as $k => $v) {
135 $values[$k] = trim($v, " \t\r\n");
137 // Historically we expect a non-associative array...
138 $rows[] = array_values($values);
144 * Get an array of column headers, if any.
146 * Null is returned when there are none - ie because a csv file does not
147 * have an initial header row.
149 * This is presented to the user in the MapField screen so
150 * that can see what fields they are mapping.
153 * @throws \API_Exception
155 public function getColumnHeaders(): array {
156 return $this->getUserJob()['metadata']['DataSource']['column_headers'];
160 * Get an array of column headers, if any.
162 * Null is returned when there are none - ie because a csv file does not
163 * have an initial header row.
165 * This is presented to the user in the MapField screen so
166 * that can see what fields they are mapping.
169 * @throws \API_Exception
171 public function getNumberOfColumns(): int {
172 return $this->getUserJob()['metadata']['DataSource']['number_of_columns'];
176 * Generated metadata relating to the the datasource.
178 * This is values that are computed within the DataSource class and
179 * which are stored in the userJob metadata in the DataSource key - eg.
181 * ['table_name' => $]
183 * Will be in the user_job.metadata field encoded into the json like
185 * `{'DataSource' : ['table_name' => $], 'submitted_values' : .....}`
189 protected $dataSourceMetadata = [];
192 * Get metadata about the datasource.
196 * @throws \API_Exception
198 public function getDataSourceMetadata(): array {
199 if (!$this->dataSourceMetadata
&& $this->getUserJobID()) {
200 $this->dataSourceMetadata
= $this->getUserJob()['metadata']['DataSource'];
203 return $this->dataSourceMetadata
;
207 * Get the table name for the datajob.
209 * @return string|null
211 * @throws \API_Exception
212 * @throws \CRM_Core_Exception
214 protected function getTableName(): ?
string {
215 // The old name is still stored...
216 $tableName = $this->getDataSourceMetadata()['table_name'];
220 if (strpos($tableName, 'civicrm_tmp_') !== 0
221 ||
!CRM_Utils_Rule
::alphanumeric($tableName)) {
222 // The table name is generated and stored by code, not users so it
223 // should be safe - but a check seems prudent all the same.
224 throw new CRM_Core_Exception('Table cannot be deleted');
230 * Get the fields declared for this datasource.
234 public function getSubmittableFields(): array {
235 return $this->submittableFields
;
239 * Provides information about the data source.
242 * Description of this data source, including:
243 * - title: string, translated, required
244 * - permissions: array, optional
247 abstract public function getInfo();
250 * Set variables up before form is built.
252 * @param CRM_Core_Form $form
254 abstract public function preProcess(&$form);
257 * This is function is called by the form object to get the DataSource's form snippet.
259 * It should add all fields necessary to get the data uploaded to the temporary table in the DB.
261 * @param CRM_Core_Form $form
263 abstract public function buildQuickForm(&$form);
266 * Process the form submission.
268 * @param array $params
270 * @param CRM_Core_Form $form
272 abstract public function postProcess(&$params, &$db, &$form);
275 * Determine if the current user has access to this data source.
279 public function checkPermission() {
280 $info = $this->getInfo();
281 return empty($info['permissions']) || CRM_Core_Permission
::check($info['permissions']);
288 * @throws \API_Exception
289 * @throws \Civi\API\Exception\UnauthorizedException
291 protected function updateUserJobMetadata(string $key, array $data): void
{
292 $metaData = array_merge(
293 $this->getUserJob()['metadata'],
296 UserJob
::update(FALSE)
297 ->addWhere('id', '=', $this->getUserJobID())
298 ->setValues(['metadata' => $metaData])
300 $this->userJob
['metadata'] = $metaData;