FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
ajax-clearing-view.php
1 <?php
2 /*
3  Copyright (C) 2014-2018, Siemens AG
4  Author: Daniele Fognini, Johannes Najjar
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  version 2 as published by the Free Software Foundation.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
35 use Monolog\Logger;
38 
40 {
41  const OPTION_SKIP_FILE = "option_skipFile";
42  const OPTION_SKIP_FILE_COPYRIGHT = "option_skipFileCopyRight";
43  const OPTION_SKIP_FILE_IP = "option_skipFileIp";
44  const OPTION_SKIP_FILE_ECC = "option_skipFileEcc";
45  const OPTION_SKIP_FILE_KEYWORD = "option_skipFileKeyword";
46 
48  private $uploadDao;
50  private $licenseDao;
52  private $clearingDao;
54  private $agentsDao;
56  private $logger;
58  private $highlightDao;
60  private $highlightProcessor;
62  private $clearingDecisionEventProcessor;
64  private $urlBuilder;
66  private $decisionTypes;
67 
68  function __construct()
69  {
70  $this->Name = "conclude-license";
71  $this->Title = _("Change concluded License ");
72  $this->DBaccess = PLUGIN_DB_WRITE;
73  $this->Dependency = array("view");
74  $this->LoginFlag = 0;
75  $this->NoMenu = 0;
76  $this->OutputType = 'JSON';
77  $this->OutputToStdout = true;
78  parent::__construct();
79 
80  global $container;
81  $this->licenseDao = $container->get('dao.license');
82  $this->uploadDao = $container->get('dao.upload');
83  $this->clearingDao = $container->get('dao.clearing');
84  $this->agentsDao = $container->get('dao.agent');
85  $this->logger = $container->get("logger");
86 
87  $this->highlightDao = $container->get("dao.highlight");
88  $this->highlightProcessor = $container->get("view.highlight_processor");
89  $this->urlBuilder = $container->get('view.url_builder');
90  $this->decisionTypes = $container->get('decision.types');
91  $this->clearingDecisionEventProcessor = $container->get('businessrules.clearing_decision_processor');
92  }
93 
100  protected function doClearingHistory($groupId, $uploadId, $uploadTreeId)
101  {
102  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId);
103 
104  $clearingDecWithLicenses = $this->clearingDao->getFileClearings($itemTreeBounds, $groupId, false, true);
105 
106  $table = array();
107  $scope = new DecisionScopes();
108  foreach ($clearingDecWithLicenses as $clearingDecision) {
109  $licenseOutputs = array();
110  foreach ($clearingDecision->getClearingLicenses() as $lic) {
111  $shortName = $lic->getShortName();
112  $licenseOutputs[$shortName] = $lic->isRemoved() ? "<span style=\"color:red\">$shortName</span>" : $shortName;
113  }
114  ksort($licenseOutputs, SORT_STRING);
115  $row = array(
116  '0' => date('Y-m-d', $clearingDecision->getTimeStamp()),
117  '1' => $clearingDecision->getUserName(),
118  '2' => $scope->getTypeName($clearingDecision->getScope()),
119  '3' => $this->decisionTypes->getTypeName($clearingDecision->getType()),
120  '4' => implode(", ", $licenseOutputs)
121  );
122  $table[] = $row;
123  }
124  return array(
125  'sEcho' => intval($_GET['sEcho']),
126  'aaData' => $table,
127  'iTotalRecords' => count($table),
128  'iTotalDisplayRecords' => count($table)
129  );
130  }
131 
139  protected function doLicenses($orderAscending, $groupId, $uploadId,
140  $uploadTreeId)
141  {
142  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId(
143  $uploadTreeId, $uploadId);
144 
145  list ($licenseDecisions, $removed) = $this->clearingDecisionEventProcessor->getCurrentClearings($itemTreeBounds, $groupId);
146 
147  $licenseRefs = $this->licenseDao->getConclusionLicenseRefs(Auth::getGroupId(), $_GET['sSearch'], $orderAscending, array_keys($licenseDecisions));
148  $licenses = array();
149  foreach ($licenseRefs as $licenseRef) {
150  $licenseId = $licenseRef->getId();
151  $shortNameWithFullTextLink = $this->urlBuilder->getLicenseTextUrl($licenseRef);
152  $actionLink = "<a href=\"javascript:;\" onClick=\"addLicense($uploadId, $uploadTreeId, $licenseId);\">"
153  . "<img src=\"images/space_16.png\" class=\"add\"/></a>";
154 
155  $licenses[] = array($shortNameWithFullTextLink, $actionLink);
156  }
157  return array(
158  'sEcho' => intval($_GET['sEcho']),
159  'aaData' => $licenses,
160  'iTotalRecords' => count($licenses),
161  'iTotalDisplayRecords' => count($licenses));
162  }
163 
172  protected function doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId)
173  {
174  $itemTreeBounds = $this->uploadDao->getItemTreeBoundsFromUploadId($uploadTreeId, $uploadId);
175  $aaData = $this->getCurrentSelectedLicensesTableData($itemTreeBounds,
176  $groupId, $orderAscending);
177 
178  return array(
179  'sEcho' => intval($_GET['sEcho']),
180  'aaData' => $aaData,
181  'iTotalRecords' => count($aaData),
182  'iTotalDisplayRecords' => count($aaData)
183  );
184  }
185 
189  function Output()
190  {
191  $userId = Auth::getUserId();
192  $groupId = Auth::getGroupId();
193  $action = GetParm("do", PARM_STRING);
194  $uploadId = GetParm("upload", PARM_INTEGER);
195  $uploadTreeId = GetParm("item", PARM_INTEGER);
196  $licenseId = GetParm("licenseId", PARM_INTEGER);
197  $sort0 = GetParm("sSortDir_0", PARM_STRING);
198 
199  $orderAscending = isset($sort0) ? $sort0 === "asc" : true;
200 
201  switch ($action) {
202  case "licenses":
203  return new JsonResponse(
204  $this->doLicenses($orderAscending, $groupId, $uploadId, $uploadTreeId));
205 
206  case "licenseDecisions":
207  return new JsonResponse(
208  $this->doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId));
209 
210  case "addLicense":
211  $this->clearingDao->insertClearingEvent($uploadTreeId, $userId, $groupId,
212  $licenseId, false, ClearingEventTypes::USER);
213  return new JsonResponse();
214 
215  case "removeLicense":
216  $this->clearingDao->insertClearingEvent($uploadTreeId, $userId, $groupId,
217  $licenseId, true, ClearingEventTypes::USER);
218  return new JsonResponse();
219 
220  case "makeMainLicense":
221  $this->clearingDao->makeMainLicense($uploadId, $groupId, $licenseId);
222  return new JsonResponse();
223 
224  case "removeMainLicense":
225  $this->clearingDao->removeMainLicense($uploadId, $groupId, $licenseId);
226  return new JsonResponse();
227 
228  case "setNextPrev":
229  case "setNextPrevCopyRight":
230  case "setNextPrevIp":
231  case "setNextPrevEcc":
232  case "setNextPrevKeyword":
233  return new JsonResponse(
234  $this->doNextPrev($action, $uploadId, $uploadTreeId, $groupId));
235 
236  case "updateClearings":
237  $id = GetParm("id", PARM_STRING);
238  if (isset($id)) {
239  list ($uploadTreeId, $licenseId) = explode(',', $id);
240  $what = GetParm("columnId", PARM_INTEGER);
241  if ($what==2) {
242  $what = 'reportinfo';
243  } elseif ($what==3) {
244  $what = 'acknowledgement';
245  } else {
246  $what = 'comment';
247  }
248  $changeTo = GetParm("value", PARM_RAW);
249  $this->clearingDao->updateClearingEvent($uploadTreeId, $userId, $groupId, $licenseId, $what, $changeTo);
250  }
251  return $this->createPlainResponse("success");
252 
253  case "showClearingHistory":
254  return new JsonResponse($this->doClearingHistory($groupId, $uploadId, $uploadTreeId));
255 
256  case "checkCandidateLicense":
257  if (!empty($this->clearingDao->getCandidateLicenseCountForCurrentDecisions($uploadTreeId))) {
258  return $this->createPlainResponse("Cannot add candidate license as global decision");
259  }
260  return $this->createPlainResponse("success");
261 
262  default:
263  return $this->createPlainResponse("fail");
264  }
265  }
266 
271  protected function getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $forValue, $what, $detectorType=0)
272  {
273  $classAttr = "color:#000000;";
274  $value = "Click to add";
275  if (empty($forValue) && $detectorType == 2 && $what == 2) {
276  $classAttr = "color:red;font-weight:bold;";
277  }
278 
279  if (!empty($forValue)) {
280  $value = substr(ltrim($forValue, " \t\n"), 0, 15)."...";
281  }
282  return "<a href=\"javascript:;\" style='$classAttr' id='clearingsForSingleFile$licenseId$what' onclick=\"openTextModel($uploadTreeId, $licenseId, $what);\" title='".htmlspecialchars($forValue, ENT_QUOTES)."'>$value</a>";
283  }
284 
291  protected function getCurrentSelectedLicensesTableData(ItemTreeBounds $itemTreeBounds, $groupId, $orderAscending)
292  {
293  $uploadTreeId = $itemTreeBounds->getItemId();
294  $uploadId = $itemTreeBounds->getUploadId();
295  $uberUri = Traceback_uri() . "?mod=view-license" . Traceback_parm_keep(array(
296  'upload',
297  'folder'
298  ));
299 
300  list ($addedClearingResults, $removedLicenses) = $this->clearingDecisionEventProcessor->getCurrentClearings(
301  $itemTreeBounds, $groupId, LicenseMap::CONCLUSION);
302  $licenseEventTypes = new ClearingEventTypes();
303 
304  $mainLicIds = $this->clearingDao->getMainLicenseIds($uploadId, $groupId);
305 
306  $table = array();
307  /* @var $clearingResult ClearingResult */
308  foreach ($addedClearingResults as $licenseShortName => $clearingResult) {
309  $licenseId = $clearingResult->getLicenseId();
310 
311  $types = $this->getAgentInfo($clearingResult, $uberUri, $uploadTreeId);
312  $reportInfo = "";
313  $comment = "";
314  $acknowledgement = "";
315 
316  if ($clearingResult->hasClearingEvent()) {
317  $licenseDecisionEvent = $clearingResult->getClearingEvent();
318  $types[] = $this->getEventInfo($licenseDecisionEvent, $uberUri,
319  $uploadTreeId, $licenseEventTypes);
320  $reportInfo = $licenseDecisionEvent->getReportinfo();
321  $comment = $licenseDecisionEvent->getComment();
322  $acknowledgement = $licenseDecisionEvent->getAcknowledgement();
323  }
324 
325  $licenseShortNameWithLink = $this->urlBuilder->getLicenseTextUrl(
326  $clearingResult->getLicenseRef());
327  $actionLink = "<a href=\"javascript:;\" onclick=\"removeLicense($uploadId, $uploadTreeId, $licenseId);\"><img class=\"delete\" src=\"images/space_16.png\" alt=\"\"/></a>";
328  if (in_array($clearingResult->getLicenseId(), $mainLicIds)) {
329  $tooltip = _('This is a main license for the upload. Click to discard selection.');
330  $actionLink .= " <a href=\"javascript:;\" onclick=\"removeMainLicense($uploadId, $licenseId);\"><img src=\"images/icons/star_filled_16.png\" alt=\"mainLicense\" title=\"$tooltip\" border=\"0\"/></a>";
331  } else {
332  $tooltip = _('Click to select this as a main license for the upload.');
333  $actionLink .= " <a href=\"javascript:;\" onclick=\"makeMainLicense($uploadId, $licenseId);\"><img src=\"images/icons/star_16.png\" alt=\"noMainLicense\" title=\"$tooltip\" border=\"0\"/></a>";
334  }
335  $detectorType = $this->licenseDao->getLicenseById($clearingResult->getLicenseId(), $groupId)->getDetectorType();
336  $id = "$uploadTreeId,$licenseId";
337  $reportInfoField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $reportInfo, 2, $detectorType);
338  $acknowledgementField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $acknowledgement, 3);
339  $commentField = $this->getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $comment, 4);
340 
341  $table[$licenseShortName] = array('DT_RowId' => $id,
342  '0' => $actionLink,
343  '1' => $licenseShortNameWithLink,
344  '2' => implode("<br/>", $types),
345  '3' => $reportInfoField,
346  '4' => $acknowledgementField,
347  '5' => $commentField);
348  }
349 
350  foreach ($removedLicenses as $licenseShortName => $clearingResult) {
351  if ($clearingResult->getAgentDecisionEvents()) {
352  $agents = $this->getAgentInfo($clearingResult, $uberUri, $uploadTreeId);
353  $licenseShortNameWithLink = $this->urlBuilder->getLicenseTextUrl($clearingResult->getLicenseRef());
354  $licenseId = $clearingResult->getLicenseId();
355  $actionLink = "<a href=\"javascript:;\" onclick=\"addLicense($uploadId, $uploadTreeId, $licenseId);\"><img class=\"add\" src=\"images/space_16.png\" alt=\"\"/></a>";
356  $filled = in_array($clearingResult->getLicenseId(), $mainLicIds) ? 'filled_' : '';
357  $actionLink .= ' <img src="images/icons/star_'.$filled.'16.png" alt="mainLicense"/>';
358 
359  $idArray = array($uploadTreeId, $licenseId);
360  $id = implode(',', $idArray);
361  $table[$licenseShortName] = array('DT_RowId' => $id,
362  'DT_RowClass' => 'removed',
363  '0' => $actionLink,
364  '1' => $licenseShortNameWithLink,
365  '2' => implode("<br/>", $agents),
366  '3' => "-",
367  '4' => "-",
368  '5' => "-");
369  }
370  }
371 
372  $valueTable = array_values($this->sortByKeys($table, $orderAscending));
373  return $valueTable;
374  }
375 
382  protected function getAgentInfo($licenseDecisionResult, $uberUri, $uploadTreeId)
383  {
384  $agentResults = array();
385  foreach ($licenseDecisionResult->getAgentDecisionEvents() as $agentDecisionEvent) {
386  $agentId = $agentDecisionEvent->getAgentId();
387  $matchId = $agentDecisionEvent->getMatchId();
388  $percentage = $agentDecisionEvent->getPercentage();
389  $page = $this->highlightDao->getPageNumberOfHighlightEntry($matchId);
390  $agentResults[$agentDecisionEvent->getAgentName()][] = array(
391  "uri" => $uberUri . "&item=$uploadTreeId&agentId=$agentId&highlightId=$matchId&page=$page#highlight",
392  "text" => $percentage ? " (" . $percentage . " %)" : ""
393  );
394  }
395 
396  $results = array();
397  foreach ($agentResults as $agentName => $agentResult) {
398  $matchTexts = array();
399 
400  foreach ($agentResult as $index => $agentData) {
401  $uri = $agentData['uri'];
402  $matchTexts[] = "<a href=\"$uri\">#" . ($index + 1) . "</a>" . $agentData['text'];
403  }
404  $results[] = $agentName . ": " . implode(', ', $matchTexts);
405  }
406  return $results;
407  }
408 
414  protected function sortByKeys($arrayToBeSortedByKeys, $orderAscending)
415  {
416  ksort($arrayToBeSortedByKeys, SORT_STRING);
417 
418  if ($orderAscending) {
419  $arrayToBeSortedByKeys = array_reverse($arrayToBeSortedByKeys);
420  return $arrayToBeSortedByKeys;
421  }
422  return $arrayToBeSortedByKeys;
423  }
424 
432  protected function doNextPrev($action, $uploadId, $uploadTreeId, $groupId)
433  {
434  switch ($action) {
435  case "setNextPrev":
436  $modName = "view-license";
437  $opt = self::OPTION_SKIP_FILE;
438  break;
439 
440  case "setNextPrevCopyRight":
441  $modName = "copyright-view";
442  $opt = self::OPTION_SKIP_FILE_COPYRIGHT;
443  break;
444 
445  case "setNextPrevIp":
446  $modName = "ip-view";
447  $opt = self::OPTION_SKIP_FILE_IP;
448  break;
449 
450  case "setNextPrevEcc":
451  $modName = "ecc-view";
452  $opt = self::OPTION_SKIP_FILE_ECC;
453  break;
454  case "setNextPrevKeyword":
455  $modName = "keyword-view";
456  $opt = self::OPTION_SKIP_FILE_KEYWORD;
457  break;
458  }
459 
460  $options = array('skipThese' => GetParm($opt, PARM_STRING), 'groupId' => $groupId);
461 
462  $prevItem = $this->uploadDao->getPreviousItem($uploadId, $uploadTreeId, $options);
463  $prevItemId = $prevItem ? $prevItem->getId() : null;
464 
465  $nextItem = $this->uploadDao->getNextItem($uploadId, $uploadTreeId, $options);
466  $nextItemId = $nextItem ? $nextItem->getId() : null;
467 
468  return array('prev' => $prevItemId, 'next' => $nextItemId,
469  'uri' => Traceback_uri() . "?mod=" . $modName . Traceback_parm_keep(array('upload', 'folder')));
470  }
471 
476  private function createPlainResponse($output)
477  {
478  return new Response($output, Response::HTTP_OK, array('Content-type' => 'text/plain'));
479  }
480 
481  private function getEventInfo($licenseDecisionEvent, $uberUri, $uploadTreeId, $licenseEventTypes)
482  {
483  $type = $licenseEventTypes->getTypeName($licenseDecisionEvent->getEventType());
484  if ($licenseDecisionEvent->getEventType() == ClearingEventTypes::BULK) {
485  $eventId = $licenseDecisionEvent->getEventId();
486  $type .= ': <a href="'.$uberUri."&item=$uploadTreeId&clearingId=".$eventId.'#highlight">#'.$eventId.'</a>';
487  }
488  return $type;
489  }
490 }
491 
492 $NewPlugin = new AjaxClearingView();
doClearings($orderAscending, $groupId, $uploadId, $uploadTreeId)
const PARM_RAW
Definition: common-parm.php:33
Traceback_uri()
Get the URI without query to this location.
getBuildClearingsForSingleFile($uploadTreeId, $licenseId, $forValue, $what, $detectorType=0)
doClearingHistory($groupId, $uploadId, $uploadTreeId)
getCurrentSelectedLicensesTableData(ItemTreeBounds $itemTreeBounds, $groupId, $orderAscending)
doNextPrev($action, $uploadId, $uploadTreeId, $groupId)
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Definition: common-parm.php:57
sortByKeys($arrayToBeSortedByKeys, $orderAscending)
const PARM_STRING
Definition: common-parm.php:29
#define PLUGIN_DB_WRITE
Plugin requires write permission on DB.
Definition: libfossology.h:50
getAgentInfo($licenseDecisionResult, $uberUri, $uploadTreeId)
const PARM_INTEGER
Definition: common-parm.php:25
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:67
doLicenses($orderAscending, $groupId, $uploadId, $uploadTreeId)
Traceback_parm_keep($List)
Create a new URI, keeping only these items.