FOSSology  4.4.0
Open Source License Compliance by Open Source Software
ReuserAgent.php
Go to the documentation of this file.
1 <?php
2 /*
3  SPDX-FileCopyrightText: © 2014-2018 Siemens AG
4 Author: Daniele Fognini, Andreas Würl
5 
6  SPDX-License-Identifier: GPL-2.0-only
7 */
8 
9 namespace Fossology\Reuser;
10 
27 
28 include_once(__DIR__ . "/version.php");
29 
36 class ReuserAgent extends Agent
37 {
41  private $uploadDao;
61  private $clearingDao;
65  private $copyrightDao;
69  private $aagentDao;
73  private $decisionTypes;
74 
75  function __construct()
76  {
77  parent::__construct(REUSER_AGENT_NAME, AGENT_VERSION, AGENT_REV);
78  $this->aagentDao = $this->container->get('dao.agent');
79  $this->uploadDao = $this->container->get('dao.upload');
80  $this->clearingDao = $this->container->get('dao.clearing');
81  $this->copyrightDao = $this->container->get('dao.copyright');
82  $this->decisionTypes = $this->container->get('decision.types');
83  $this->clearingEventProcessor = $this->container->get('businessrules.clearing_event_processor');
84  $this->clearingDecisionFilter = $this->container->get('businessrules.clearing_decision_filter');
85  $this->clearingDecisionProcessor = $this->container->get('businessrules.clearing_decision_processor');
86  $this->agentLicenseEventProcessor = $this->container->get('businessrules.agent_license_event_processor');
87  }
88 
94  function processUploadId($uploadId)
95  {
96  $itemTreeBounds = $this->uploadDao->getParentItemBounds($uploadId);
97  foreach ($this->uploadDao->getReusedUpload($uploadId, $this->groupId) as $reuseTriple) {
98  // Get the reuse upload id
99  $reusedUploadId = $reuseTriple['reused_upload_fk'];
100  // Get the group id
101  $reusedGroupId = $reuseTriple['reused_group_fk'];
102  // Get the reuse mode
103  $reuseMode = $reuseTriple['reuse_mode'];
104  // Get the ItemTreeBounds for the upload
105  $itemTreeBoundsReused = $this->uploadDao->getParentItemBounds($reusedUploadId);
106  if (false === $itemTreeBoundsReused) {
107  continue;
108  }
109 
110  if ($reuseMode & UploadDao::REUSE_ENHANCED) {
111  $this->processEnhancedUploadReuse($itemTreeBounds, $itemTreeBoundsReused, $reusedGroupId);
112  } else {
113  $this->processUploadReuse($itemTreeBounds, $itemTreeBoundsReused, $reusedGroupId);
114  }
115 
116  if ($reuseMode & UploadDao::REUSE_MAIN) {
117  $this->reuseMainLicense($uploadId, $this->groupId, $reusedUploadId, $reusedGroupId);
118  }
119 
120  if ($reuseMode & UploadDao::REUSE_CONF) {
121  $this->reuseConfSettings($uploadId, $reusedUploadId);
122  }
123 
124  if ($reuseMode & UploadDao::REUSE_COPYRIGHT) {
125  $this->reuseCopyrights($uploadId, $reusedUploadId);
126  }
127  }
128  return true;
129  }
130  protected function reuseConfSettings($uploadId, $reusedUploadId)
131  {
132  if (!$this->uploadDao->insertReportConfReuse($uploadId, $reusedUploadId)) {
133  echo "INFO :: Report configuration for select upload doesn't exists. Unable to copy!!!";
134  }
135  $this->heartbeat(1);
136  return true;
137  }
138 
149  protected function reuseMainLicense($uploadId, $groupId, $reusedUploadId, $reusedGroupId)
150  {
151  $mainLicenseIds = $this->clearingDao->getMainLicenseIds($reusedUploadId, $reusedGroupId);
152  if (!empty($mainLicenseIds)) {
153  foreach ($mainLicenseIds as $mainLicenseId) {
154  if (in_array($mainLicenseId, $this->clearingDao->getMainLicenseIds($uploadId, $groupId))) {
155  continue;
156  } else {
157  $this->clearingDao->makeMainLicense($uploadId, $groupId, $mainLicenseId);
158  }
159  }
160  }
161  return true;
162  }
163 
171  protected function getAgentId($uploadId)
172  {
173  $agentName = 'copyright';
174 
176  $scanJobProxy = new ScanJobProxy($this->aagentDao, $uploadId);
177 
178  $scanJobProxy->createAgentStatus(array($agentName));
179  $selectedScanners = $scanJobProxy->getLatestSuccessfulAgentIds();
180  if (!array_key_exists($agentName, $selectedScanners)) {
181  return;
182  }
183  return $selectedScanners[$agentName];
184  }
185 
186 
195  protected function reuseCopyrights($uploadId, $reusedUploadId)
196  {
197  $agentId = $this->getAgentId($uploadId);
198  $reusedAgentId = $this->getAgentId($reusedUploadId);
199  if ($agentId == null || $reusedAgentId == null) {
200  return true;
201  }
202  $uploadTreeTableName = $this->uploadDao->getUploadtreeTableName($uploadId);
203  $extrawhere = ' agent_fk='.$agentId;
204  $allCopyrights = $this->copyrightDao->getScannerEntries('copyright',
205  $uploadTreeTableName, $uploadId, null, $extrawhere);
206 
207  $reusedCopyrights = $this->copyrightDao->getAllEventEntriesForUpload(
208  $reusedUploadId, $reusedAgentId);
209 
210  if (!empty($reusedCopyrights) && !empty($allCopyrights)) {
211  foreach ($reusedCopyrights as $reusedCopyright) {
212  foreach ($allCopyrights as $copyrightKey => $copyright) {
213  if (strcmp($copyright['hash'], $reusedCopyright['hash']) == 0) {
214  if ($this->dbManager->booleanFromDb($reusedCopyright['is_enabled'])) {
215  $action = "update";
216  $content = $reusedCopyright["contentedited"];
217  } else {
218  $action = "delete";
219  $content = "";
220  }
221  $hash = $copyright['hash'];
222  $item = $this->uploadDao->getItemTreeBounds(intval($copyright['uploadtree_pk']),
223  $uploadTreeTableName);
224  $this->copyrightDao->updateTable($item, $hash, $content,
225  $this->userId, 'copyright', $action);
226  unset($allCopyrights[$copyrightKey]);
227  $this->heartbeat(1);
228  }
229  }
230  }
231  }
232  return true;
233  }
234 
243  protected function processUploadReuse($itemTreeBounds, $itemTreeBoundsReused, $reusedGroupId)
244  {
247 
248  $clearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBoundsReused, $reusedGroupId);
249  $currenlyVisibleClearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds, $groupId);
250 
251  $currenlyVisibleClearingDecisionsById = $this->mapByClearingId($currenlyVisibleClearingDecisions);
252  $clearingDecisionsById = $this->mapByClearingId($clearingDecisions);
253 
254  $clearingDecisionsToImport = array_diff_key($clearingDecisionsById,$currenlyVisibleClearingDecisionsById);
255 
256  $clearingDecisionToImportByFileId = $this->mapByFileId($clearingDecisionsToImport);
257 
260  $containedItems = ArrayOperation::callChunked(
261  function ($fileIds) use ($itemTreeBounds, $uploadDao)
262  {
263  return $uploadDao->getContainedItems(
264  $itemTreeBounds,
265  "pfile_fk = ANY($1)",
266  array('{' . implode(', ', $fileIds) . '}')
267  );
268  }, array_keys($clearingDecisionToImportByFileId), 100);
269 
270  foreach ($containedItems as $item) {
271  $fileId = $item->getFileId();
272  if (empty($fileId)) {
273  continue;
274  }
275  if (array_key_exists($fileId, $clearingDecisionToImportByFileId)) {
276  $this->createCopyOfClearingDecision($item->getId(), $userId, $groupId,
277  $clearingDecisionToImportByFileId[$fileId]);
278  } else {
279  throw new \Exception("bad internal state");
280  }
281 
282  $this->heartbeat(1);
283  }
284 
285  return true;
286  }
287 
295  protected function processEnhancedUploadReuse($itemTreeBounds, $itemTreeBoundsReused, $reusedGroupId)
296  {
297  $clearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBoundsReused, $reusedGroupId);
298  $currenlyVisibleClearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds, $this->groupId);
299 
300  $currenlyVisibleClearingDecisionsById = $this->mapByClearingId($currenlyVisibleClearingDecisions);
301  $clearingDecisionsById = $this->mapByClearingId($clearingDecisions);
302 
303  $clearingDecisionsToImport = array_diff_key($clearingDecisionsById,$currenlyVisibleClearingDecisionsById);
304 
305  $sql = "SELECT ut.* FROM uploadtree ur, uploadtree ut WHERE ur.upload_fk=$2"
306  . " AND ur.pfile_fk=$3 AND ut.upload_fk=$1 AND ut.ufile_name=ur.ufile_name";
307  $stmt = __METHOD__.'.reuseByName';
308  $this->dbManager->prepare($stmt, $sql);
309  $treeDao = $this->container->get('dao.tree');
310 
311  foreach ($clearingDecisionsToImport as $clearingDecision) {
312  $reusedPath = $treeDao->getRepoPathOfPfile($clearingDecision->getPfileId());
313  if (empty($reusedPath)) {
314  // File missing from repo
315  continue;
316  }
317 
318  $res = $this->dbManager->execute($stmt,array($itemTreeBounds->getUploadId(),
319  $itemTreeBoundsReused->getUploadId(),$clearingDecision->getPfileId()));
320  while ($row = $this->dbManager->fetchArray($res)) {
321  $newPath = $treeDao->getRepoPathOfPfile($row['pfile_fk']);
322  if (empty($newPath)) {
323  // File missing from repo
324  continue;
325  }
326  $this->copyClearingDecisionIfDifferenceIsSmall($reusedPath, $newPath, $clearingDecision, $row['uploadtree_pk']);
327  }
328  $this->dbManager->freeResult($res);
329  }
330  }
331 
343  protected function copyClearingDecisionIfDifferenceIsSmall($reusedPath,$newPath,$clearingDecision,$itemId)
344  {
345  $diffLevel = exec("diff $reusedPath $newPath | wc -l");
346  if ($diffLevel === false) {
347  throw new \Exception('cannot use diff tool');
348  }
349  if ($diffLevel < 5) {
350  $this->createCopyOfClearingDecision($itemId, $this->userId, $this->groupId, $clearingDecision);
351  $this->heartbeat(1);
352  }
353  }
354 
362  protected function mapByFileId($clearingDecisions)
363  {
364  $clearingDecisionByFileId = array();
365  foreach ($clearingDecisions as $clearingDecision) {
366  $fileId = $clearingDecision->getPfileId();
367  if (!array_key_exists($fileId, $clearingDecisionByFileId)) {
368  $clearingDecisionByFileId[$fileId] = $clearingDecision;
369  }
370  }
371  return $clearingDecisionByFileId;
372  }
373 
381  protected function createCopyOfClearingDecision($itemId, $userId, $groupId, $clearingDecisionToCopy)
382  {
383  $clearingEventIdsToCopy = array();
385  foreach ($clearingDecisionToCopy->getClearingEvents() as $clearingEvent) {
386  $licenseId = $clearingEvent->getLicenseId();
387  $uploadTreeId = $itemId;
388  $isRemoved = $clearingEvent->isRemoved();
389  $type = ClearingEventTypes::USER;
390  $reportInfo = $clearingEvent->getReportinfo();
391  $comment = $clearingEvent->getComment();
392  $acknowledgement = $clearingEvent->getAcknowledgement();
394  $clearingEventIdsToCopy[] = $this->clearingDao->insertClearingEvent(
395  $uploadTreeId, $userId, $groupId, $licenseId, $isRemoved,
396  $type, $reportInfo, $comment, $acknowledgement, $jobId);
397  }
398 
399  $this->clearingDao->createDecisionFromEvents(
400  $itemId,
401  $userId,
402  $groupId,
403  $clearingDecisionToCopy->getType(),
404  $clearingDecisionToCopy->getScope(),
405  $clearingEventIdsToCopy
406  );
407  }
408 
417  public function mapByClearingId($clearingDecisions)
418  {
419  $mapped = array();
420 
421  foreach ($clearingDecisions as $clearingDecision) {
422  $mapped[$clearingDecision->getClearingId()] = $clearingDecision;
423  }
424 
425  return $mapped;
426  }
427 }
Structure of an Agent with all required parameters.
Definition: Agent.php:41
heartbeat($newProcessed)
Send hear beat to the scheduler.
Definition: Agent.php:203
Various utility functions to filter ClearingDecision.
Utility functions to process ClearingDecision.
processEnhancedUploadReuse($itemTreeBounds, $itemTreeBoundsReused, $reusedGroupId)
Get clearing decisions and use copyClearingDecisionIfDifferenceIsSmall()
processUploadId($uploadId)
Get the upload items and reuse based on reuse mode.
Definition: ReuserAgent.php:94
reuseMainLicense($uploadId, $groupId, $reusedUploadId, $reusedGroupId)
Reuse main license from previous upload.
mapByClearingId($clearingDecisions)
Map clearing decisions by clearing id.
copyClearingDecisionIfDifferenceIsSmall($reusedPath, $newPath, $clearingDecision, $itemId)
Use diff tool to compare files.
mapByFileId($clearingDecisions)
Maps clearing decisions by file id.
reuseCopyrights($uploadId, $reusedUploadId)
Reuse deactivated Copyrights from previous upload.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16