FOSSology  4.5.1
Open Source License Compliance by Open Source Software
ObligationCsvImport.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2017 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
9 
12 
23 {
26  protected $dbManager;
29  protected $delimiter = ',';
32  protected $enclosure = '"';
35  protected $headrow = null;
38  protected $alias = array(
39  'type'=>array('type','Type'),
40  'topic'=>array('topic','Obligation or Risk topic'),
41  'text'=>array('text','Full Text'),
42  'classification'=>array('classification','Classification'),
43  'modifications'=>array('modifications','Apply on modified source code'),
44  'comment'=>array('comment','Comment'),
45  'licnames'=>array('licnames','Associated Licenses'),
46  'candidatenames'=>array('candidatenames','Associated candidate Licenses')
47  );
48 
53  public function __construct(DbManager $dbManager)
54  {
55  $this->dbManager = $dbManager;
56  $this->obligationMap = $GLOBALS['container']->get('businessrules.obligationmap');
57  }
58 
63  public function setDelimiter($delimiter=',')
64  {
65  $this->delimiter = substr($delimiter,0,1);
66  }
67 
72  public function setEnclosure($enclosure='"')
73  {
74  $this->enclosure = substr($enclosure,0,1);
75  }
76 
83  public function handleFile($filename, $fileExtension)
84  {
85  if (!is_file($filename) || ($handle = fopen($filename, 'r')) === false) {
86  return _('Internal error');
87  }
88  $cnt = -1;
89  $msg = '';
90  try {
91  if ($fileExtension == 'csv') {
92  while (($row = fgetcsv($handle,0,$this->delimiter,$this->enclosure)) !== false) {
93  $log = $this->handleCsv($row);
94  if (!empty($log)) {
95  $msg .= "$log\n";
96  }
97  $cnt++;
98  }
99  $msg .= _('Read csv').(": $cnt ")._('obligations');
100  } else {
101  $jsonContent = fread($handle, filesize($filename));
102  $data = json_decode($jsonContent, true);
103  if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
104  $msg .= "Error decoding JSON: " . json_last_error_msg() . "\n";
105  }
106  $msg = $this->importJsonData($data, $msg);
107  $msg .= _('Read json').(":". count($data) ." ")._('obligations');
108  }
109  } catch(\Exception $e) {
110  fclose($handle);
111  return $msg .= _('Error while parsing file').': '.$e->getMessage();
112  }
113  fclose($handle);
114  return $msg;
115  }
116 
123  function handleRowJson($row)
124  {
125  $newArray = array();
126  foreach ($row as $key => $value) {
127  $newKey = $key;
128  foreach ($this->alias as $aliasKey => $aliasValues) {
129  if (in_array($key, $aliasValues)) {
130  $newKey = $aliasKey;
131  break;
132  }
133  }
134  $newArray[$newKey] = $value;
135  }
136  return $newArray;
137  }
138 
145  private function handleCsv($row)
146  {
147  if ($this->headrow===null) {
148  $this->headrow = $this->handleHeadCsv($row);
149  return 'head okay';
150  }
151 
152  $mRow = array();
153  foreach (array('type','topic','text','classification','modifications','comment','licnames','candidatenames') as $needle) {
154  $mRow[$needle] = $row[$this->headrow[$needle]];
155  }
156 
157  return $this->handleCsvObligation($mRow);
158  }
159 
166  private function handleHeadCsv($row)
167  {
168  $headrow = array();
169  foreach (array('type','topic','text','classification','modifications','comment','licnames','candidatenames') as $needle) {
170  $col = ArrayOperation::multiSearch($this->alias[$needle], $row);
171  if (false === $col) {
172  throw new \Exception("Undetermined position of $needle");
173  }
174  $headrow[$needle] = $col;
175  }
176  return $headrow;
177  }
178 
184  private function getKeyFromTopicAndText($row)
185  {
186  $req = array($row['topic'], $row['text']);
187  $row = $this->dbManager->getSingleRow('SELECT ob_pk FROM obligation_ref WHERE ob_topic=$1 AND ob_md5=md5($2)',$req);
188  return ($row === false) ? false : $row['ob_pk'];
189  }
190 
199  private function compareLicList($exists, $listFromCsv, $candidate, $row)
200  {
201  $getList = $this->obligationMap->getLicenseList($exists, $candidate);
202  $listFromDb = $this->reArrangeString($getList);
203  $listFromCsv = $this->reArrangeString($listFromCsv);
204  return strcmp($listFromDb, $listFromCsv);
205  }
206 
213  private function reArrangeString($string)
214  {
215  $string = explode(";", $string);
216  sort($string);
217  return implode(",", $string);
218  }
219 
226  private function clearListFromDb($exists, $candidate)
227  {
228  $licId = 0;
229  $this->obligationMap->unassociateLicenseFromObligation($exists, $licId, $candidate);
230  return true;
231  }
232 
241  private function handleCsvObligation($row)
242  {
243  /* @var $dbManager DbManager */
245  $exists = $this->getKeyFromTopicAndText($row);
246  $associatedLicenses = "";
247  $candidateLicenses = "";
248  $msg = "";
249  if ($exists !== false) {
250  $msg = "Obligation topic '$row[topic]' already exists in DB (id=".$exists."),";
251  if ( $this->compareLicList($exists, $row['licnames'], false, $row) === 0 ) {
252  $msg .=" No Changes in AssociateLicense";
253  } else {
254  $this->clearListFromDb($exists, false);
255  if (!empty($row['licnames'])) {
256  $associatedLicenses .= $this->AssociateWithLicenses($row['licnames'], $exists, false);
257  }
258  $msg .=" Updated AssociatedLicense license";
259  }
260  if ($this->compareLicList($exists, $row['candidatenames'], true, $row) === 0) {
261  $msg .=" No Changes in CandidateLicense";
262  } else {
263  $this->clearListFromDb($exists, true);
264  if (!empty($row['candidatenames'])) {
265  $associatedLicenses .= $this->AssociateWithLicenses($row['candidatenames'], $exists, true);
266  }
267  $msg .=" Updated CandidateLicense";
268  }
269  $this->updateOtherFields($exists, $row);
270  return $msg . "\n" . $associatedLicenses . "\n";
271  }
272 
273  $stmtInsert = __METHOD__.'.insert';
274  $dbManager->prepare($stmtInsert,'INSERT INTO obligation_ref (ob_type,ob_topic,ob_text,ob_classification,ob_modifications,ob_comment,ob_md5)'
275  . ' VALUES ($1,$2,$3,$4,$5,$6,md5($3)) RETURNING ob_pk');
276  $resi = $dbManager->execute($stmtInsert,array($row['type'],$row['topic'],$row['text'],$row['classification'],$row['modifications'],$row['comment']));
277  $new = $dbManager->fetchArray($resi);
278  $dbManager->freeResult($resi);
279 
280  if (!empty($row['licnames'])) {
281  $associatedLicenses .= $this->AssociateWithLicenses($row['licnames'], $new['ob_pk']);
282  }
283  if (!empty($row['candidatenames'])) {
284  $candidateLicenses = $this->AssociateWithLicenses($row['candidatenames'], $new['ob_pk'], true);
285  }
286 
287  $message = "License association results for obligation '$row[topic]':\n";
288  $message .= "$associatedLicenses";
289  $message .= "$candidateLicenses";
290  $message .= "Obligation with id=$new[ob_pk] was added successfully.\n";
291  return $message;
292  }
293 
302  function AssociateWithLicenses($licList, $obPk, $candidate=False)
303  {
304  $associatedLicenses = "";
305  $message = "";
306 
307  $licenses = explode(";",$licList);
308  foreach ($licenses as $license) {
309  $licIds = $this->obligationMap->getIdFromShortname($license, $candidate);
310  $updated = false;
311  if (empty($licIds)) {
312  $message .= "License $license could not be found in the DB.\n";
313  } else {
314  $updated = $this->obligationMap->associateLicenseFromLicenseList($obPk,
315  $licIds, $candidate);
316  }
317  if ($updated) {
318  if ($associatedLicenses == "") {
319  $associatedLicenses = "$license";
320  } else {
321  $associatedLicenses .= ";$license";
322  }
323  }
324  }
325 
326  if (!empty($associatedLicenses)) {
327  $message .= "$associatedLicenses were associated.\n";
328  } else {
329  $message .= "No ";
330  $message .= $candidate ? "candidate": "";
331  $message .= "licenses were associated.\n";
332  }
333  return $message;
334  }
335 
346  function updateOtherFields($exists, $row)
347  {
348  $this->dbManager->getSingleRow('UPDATE obligation_ref SET ob_classification=$2, ob_modifications=$3, ob_comment=$4 where ob_pk=$1',
349  array($exists, $row['classification'], $row['modifications'], $row['comment']),
350  __METHOD__ . '.updateOtherOb');
351  }
352 
358  public function importJsonData($data, string $msg): string
359  {
360  foreach ($data as $row) {
361  $log = $this->handleCsvObligation($this->handleRowJson($row));
362  if (!empty($log)) {
363  $msg .= "$log\n";
364  }
365  }
366  return $msg;
367  }
368 }
Helper class for Obligation CSV Import.
setDelimiter($delimiter=',')
Update the delimiter.
setEnclosure($enclosure='"')
Update the enclosure.
clearListFromDb($exists, $candidate)
Clear all license maps for given obligation.
getKeyFromTopicAndText($row)
Get the Obligation key from obligation topic and obligation text.
handleCsvObligation($row)
Handle a single row from CSV.
updateOtherFields($exists, $row)
Update other fields of the obligation.
AssociateWithLicenses($licList, $obPk, $candidate=False)
Associate selected licenses to the obligation.
handleFile($filename, $fileExtension)
Read the CSV line by line and import it.
compareLicList($exists, $listFromCsv, $candidate, $row)
Compare licenses from Database and CSV.
Fossology exception.
Definition: Exception.php:15
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
Utility functions for specific applications.