47 private $mapDBColumns = array(
48 "reviewedBy" =>
"ri_reviewed",
49 "department" =>
"ri_department",
50 "reportRel" =>
"ri_report_rel",
51 "community" =>
"ri_community",
52 "component" =>
"ri_component",
53 "version" =>
"ri_version",
54 "relDate" =>
"ri_release_date",
55 "sw360Link" =>
"ri_sw360_link",
56 "componentType" =>
"ri_component_type",
57 "componentId" =>
"ri_component_id",
58 "footerNote" =>
"ri_footer",
59 "generalAssesment" =>
"ri_general_assesment",
60 "gaAdditional" =>
"ri_ga_additional",
61 "gaRisk" =>
"ri_ga_risk",
62 "dependencyBinarySource" =>
"ri_depnotes",
63 "exportRestrictionText" =>
"ri_exportnotes",
64 "copyrightRestrictionText" =>
"ri_copyrightnotes",
65 "criticalFilesText" =>
"ri_criticalnotes"
71 private $radioListUR = array(
72 "nonCritical" =>
"critical",
73 "critical" =>
"critical",
74 "noDependency" =>
"dependencySourceBinary",
75 "dependencySource" =>
"dependencySourceBinary",
76 "dependencyBinary" =>
"dependencySourceBinary",
77 "noExportRestriction" =>
"exportRestriction",
78 "exportRestriction" =>
"exportRestriction",
79 "noRestriction" =>
"restrictionForUse",
80 "restrictionForUse" =>
"restrictionForUse"
86 private $checkBoxListSPDX = array(
87 "spdxLicenseComment" =>
"spdxLicenseComment",
88 "ignoreFilesWOInfo" =>
"ignoreFilesWOInfo",
89 "osselotExport" =>
"osselotExport"
95 $this->Name =
"report_conf";
96 $this->Title = _(
"Report Configuration");
97 $this->Dependency = array(
"browse");
100 parent::__construct();
101 $this->uploadDao = $GLOBALS[
'container']->get(
'dao.upload');
102 $this->
dbManager = $GLOBALS[
'container']->get(
'db.manager');
103 $this->userDao = $GLOBALS[
'container']->get(
'dao.user');
104 $this->clearingDao = $GLOBALS[
'container']->get(
'dao.clearing');
105 $this->licenseDao = $GLOBALS[
'container']->get(
'dao.license');
113 $tooltipText = _(
"Report Configuration");
114 menu_insert(
"Browse-Pfile::Conf",5,$this->Name,$tooltipText);
117 $URI = $this->Name . $Parm;
127 menu_insert(
"View-Meta::{$menuText}", $menuPosition);
131 $tooltipText = _(
"Report Configuration");
134 menu_insert(
"View::{$menuText}", $menuPosition, $URI, $tooltipText);
137 menu_insert(
"View-Meta::{$menuText}", $menuPosition, $URI, $tooltipText);
139 menu_insert(
"Browse::Conf", -3, $URI, $tooltipText);
152 $row = $this->uploadDao->getReportInfo($uploadId);
153 foreach ($this->mapDBColumns as $key => $value) {
154 $vars[$key] = $row[$value];
156 foreach ([
"dependencyBinarySource",
"exportRestrictionText",
157 "copyrightRestrictionText",
"criticalFilesText"] as $noteField) {
158 if ($vars[$noteField] ==
'NA') {
159 $vars[$noteField] =
'';
162 $textAreaNoneStyle =
' style="display:none;overflow:auto;width:98%;height:80px;"';
163 $textAreaStyle =
' style="overflow:auto;width:98%;height:80px;"';
164 $vars[
'styleDependencyTA'] = $vars[
'styleExportTA'] = $vars[
'styleRestrictionTA'] = $textAreaStyle;
165 $vars[
'styleCriticalTA'] = $textAreaStyle;
166 if ($row[
'ri_criticalnotes'] ==
'NA' || empty($row[
'ri_criticalnotes'])) {
167 $vars[
'styleCriticalTA'] = $textAreaNoneStyle;
169 if ($row[
'ri_depnotes'] ==
'NA' || empty($row[
'ri_depnotes'])) {
170 $vars[
'styleDependencyTA'] = $textAreaNoneStyle;
173 if ($row[
'ri_exportnotes'] ==
'NA' || empty($row[
'ri_exportnotes'])) {
174 $vars[
'styleExportTA'] = $textAreaNoneStyle;
177 if ($row[
'ri_copyrightnotes'] ==
'NA' || empty($row[
'ri_copyrightnotes'])) {
178 $vars[
'styleRestrictionTA'] = $textAreaNoneStyle;
181 if (!empty($row[
'ri_ga_checkbox_selection'])) {
182 $listURCheckbox = explode(
',', $row[
'ri_ga_checkbox_selection']);
183 foreach (array_keys($this->radioListUR) as $key => $value) {
184 $vars[$value] = $listURCheckbox[$key];
188 if (!empty($row[
'ri_spdx_selection'])) {
189 $listSPDXCheckbox = explode(
',', $row[
'ri_spdx_selection']);
190 foreach (array_keys($this->checkBoxListSPDX) as $key => $value) {
191 $vars[$value] = $listSPDXCheckbox[$key];
194 foreach (array_keys($this->checkBoxListSPDX) as $key) {
195 $vars[$key] =
'unchecked';
199 $uploadTreeTableName = $this->uploadDao->getUploadtreeTableName($uploadId);
200 $itemTreeBounds = $this->uploadDao->getParentItemBounds($uploadId, $uploadTreeTableName);
201 $allClearingDecisions = $this->clearingDao->getFileClearingsFolder($itemTreeBounds, $groupId);
204 $excludedObligations = array();
205 $excludedObligations = (array) json_decode($row[
'ri_excluded_obligations'],
true);
207 $tableRows .=
'<tr><td style="width:35%">'.$obTopic.
'</td>';
208 $tableRows .=
'<td><textarea readonly="readonly" style="overflow:auto;width:98%;height:80px;">'.
209 $obData[
'text'].
'</textarea></td><td>';
210 foreach ($obData[
'license'] as $value) {
211 if (!empty($excludedObligations[$obTopic]) && in_array($value, $excludedObligations[$obTopic])) {
212 $tableRows .=
'<input class="browse-upload-checkbox view-license-rc-size" type="checkbox" name="obLicenses['.urlencode($obTopic).
'][]" value="'.$value.
'" checked> '.$value.
'<br />';
214 $tableRows .=
'<input class="browse-upload-checkbox view-license-rc-size" type="checkbox" name="obLicenses['.urlencode($obTopic).
'][]" value="'.$value.
'"> '.$value.
'<br />';
217 $tableRows .=
'</td></tr>';
219 $tableRowsUnifiedReport =
"";
220 $unifiedColumns = array();
221 if (!empty($row[
'ri_unifiedcolumns'])) {
222 $unifiedColumns = (array) json_decode($row[
'ri_unifiedcolumns'],
true);
224 $unifiedColumns = UploadDao::UNIFIED_REPORT_HEADINGS;
226 foreach ($unifiedColumns as $name => $unifiedReportColumns) {
227 foreach ($unifiedReportColumns as $columnName => $isenabled) {
228 $tableRowsUnifiedReport .=
'<tr>';
229 $tableRowsUnifiedReport .=
'<td><input class="form-control" type="text" style="width:95%" name="'.$name.
'[]" value="'.$columnName.
'"></td>';
232 $checked =
'checked';
234 $tableRowsUnifiedReport .=
'<td style="vertical-align:middle"><input class="browse-upload-checkbox view-license-rc-size" type="checkbox" style="width:95%" name="'.$name.
'[]" '.$checked.
'></td>';
235 $tableRowsUnifiedReport .=
'</tr>';
239 $tableRowsClixmlReport =
"";
240 $clixmlColumns = array();
241 if (!empty($row[
'ri_clixmlcolumns'])) {
242 $clixmlColumns = (array) json_decode($row[
'ri_clixmlcolumns'],
true);
244 $clixmlColumns = UploadDao::CLIXML_REPORT_HEADINGS;
246 foreach ($clixmlColumns as $name => $clixmlReportColumns) {
247 foreach ($clixmlReportColumns as $columnName => $isenabled) {
248 $tableRowsClixmlReport .=
'<tr>';
249 $tableRowsClixmlReport .=
'<td><input class="form-control" type="text" style="width:95%" name="'.$name.
'[]" value="'.$columnName.
'" readonly></td>';
252 $checked =
'checked';
254 $tableRowsClixmlReport .=
'<td style="vertical-align:middle"><input class="browse-upload-checkbox view-license-rc-size" type="checkbox" style="width:95%" name="'.$name.
'[]" '.$checked.
'></td>';
255 $tableRowsClixmlReport .=
'</tr>';
259 if (!empty($row[
'ri_globaldecision'])) {
260 $vars[
'applyGlobal'] =
"checked";
262 $vars[
'tableRows'] = $tableRows;
263 $vars[
'tableRowsUnifiedReport'] = $tableRowsUnifiedReport;
264 $vars[
'tableRowsClixmlReport'] = $tableRowsClixmlReport;
279 foreach ($clearingDecisions as $clearingDecision) {
280 if ($clearingDecision->getType() == DecisionTypes::IRRELEVANT) {
283 $uploadTreeId = $clearingDecision->getUploadTreeId();
284 foreach ($clearingDecision->getClearingLicenses() as $clearingLicense) {
285 if ($clearingLicense->isRemoved()) {
288 $ack = $clearingLicense->getAcknowledgement();
289 if (empty(
trim($ack))) {
292 if (!isset($ackData[$ack])) {
293 $ackData[$ack] = array(
'files' => array(),
'licenses' => array());
295 $ackData[$ack][
'files'][$uploadTreeId] =
true;
296 $ackData[$ack][
'licenses'][$clearingLicense->getShortName()] =
true;
300 foreach ($ackData as $ack => $data) {
301 $result[$ack] = array(
302 'count' => count($data[
'files']),
303 'licenses' => array_keys($data[
'licenses'])
319 foreach ($acknowledgements as $ackText => $ackData) {
320 $ackHtml = htmlspecialchars($ackText, ENT_QUOTES);
321 $licensesHtml = htmlspecialchars(implode(
', ', $ackData[
'licenses']));
323 $rows .=
'<td style="width:5%;text-align:center">'
324 .
'<a href="#" class="ack-count-link" data-upload="' . $uploadId
325 .
'" data-ack="' . $ackHtml .
'">' . $ackData[
'count'] .
'</a></td>';
326 $rows .=
'<td style="width:60%"><textarea class="ack-text-area" readonly="readonly"'
327 .
' data-original-ack="' . $ackHtml .
'"'
328 .
' style="overflow:auto;width:98%;height:60px;">'
329 . $ackHtml .
'</textarea></td>';
330 $rows .=
'<td style="width:25%">' . $licensesHtml .
'</td>';
331 $rows .=
'<td style="width:10%;text-align:center">'
332 .
'<button type="button" class="btn btn-danger btn-sm delete-ack-btn"'
333 .
' data-upload="' . $uploadId .
'" data-ack="' . $ackHtml .
'">'
334 .
'Delete</button></td>';
348 $allClearedLicenses = array();
350 foreach ($clearingDecisions as $clearingDecision) {
351 if ($clearingDecision->getType() == DecisionTypes::IRRELEVANT) {
354 foreach ($clearingDecision->getClearingLicenses() as $clearingLicense) {
355 if ($clearingLicense->isRemoved()) {
358 $allClearedLicenses[$licenseMap->getProjectedId($clearingLicense->getLicenseId())] =
true;
361 $uniqueLicenseIds = array_keys($allClearedLicenses);
362 $allObligations = array_merge(
363 $this->licenseDao->getLicenseObligations($uniqueLicenseIds) ?: array(),
364 $this->licenseDao->getLicenseObligations($uniqueLicenseIds,
true) ?: array()
366 $groupedObligations = array();
367 foreach ($allObligations as $obligation) {
368 $groupBy = $obligation[
'ob_topic'];
369 $licenseName = LicenseRef::convertToSpdxId($obligation[
'rf_shortname'],
370 $obligation[
'rf_spdx_id']);
371 if (array_key_exists($groupBy, $groupedObligations)) {
372 $groupedObligations[$groupBy][
'license'][$licenseName] =
true;
374 $groupedObligations[$groupBy] = array(
375 "topic" => $obligation[
'ob_topic'],
376 "text" => $obligation[
'ob_text'],
377 "license" => array($licenseName =>
true)
381 foreach ($groupedObligations as &$ob) {
382 $ob[
'license'] = array_keys($ob[
'license']);
384 return $groupedObligations;
393 foreach ($listParams as $listkey => $listValue) {
395 if ($ret != $listkey) {
396 $cbList[] =
"unchecked";
398 $cbList[] =
"checked";
401 $cbSelectionList = implode(
",", $cbList);
403 return $cbSelectionList;
409 $groupId = Auth::getGroupId();
410 $userId = Auth::getUserId();
411 if (!$this->uploadDao->isAccessible($uploadId, $groupId)) {
416 $this->vars[
'micromenu'] =
Dir2Browse(
"browse", $itemId, NULL, $showBox=0,
"View-Meta");
417 $this->vars[
'globalClearingAvailable'] = Auth::isClearingAdmin();
421 if (isset($submitReportConf)) {
422 $applyGlobal = @$_POST[
"applyGlobal"];
423 $applyGlobal = !empty($applyGlobal) ? 1 : 0;
425 $obLicensesEncoded = @$_POST[
"obLicenses"];
426 $obLicensesEncoded = !empty($obLicensesEncoded) ? $obLicensesEncoded : array();
427 $obLicenses = array();
428 array_walk($obLicensesEncoded,
429 function (&$licArray, $obTopic) use (&$obLicenses) {
430 $obLicenses[urldecode($obTopic)] = $licArray;
435 foreach ($this->mapDBColumns as $key => $value) {
436 $columns .= $value.
" = $".$i.
", ";
442 $unifiedReportColumnsForJson = array();
443 foreach (UploadDao::UNIFIED_REPORT_HEADINGS as $columnName => $columnValue) {
444 $columnResult = @$_POST[$columnName];
445 $unifiedReportColumnsForJson[$columnName] = array($columnResult[0] => isset($columnResult[1]) ? $columnResult[1] :
null);
447 $clixmlColumnsForJson = array();
448 foreach (UploadDao::CLIXML_REPORT_HEADINGS as $columnName => $columnValue) {
449 $columnResult = @$_POST[$columnName];
450 $clixmlColumnsForJson[$columnName] = array($columnResult[0] => isset($columnResult[1]) ? $columnResult[1] :
null);
452 $checkBoxUrPos = count($parms);
454 $checkBoxSpdxPos = count($parms);
455 $parms[] = json_encode($obLicenses);
456 $excludeObligationPos = count($parms);
457 $parms[] = json_encode($unifiedReportColumnsForJson);
458 $unifiedColumnsPos = count($parms);
459 $parms[] = json_encode($clixmlColumnsForJson);
460 $clixmlColumnsPos = count($parms);
461 $parms[] = $applyGlobal;
462 $applyGlobalPos = count($parms);
463 $parms[] = $uploadId;
464 $uploadIdPos = count($parms);
466 $SQL =
"UPDATE report_info SET $columns" .
467 "ri_ga_checkbox_selection = $$checkBoxUrPos, " .
468 "ri_spdx_selection = $$checkBoxSpdxPos, " .
469 "ri_excluded_obligations = $$excludeObligationPos, " .
470 "ri_unifiedcolumns = $$unifiedColumnsPos, " .
471 "ri_clixmlcolumns = $$clixmlColumnsPos, " .
472 "ri_globaldecision = $$applyGlobalPos " .
473 "WHERE upload_fk = $$uploadIdPos;";
474 $this->
dbManager->getSingleRow($SQL, $parms,
475 __METHOD__ .
"updateReportInfoData");
477 if (@$_POST[
'markGlobal']) {
478 $upload = $this->uploadDao->getUpload($uploadId);
479 $uploadName = $upload->getFilename();
480 $jobId = JobAddJob($userId, $groupId, $uploadName, $uploadId);
483 $conflictStrategyId =
"global";
485 $deciderPlugin->AgentAdd($jobId, $uploadId, $errorMsg, array(), $conflictStrategyId);
488 $text = _(
"Your jobs have been added to job queue.");
489 $linkText = _(
"View Jobs");
490 $this->vars[
'message'] =
"$schedulerMsg" .
"$text <a href=\"$url\">$linkText</a>";
494 $this->vars[
'typemap'] = [];
495 foreach (ComponentType::TYPE_MAP as $key => $name) {
496 if ($key == ComponentType::PACKAGEURL) {
499 $this->vars[
'typemap'][] = [
'key' => $key,
'name' => $name];
503 public function getTemplateName()
505 return "ui-report-conf.html.twig";
516 var reportTabCookie = 'stickyReportTab';
518 $(document).ready(function() {
519 $(\"#confTabs\").tabs({
520 active: ($.cookie(reportTabCookie) || 0),
521 activate: function(e, ui){
522 // Get active tab index and update cookie
523 var idString = $(e.currentTarget).attr('id');
524 idString = parseInt(idString.slice(-1)) - 1;
525 $.cookie(reportTabCookie, idString);
526 // Hide submit button on acknowledgements tab (AJAX-only tab)
527 if (ui.newPanel.attr('id') === 'acknowledgementsConfTab') {
528 $('#reportConfSubmit').hide();
530 $('#reportConfSubmit').show();
535 var activeIdx = $.cookie(reportTabCookie) || 0;
536 if ($(\"#confTabs .ui-tabs-panel\").eq(activeIdx).attr('id') === 'acknowledgementsConfTab') {
537 $('#reportConfSubmit').hide();
539 $(\"input[name='critical']\").change(function(){
540 var val = $(\"input[name='critical']:checked\").val();
541 if (val == 'nonCritical') {
542 $('#criticalFilesText').hide();
543 $('#criticalFilesText').val('');
545 $('#criticalFilesText').css('display', 'block');
548 $(\"input[name='dependencySourceBinary']\").change(function(){
549 var val = $(\"input[name='dependencySourceBinary']:checked\").val();
550 if (val == 'noDependency') {
551 $('#dependencyBinarySource').hide();
552 $('#dependencyBinarySource').val('');
554 $('#dependencyBinarySource').css('display', 'block');
557 $(\"input[name='exportRestriction']\").change(function(){
558 var val = $(\"input[name='exportRestriction']:checked\").val();
559 if (val == 'noExportRestriction') {
560 $('#exportRestrictionText').hide();
561 $('#exportRestrictionText').val('');
563 $('#exportRestrictionText').css('display', 'block');
566 $(\"input[name='restrictionForUse']\").change(function(){
567 var val = $(\"input[name='restrictionForUse']:checked\").val();
568 if (val == 'noRestriction') {
569 $('#copyrightRestrictionText').hide();
570 $('#copyrightRestrictionText').val('');
572 $('#copyrightRestrictionText').css('display', 'block');
576 $('#osselotExportCheckbox').change(function() {
577 if ($(this).is(':checked')) {
578 $('#spdxLicenseCommentCheckbox').prop('checked', true);
581 $(\"[data-toggle='tooltip']\").tooltip();
582 $('#spdxLicenseCommentCheckbox').change(function() {
584 $('#osselotExportCheckbox').prop('checked', false);
588 var ackAjaxUrl = '?mod=ajax-acknowledgement-conf';
590 $(document).on('click', '.ack-count-link', function(e) {
592 var upload = $(this).data('upload');
593 var ack = $(this).data('ack');
594 $('#ackFilesModalBody').html('<p>Loading...</p>');
595 $('#ackFilesModalCount').text('');
596 $('#ackFilesModal').modal('show');
597 $.get(ackAjaxUrl, {action: 'getFiles', upload: upload, ack: ack},
599 if (!data || data.length === 0) {
600 $('#ackFilesModalCount').text('');
601 $('#ackFilesModalBody').html('<p>No files found.</p>');
604 $('#ackFilesModalCount').text('(' + data.length + ' files)');
605 var html = '<table class=\"table table-condensed table-hover\" style=\"margin:0;\">'
606 + '<thead><tr><th>#</th><th>File</th></tr></thead><tbody>';
607 $.each(data, function(i, file) {
608 html += '<tr><td>' + (i + 1) + '</td>'
609 + '<td><a href=\"' + file.url + '\" target=\"_blank\">'
610 + $('<span/>').text(file.name).html()
613 html += '</tbody></table>';
614 $('#ackFilesModalBody').html(html);
617 $('#ackFilesModalCount').text('');
618 $('#ackFilesModalBody').html('<p>Error loading files.</p>');
622 $(document).on('dblclick', '.ack-text-area', function() {
623 if (!$(this).prop('readonly')) {
627 var td = ta.closest('td');
628 ta.prop('readonly', false).css('border', '2px solid #337ab7').focus();
629 td.append('<div class=\"ack-edit-actions\" style=\"margin-top:4px;\">'
630 + '<button type=\"button\" class=\"btn btn-primary btn-xs ack-save-btn\">Save</button> '
631 + '<button type=\"button\" class=\"btn btn-light btn-xs ack-cancel-btn\">Cancel</button>'
635 $(document).on('click', '.ack-save-btn', function() {
636 var row = $(this).closest('tr');
637 var td = $(this).closest('td');
638 var ta = td.find('.ack-text-area');
639 var newAck = ta.val();
640 var oldAck = ta.data('original-ack');
641 if (newAck === oldAck) {
642 ta.prop('readonly', true).css('border', '');
643 td.find('.ack-edit-actions').remove();
646 var upload = row.find('.ack-count-link').data('upload');
648 {action: 'updateAcknowledgement', upload: upload, oldAck: oldAck, newAck: newAck},
650 if (data && data.status === 'success') {
651 $('#acknowledgementsConfTab tbody tr').each(function() {
652 if ($(this).find('.ack-text-area').data('original-ack') === newAck
653 && this !== row[0]) {
658 .data('original-ack', newAck)
659 .prop('readonly', true)
661 row.find('.ack-count-link').text(data.count).data('ack', newAck);
662 row.find('.delete-ack-btn').data('ack', newAck);
663 td.find('.ack-edit-actions').remove();
665 alert('Failed to update acknowledgement.');
669 alert('Error communicating with server.');
673 $(document).on('click', '.ack-cancel-btn', function() {
674 var td = $(this).closest('td');
675 var ta = td.find('.ack-text-area');
676 ta.val(ta.data('original-ack'))
677 .prop('readonly', true)
679 td.find('.ack-edit-actions').remove();
682 $(document).on('click', '.delete-ack-btn', function() {
683 var upload = $(this).data('upload');
684 var ack = $(this).data('ack');
685 if (!confirm('Are you sure you want to clear this acknowledgement from all files?')) {
688 var row = $(this).closest('tr');
690 {action: 'deleteAcknowledgement', upload: upload, ack: ack},
692 if (data && data.status === 'success') {
693 row.fadeOut(400, function() { row.remove(); });
695 alert('Failed to delete acknowledgement.');
699 alert('Error communicating with server.');
708 $NewPlugin->Initialize();
This is the Plugin class. All plugins should:
Output()
This function is called when user output is requested. This function is responsible for content....
Contains the constants and helpers for authentication of user.
Wrapper class for license map.
getAllObligationsForGivenUploadId($groupId, array $clearingDecisions)
get all the obligations for cleared licenses
createScriptBlock()
Create Script block for conf.
buildAcknowledgementRows($uploadId, array $clearingDecisions)
Build HTML table rows for acknowledgements tab.
getAllAcknowledgementsForUpload(array $clearingDecisions)
Get acknowledgements for cleared licenses grouped by text.
allReportConfiguration($uploadId, $groupId)
list all the options for Report Configuration
RegisterMenus()
Customize submenus.
getCheckBoxSelectionList($listParams)
__construct()
base constructor. Most plugins will just use this
Dir2Browse($Mod, $UploadtreePk, $LinkLast=NULL, $ShowBox=1, $ShowMicro=NULL, $Enumerate=-1, $PreText='', $PostText='', $uploadtree_tablename="uploadtree")
Get an html linked string of a file browse path.
Traceback_uri()
Get the URI without query to this location.
GetParm($parameterName, $parameterType)
This function will retrieve the variables and check data types.
Traceback_parm_keep($List)
Create a new URI, keeping only these items.
plugin_find($pluginName)
Given the official name of a plugin, return the $Plugins object.
GetRunnableJobList()
Get runnable job list, the process is below:
char * trim(char *ptext)
Trimming whitespace.
#define PLUGIN_DB_READ
Plugin requires read permission on DB.
fo_dbManager * dbManager
fo_dbManager object