FOSSology  4.4.0
Open Source License Compliance by Open Source Software
ajax-clearing-view.php
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2018 Siemens AG
4  Author: Daniele Fognini, Johannes Najjar
5 
6  SPDX-License-Identifier: GPL-2.0-only
7 */
8 
24 use Monolog\Logger;
25 use Symfony\Component\HttpFoundation\JsonResponse;
26 use Symfony\Component\HttpFoundation\Response;
27 
29 {
30  const OPTION_SKIP_FILE = "option_skipFile";
31  const OPTION_SKIP_FILE_COPYRIGHT = "option_skipFileCopyRight";
32  const OPTION_SKIP_FILE_IPRA = "option_skipFileIpra";
33  const OPTION_SKIP_FILE_ECC = "option_skipFileEcc";
34  const OPTION_SKIP_FILE_KEYWORD = "option_skipFileKeyword";
35 
37  private $uploadDao;
39  private $licenseDao;
41  private $clearingDao;
43  private $agentsDao;
45  private $logger;
47  private $highlightDao;
49  private $highlightProcessor;
51  private $clearingDecisionEventProcessor;
53  private $urlBuilder;
55  private $decisionTypes;
56 
57  function __construct()
58  {
59  $this->Name = "conclude-license";
60  $this->Title = _("Change concluded License ");
61  $this->DBaccess = PLUGIN_DB_WRITE;
62  $this->Dependency = array("view");
63  $this->LoginFlag = 0;
64  $this->NoMenu = 0;
65  $this->OutputType = 'JSON';
66  $this->OutputToStdout = true;
67  parent::__construct();
68 
69  global $container;
70  $this->licenseDao = $container->get('dao.license');
71  $this->uploadDao = $container->get('dao.upload');
72  $this->clearingDao = $container->get('dao.clearing');
73  $this->agentsDao = $container->get('dao.agent');
74  $this->logger = $container->get("logger");
75 
76  $this->highlightDao = $container->get("dao.highlight");
77  $this->highlightProcessor = $container->get("view.highlight_processor");
78  $this->urlBuilder = $container->get('view.url_builder');
79  $this->decisionTypes = $container->get('decision.types');
80  $this->clearingDecisionEventProcessor = $container->get('businessrules.clearing_decision_processor');
81  }
82 
89  protected function doClearingHistory($groupId, $uploadId, $uploadTreeId)
90  {
91  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId);
92 
93  $clearingDecWithLicenses = $this->clearingDao->getFileClearings($itemTreeBounds, $groupId, false, true);
94 
95  $table = array();
96  $scope = new DecisionScopes();
97  foreach ($clearingDecWithLicenses as $clearingDecision) {
98  $licenseOutputs = array();
99  foreach ($clearingDecision->getClearingLicenses() as $lic) {
100  $shortName = $lic->getShortName();
101  $licenseOutputs[$shortName] = $lic->isRemoved() ? "<span style=\"color:red\">$shortName</span>" : $shortName;
102  }
103  ksort($licenseOutputs, SORT_STRING);
104  $row = array(
105  '0' => date('Y-m-d', $clearingDecision->getTimeStamp()),
106  '1' => $clearingDecision->getUserName(),
107  '2' => $scope->getTypeName($clearingDecision->getScope()),
108  '3' => $this->decisionTypes->getTypeName($clearingDecision->getType()),
109  '4' => implode(", ", $licenseOutputs)
110  );
111  $table[] = $row;
112  }
113  return array(
114  'sEcho' => intval($_GET['sEcho']),
115  'aaData' => $table,
116  'iTotalRecords' => count($table),
117  'iTotalDisplayRecords' => count($table)
118  );
119  }
120 
128  protected function doLicenses($orderAscending, $groupId, $uploadId,
129  $uploadTreeId)
130  {
131  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId(
132  $uploadTreeId, $uploadId);
133 
134  list ($licenseDecisions, $removed) = $this->clearingDecisionEventProcessor->getCurrentClearings($itemTreeBounds, $groupId);
135 
136  $licenseRefs = $this->licenseDao->getConclusionLicenseRefs(Auth::getGroupId(), $_GET['sSearch'], $orderAscending, array_keys($licenseDecisions));
137  $licenses = array();
138  foreach ($licenseRefs as $licenseRef) {
139  $licenseId = $licenseRef->getId();
140  $shortNameWithFullTextLink = $this->urlBuilder->getLicenseTextUrl($licenseRef);
141  $actionLink = "<a href=\"javascript:;\" onClick=\"addLicense($uploadId, $uploadTreeId, $licenseId);\">"
142  . "<img src=\"images/space_16.png\" class=\"add\"/></a>";
143 
144  $licenses[] = array($shortNameWithFullTextLink, $actionLink);
145  }
146  return array(
147  'sEcho' => intval($_GET['sEcho']),
148  'aaData' => $licenses,
149  'iTotalRecords' => count($licenses),
150  'iTotalDisplayRecords' => count($licenses));
151  }
152 
161  public function doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId)
162  {
163  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId);
164  $aaData = $this->getCurrentSelectedLicensesTableData($itemTreeBounds,
165  $groupId, $orderAscending);
166 
167  return array(
168  'sEcho' => intval($_GET['sEcho']),
169  'aaData' => $aaData,
170  'iTotalRecords' => count($aaData),
171  'iTotalDisplayRecords' => count($aaData)
172  );
173  }
174 
178  function Output()
179  {
180  $userId = Auth::getUserId();
181  $groupId = Auth::getGroupId();
182  $action = GetParm("do", PARM_STRING);
183  $uploadId = GetParm("upload", PARM_INTEGER);
184  $uploadTreeId = GetParm("item", PARM_INTEGER);
185  $licenseId = GetParm("licenseId", PARM_INTEGER);
186  $sort0 = GetParm("sSortDir_0", PARM_STRING);
187 
188  $orderAscending = isset($sort0) ? $sort0 === "asc" : true;
189 
190  switch ($action) {
191  case "licenses":
192  return new JsonResponse(
193  $this->doLicenses($orderAscending, $groupId, $uploadId, $uploadTreeId));
194 
195  case "licenseDecisions":
196  return new JsonResponse(
197  $this->doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId));
198 
199  case "addLicense":
200  $this->clearingDao->insertClearingEvent($uploadTreeId, $userId, $groupId,
201  $licenseId, false, ClearingEventTypes::USER);
202  return new JsonResponse();
203 
204  case "removeLicense":
205  $this->clearingDao->insertClearingEvent($uploadTreeId, $userId, $groupId,
206  $licenseId, true, ClearingEventTypes::USER);
207  return new JsonResponse();
208 
209  case "makeMainLicense":
210  $this->clearingDao->makeMainLicense($uploadId, $groupId, $licenseId);
211  return new JsonResponse();
212 
213  case "removeMainLicense":
214  $this->clearingDao->removeMainLicense($uploadId, $groupId, $licenseId);
215  return new JsonResponse();
216 
217  case "setNextPrev":
218  case "setNextPrevCopyRight":
219  case "setNextPrevIpra":
220  case "setNextPrevEcc":
221  case "setNextPrevKeyword":
222  return new JsonResponse(
223  $this->doNextPrev($action, $uploadId, $uploadTreeId, $groupId));
224 
225  case "updateClearings":
226  $id = GetParm("id", PARM_STRING);
227  if (isset($id)) {
228  list ($uploadTreeId, $licenseId) = explode(',', $id);
229  $what = GetParm("columnId", PARM_INTEGER);
230  if ($what==2) {
231  $what = 'reportinfo';
232  } elseif ($what==3) {
233  $what = 'acknowledgement';
234  } else {
235  $what = 'comment';
236  }
237  $changeTo = GetParm("value", PARM_RAW);
238  $this->clearingDao->updateClearingEvent($uploadTreeId, $userId, $groupId, $licenseId, $what, $changeTo);
239  }
240  return $this->createPlainResponse("success");
241 
242  case "showClearingHistory":
243  return new JsonResponse($this->doClearingHistory($groupId, $uploadId, $uploadTreeId));
244 
245  case "checkCandidateLicense":
246  if (!empty($this->clearingDao->getCandidateLicenseCountForCurrentDecisions($uploadTreeId))) {
247  return $this->createPlainResponse("Cannot add candidate license as global decision");
248  }
249  return $this->createPlainResponse("success");
250 
251  default:
252  return $this->createPlainResponse("fail");
253  }
254  }
255 
260  protected function getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $forValue, $what, $detectorType=0)
261  {
262  $classAttr = "color:#000000;";
263  $value = "Click to add";
264  if (empty($forValue) && $detectorType == 2 && $what == 2) {
265  $classAttr = "color:red;font-weight:bold;";
266  }
267 
268  if (!empty($forValue)) {
269  $value = convertToUTF8(substr(ltrim($forValue, " \t\n"), 0, 15)."...");
270  }
271  return "<a href=\"javascript:;\" style='$classAttr' id='clearingsForSingleFile$licenseId$what' onclick=\"openTextModel($uploadTreeId, $licenseId, $what);\" title='".convertToUTF8(htmlspecialchars($forValue, ENT_QUOTES), true)."'>$value</a>";
272  }
273 
280  public function getCurrentSelectedLicensesTableData(ItemTreeBounds $itemTreeBounds, $groupId, $orderAscending)
281  {
282  $uploadTreeId = $itemTreeBounds->getItemId();
283  $uploadId = $itemTreeBounds->getUploadId();
284  $uberUri = Traceback_uri() . "?mod=view-license" . Traceback_parm_keep(array(
285  'upload',
286  'folder'
287  ));
288 
289  list ($addedClearingResults, $removedLicenses) = $this->clearingDecisionEventProcessor->getCurrentClearings(
290  $itemTreeBounds, $groupId, LicenseMap::CONCLUSION);
291  $licenseEventTypes = new ClearingEventTypes();
292 
293  $mainLicIds = $this->clearingDao->getMainLicenseIds($uploadId, $groupId);
294 
295  $table = array();
296  /* @var $clearingResult ClearingResult */
297  foreach ($addedClearingResults as $licenseShortName => $clearingResult) {
298  $licenseId = $clearingResult->getLicenseId();
299 
300  $types = $this->getAgentInfo($clearingResult, $uberUri, $uploadTreeId);
301  $reportInfo = "";
302  $comment = "";
303  $acknowledgement = "";
304 
305  if ($clearingResult->hasClearingEvent()) {
306  $licenseDecisionEvent = $clearingResult->getClearingEvent();
307  $types[] = $this->getEventInfo($licenseDecisionEvent, $uberUri,
308  $uploadTreeId, $licenseEventTypes);
309  $reportInfo = $licenseDecisionEvent->getReportinfo();
310  $comment = $licenseDecisionEvent->getComment();
311  $acknowledgement = $licenseDecisionEvent->getAcknowledgement();
312  }
313 
314  $licenseShortNameWithLink = $this->urlBuilder->getLicenseTextUrl(
315  $clearingResult->getLicenseRef());
316  $actionLink = "<a href=\"javascript:;\" onclick=\"removeLicense($uploadId, $uploadTreeId, $licenseId);\"><img class=\"delete\" src=\"images/space_16.png\" alt=\"\"/></a>";
317  if (in_array($clearingResult->getLicenseId(), $mainLicIds)) {
318  $tooltip = _('This is a main license for the upload. Click to discard selection.');
319  $actionLink .= " <a href=\"javascript:;\" onclick=\"removeMainLicense($uploadId, $licenseId);\"><img src=\"images/icons/star_filled_16.png\" alt=\"mainLicense\" title=\"$tooltip\" border=\"0\"/></a>";
320  } else {
321  $tooltip = _('Click to select this as a main license for the upload.');
322  $actionLink .= " <a href=\"javascript:;\" onclick=\"makeMainLicense($uploadId, $licenseId);\"><img src=\"images/icons/star_16.png\" alt=\"noMainLicense\" title=\"$tooltip\" border=\"0\"/></a>";
323  }
324  $detectorType = $this->licenseDao->getLicenseById($clearingResult->getLicenseId(), $groupId)->getDetectorType();
325  $id = "$uploadTreeId,$licenseId";
326  $reportInfoField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $reportInfo, 2, $detectorType);
327  $acknowledgementField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $acknowledgement, 3);
328  $commentField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $comment, 4);
329 
330  $table[$licenseShortName] = array('DT_RowId' => $id,
331  '0' => $actionLink,
332  '1' => $licenseShortNameWithLink,
333  '2' => implode("<br/>", $types),
334  '3' => $reportInfoField,
335  '4' => $acknowledgementField,
336  '5' => $commentField);
337  }
338 
339  foreach ($removedLicenses as $licenseShortName => $clearingResult) {
340  if ($clearingResult->getAgentDecisionEvents()) {
341  $agents = $this->getAgentInfo($clearingResult, $uberUri, $uploadTreeId);
342  $licenseShortNameWithLink = $this->urlBuilder->getLicenseTextUrl($clearingResult->getLicenseRef());
343  $licenseId = $clearingResult->getLicenseId();
344  $actionLink = "<a href=\"javascript:;\" onclick=\"addLicense($uploadId, $uploadTreeId, $licenseId);\"><img class=\"add\" src=\"images/space_16.png\" alt=\"\"/></a>";
345  $filled = in_array($clearingResult->getLicenseId(), $mainLicIds) ? 'filled_' : '';
346  $actionLink .= ' <img src="images/icons/star_'.$filled.'16.png" alt="mainLicense"/>';
347 
348  $idArray = array($uploadTreeId, $licenseId);
349  $id = implode(',', $idArray);
350  $table[$licenseShortName] = array('DT_RowId' => $id,
351  'DT_RowClass' => 'removed',
352  '0' => $actionLink,
353  '1' => $licenseShortNameWithLink,
354  '2' => implode("<br/>", $agents),
355  '3' => "-",
356  '4' => "-",
357  '5' => "-");
358  }
359  }
360 
361  return array_values($this->sortByKeys($table, $orderAscending));
362  }
363 
370  protected function getAgentInfo($licenseDecisionResult, $uberUri, $uploadTreeId)
371  {
372  $agentResults = array();
373  foreach ($licenseDecisionResult->getAgentDecisionEvents() as $agentDecisionEvent) {
374  $agentId = $agentDecisionEvent->getAgentId();
375  $matchId = $agentDecisionEvent->getMatchId();
376  $highlightRegion = $this->highlightDao->getHighlightRegion($matchId);
377  $uri = null;
378  $percentage = false;
379  if ($highlightRegion[0] != "" && $highlightRegion[1] != "") {
380  $percentage = $agentDecisionEvent->getPercentage();
381  $page = $this->highlightDao->getPageNumberOfHighlightEntry($matchId);
382  $uri = $uberUri . "&item=$uploadTreeId&agentId=$agentId&highlightId=$matchId&page=$page#highlight";
383  }
384  $agentResults[$agentDecisionEvent->getAgentName()][] = array(
385  "uri" => $uri,
386  "text" => $percentage ? " (" . $percentage . " %)" : ""
387  );
388  }
389 
390  $results = array();
391  foreach ($agentResults as $agentName => $agentResult) {
392  $matchTexts = array();
393 
394  foreach ($agentResult as $index => $agentData) {
395  $uri = $agentData['uri'];
396  if (! empty($uri)) {
397  $matchTexts[] = "<a href=\"$uri\">#" . ($index + 1) . "</a>" . $agentData['text'];
398  } else {
399  $matchTexts[] = $agentData['text'];
400  }
401  }
402  $matchTexts = implode(', ', $matchTexts);
403  $results[] = $agentName . (empty($matchTexts) ? "" : ": $matchTexts");
404  }
405  return $results;
406  }
407 
413  protected function sortByKeys($arrayToBeSortedByKeys, $orderAscending)
414  {
415  ksort($arrayToBeSortedByKeys, SORT_STRING);
416 
417  if ($orderAscending) {
418  return array_reverse($arrayToBeSortedByKeys);
419  }
420  return $arrayToBeSortedByKeys;
421  }
422 
430  protected function doNextPrev($action, $uploadId, $uploadTreeId, $groupId)
431  {
432  switch ($action) {
433  case "setNextPrev":
434  $modName = "view-license";
435  $opt = self::OPTION_SKIP_FILE;
436  break;
437 
438  case "setNextPrevCopyRight":
439  $modName = "copyright-view";
440  $opt = self::OPTION_SKIP_FILE_COPYRIGHT;
441  break;
442 
443  case "setNextPrevIpra":
444  $modName = "ipra-view";
445  $opt = self::OPTION_SKIP_FILE_IPRA;
446  break;
447 
448  case "setNextPrevEcc":
449  $modName = "ecc-view";
450  $opt = self::OPTION_SKIP_FILE_ECC;
451  break;
452  case "setNextPrevKeyword":
453  $modName = "keyword-view";
454  $opt = self::OPTION_SKIP_FILE_KEYWORD;
455  break;
456  }
457 
458  $options = array('skipThese' => GetParm($opt, PARM_STRING), 'groupId' => $groupId);
459 
460  $prevItem = $this->uploadDao->getPreviousItem($uploadId, $uploadTreeId, $options);
461  $prevItemId = $prevItem ? $prevItem->getId() : null;
462 
463  $nextItem = $this->uploadDao->getNextItem($uploadId, $uploadTreeId, $options);
464  $nextItemId = $nextItem ? $nextItem->getId() : null;
465 
466  return array('prev' => $prevItemId, 'next' => $nextItemId,
467  'uri' => Traceback_uri() . "?mod=" . $modName . Traceback_parm_keep(array('upload', 'folder')));
468  }
469 
474  private function createPlainResponse($output)
475  {
476  return new Response($output, Response::HTTP_OK, array('Content-type' => 'text/plain'));
477  }
478 
479  private function getEventInfo($licenseDecisionEvent, $uberUri, $uploadTreeId, $licenseEventTypes)
480  {
481  $type = $licenseEventTypes->getTypeName($licenseDecisionEvent->getEventType());
482  if ($licenseDecisionEvent->getEventType() == ClearingEventTypes::BULK) {
483  $eventId = $licenseDecisionEvent->getEventId();
484  $type .= ': <a href="'.$uberUri."&item=$uploadTreeId&clearingId=".$eventId.'#highlight">#'.$eventId.'</a>';
485  }
486  return $type;
487  }
488 }
489 
490 $NewPlugin = new AjaxClearingView();
doLicenses($orderAscending, $groupId, $uploadId, $uploadTreeId)
getCurrentSelectedLicensesTableData(ItemTreeBounds $itemTreeBounds, $groupId, $orderAscending)
__construct()
base constructor. Most plugins will just use this
getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $forValue, $what, $detectorType=0)
doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId)
getAgentInfo($licenseDecisionResult, $uberUri, $uploadTreeId)
doNextPrev($action, $uploadId, $uploadTreeId, $groupId)
sortByKeys($arrayToBeSortedByKeys, $orderAscending)
doClearingHistory($groupId, $uploadId, $uploadTreeId)
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:57
Contains the constants and helpers for authentication of user.
Definition: Auth.php:24
Utility functions to process ClearingDecision.
Wrapper class for license map.
Definition: LicenseMap.php:19
Traceback_uri()
Get the URI without query to this location.
Definition: common-parm.php:97
const PARM_INTEGER
Definition: common-parm.php:14
const PARM_RAW
Definition: common-parm.php:22
const PARM_STRING
Definition: common-parm.php:18
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Definition: common-parm.php:46
Traceback_parm_keep($List)
Create a new URI, keeping only these items.
if(! defined('ENT_SUBSTITUTE')) convertToUTF8($content, $toHTML=true)
#define PLUGIN_DB_WRITE
Plugin requires write permission on DB.
Definition: libfossology.h:38