FOSSology  4.4.0
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)
84  {
85  if (!is_file($filename) || ($handle = fopen($filename, 'r')) === false) {
86  return _('Internal error');
87  }
88  $cnt = -1;
89  $msg = '';
90  try {
91  while (($row = fgetcsv($handle,0,$this->delimiter,$this->enclosure)) !== false) {
92  $log = $this->handleCsv($row);
93  if (!empty($log)) {
94  $msg .= "$log\n";
95  }
96  $cnt++;
97  }
98  $msg .= _('Read csv').(": $cnt ")._('obligations');
99  } catch(\Exception $e) {
100  fclose($handle);
101  return $msg .= _('Error while parsing file').': '.$e->getMessage();
102  }
103  fclose($handle);
104  return $msg;
105  }
106 
113  private function handleCsv($row)
114  {
115  if ($this->headrow===null) {
116  $this->headrow = $this->handleHeadCsv($row);
117  return 'head okay';
118  }
119 
120  $mRow = array();
121  foreach (array('type','topic','text','classification','modifications','comment','licnames','candidatenames') as $needle) {
122  $mRow[$needle] = $row[$this->headrow[$needle]];
123  }
124 
125  return $this->handleCsvObligation($mRow);
126  }
127 
134  private function handleHeadCsv($row)
135  {
136  $headrow = array();
137  foreach (array('type','topic','text','classification','modifications','comment','licnames','candidatenames') as $needle) {
138  $col = ArrayOperation::multiSearch($this->alias[$needle], $row);
139  if (false === $col) {
140  throw new \Exception("Undetermined position of $needle");
141  }
142  $headrow[$needle] = $col;
143  }
144  return $headrow;
145  }
146 
152  private function getKeyFromTopicAndText($row)
153  {
154  $req = array($row['topic'], $row['text']);
155  $row = $this->dbManager->getSingleRow('SELECT ob_pk FROM obligation_ref WHERE ob_topic=$1 AND ob_md5=md5($2)',$req);
156  return ($row === false) ? false : $row['ob_pk'];
157  }
158 
167  private function compareLicList($exists, $listFromCsv, $candidate, $row)
168  {
169  $getList = $this->obligationMap->getLicenseList($exists, $candidate);
170  $listFromDb = $this->reArrangeString($getList);
171  $listFromCsv = $this->reArrangeString($listFromCsv);
172  return strcmp($listFromDb, $listFromCsv);
173  }
174 
181  private function reArrangeString($string)
182  {
183  $string = explode(";", $string);
184  sort($string);
185  return implode(",", $string);
186  }
187 
194  private function clearListFromDb($exists, $candidate)
195  {
196  $licId = 0;
197  $this->obligationMap->unassociateLicenseFromObligation($exists, $licId, $candidate);
198  return true;
199  }
200 
209  private function handleCsvObligation($row)
210  {
211  /* @var $dbManager DbManager */
213  $exists = $this->getKeyFromTopicAndText($row);
214  $associatedLicenses = "";
215  $candidateLicenses = "";
216  $msg = "";
217  if ($exists !== false) {
218  $msg = "Obligation topic '$row[topic]' already exists in DB (id=".$exists."),";
219  if ( $this->compareLicList($exists, $row['licnames'], false, $row) === 0 ) {
220  $msg .=" No Changes in AssociateLicense";
221  } else {
222  $this->clearListFromDb($exists, false);
223  if (!empty($row['licnames'])) {
224  $associatedLicenses .= $this->AssociateWithLicenses($row['licnames'], $exists, false);
225  }
226  $msg .=" Updated AssociatedLicense license";
227  }
228  if ($this->compareLicList($exists, $row['candidatenames'], true, $row) === 0) {
229  $msg .=" No Changes in CandidateLicense";
230  } else {
231  $this->clearListFromDb($exists, true);
232  if (!empty($row['candidatenames'])) {
233  $associatedLicenses .= $this->AssociateWithLicenses($row['candidatenames'], $exists, true);
234  }
235  $msg .=" Updated CandidateLicense";
236  }
237  $this->updateOtherFields($exists, $row);
238  return $msg . "\n" . $associatedLicenses . "\n";
239  }
240 
241  $stmtInsert = __METHOD__.'.insert';
242  $dbManager->prepare($stmtInsert,'INSERT INTO obligation_ref (ob_type,ob_topic,ob_text,ob_classification,ob_modifications,ob_comment,ob_md5)'
243  . ' VALUES ($1,$2,$3,$4,$5,$6,md5($3)) RETURNING ob_pk');
244  $resi = $dbManager->execute($stmtInsert,array($row['type'],$row['topic'],$row['text'],$row['classification'],$row['modifications'],$row['comment']));
245  $new = $dbManager->fetchArray($resi);
246  $dbManager->freeResult($resi);
247 
248  if (!empty($row['licnames'])) {
249  $associatedLicenses .= $this->AssociateWithLicenses($row['licnames'], $new['ob_pk']);
250  }
251  if (!empty($row['candidatenames'])) {
252  $candidateLicenses = $this->AssociateWithLicenses($row['candidatenames'], $new['ob_pk'], true);
253  }
254 
255  $message = "License association results for obligation '$row[topic]':\n";
256  $message .= "$associatedLicenses";
257  $message .= "$candidateLicenses";
258  $message .= "Obligation with id=$new[ob_pk] was added successfully.\n";
259  return $message;
260  }
261 
270  function AssociateWithLicenses($licList, $obPk, $candidate=False)
271  {
272  $associatedLicenses = "";
273  $message = "";
274 
275  $licenses = explode(";",$licList);
276  foreach ($licenses as $license) {
277  $licIds = $this->obligationMap->getIdFromShortname($license, $candidate);
278  $updated = false;
279  if (empty($licIds)) {
280  $message .= "License $license could not be found in the DB.\n";
281  } else {
282  $updated = $this->obligationMap->associateLicenseFromLicenseList($obPk,
283  $licIds, $candidate);
284  }
285  if ($updated) {
286  if ($associatedLicenses == "") {
287  $associatedLicenses = "$license";
288  } else {
289  $associatedLicenses .= ";$license";
290  }
291  }
292  }
293 
294  if (!empty($associatedLicenses)) {
295  $message .= "$associatedLicenses were associated.\n";
296  } else {
297  $message .= "No ";
298  $message .= $candidate ? "candidate": "";
299  $message .= "licenses were associated.\n";
300  }
301  return $message;
302  }
303 
314  function updateOtherFields($exists, $row)
315  {
316  $this->dbManager->getSingleRow('UPDATE obligation_ref SET ob_classification=$2, ob_modifications=$3, ob_comment=$4 where ob_pk=$1',
317  array($exists, $row['classification'], $row['modifications'], $row['comment']),
318  __METHOD__ . '.updateOtherOb');
319  }
320 }
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.
handleFile($filename)
Read the CSV line by line and import it.
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.
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.