13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpFoundation\Response;
23 const NAME =
'multicompare';
32 public function __construct()
34 parent::__construct(self::NAME, [
35 self::TITLE => _(
"Multi-Component Comparison"),
36 self::DEPENDENCIES => [
"browse",
"view"],
38 self::REQUIRES_LOGIN =>
true,
41 $this->uploadDao = $this->
getObject(
'dao.upload');
42 $this->agentDao = $this->
getObject(
'dao.agent');
47 private function createFilePickerMultiTable():
void
49 if ($this->
dbManager->existsTable(
'file_picker_multi')) {
53 "CREATE TABLE file_picker_multi (
54 file_picker_multi_pk serial NOT NULL PRIMARY KEY,
55 user_fk integer NOT NULL,
57 last_access_date date NOT NULL
75 $TreeInfo = $this->
dbManager->getSingleRow(
76 "SELECT ut.*, u.uploadtree_tablename, u.upload_filename
78 JOIN upload u ON u.upload_pk = ut.upload_fk
79 WHERE ut.uploadtree_pk = \$1",
80 [$uploadtree_pk], __METHOD__ .
'.bootstrap'
89 $tableName = $TreeInfo[
'uploadtree_tablename'];
90 if ($tableName !==
'uploadtree') {
91 $specific = $this->
dbManager->getSingleRow(
92 "SELECT lft, rgt, ufile_mode, ufile_name, pfile_fk, parent,
93 uploadtree_pk, upload_fk
94 FROM $tableName WHERE uploadtree_pk = \$1",
95 [$uploadtree_pk], __METHOD__ .
".$tableName"
98 $TreeInfo = array_merge($TreeInfo, $specific);
102 $upload_pk = intval($TreeInfo[
'upload_fk']);
103 $TreeInfo[
'display_name'] = !empty($TreeInfo[
'upload_filename'])
104 ? basename($TreeInfo[
'upload_filename'])
105 : $TreeInfo[
'ufile_name'];
112 $TreeInfo = array_merge($TreeInfo, $agentPks);
113 $TreeInfo[
'agent_pk'] = $TreeInfo[
'nomos_agent_pk'];
127 static $existsCache = [];
130 'nomos_pk' =>
'nomos_ars',
131 'monk_pk' =>
'monk_ars',
132 'ojo_pk' =>
'ojo_ars',
133 'copyright_pk' =>
'copyright_ars',
134 'ecc_pk' =>
'ecc_ars',
139 foreach ($agentDef as $alias => $table) {
140 if (!array_key_exists($table, $existsCache)) {
141 $existsCache[$table] = $this->
dbManager->existsTable($table);
143 if ($existsCache[$table]) {
144 $parts[] =
"(SELECT a.agent_fk FROM $table a"
145 .
" JOIN agent ON agent_pk=a.agent_fk"
146 .
" WHERE a.upload_fk=\$1 AND a.ars_success AND agent_enabled"
147 .
" ORDER BY agent_ts DESC LIMIT 1) AS $alias";
150 $parts[] =
"NULL::integer AS $alias";
155 $stmt = __METHOD__ .
'.' . $existMask;
156 $this->
dbManager->prepare($stmt,
"SELECT " . implode(
",\n", $parts));
157 $res = $this->
dbManager->execute($stmt, [$uploadPk]);
158 $row = $this->
dbManager->fetchArray($res) ?: [];
162 'nomos_agent_pk' => intval($row[
'nomos_pk'] ?? 0),
163 'monk_agent_pk' => intval($row[
'monk_pk'] ?? 0),
164 'ojo_agent_pk' => intval($row[
'ojo_pk'] ?? 0),
165 'copyright_agent_pk' => intval($row[
'copyright_pk'] ?? 0),
166 'ecc_agent_pk' => intval($row[
'ecc_pk'] ?? 0),
175 private function AddDataStr(array $treeInfo, array &$children,
string $mode): void
177 if ($mode ===
'license') {
178 $licAgentPks = array_values(array_filter([
179 $treeInfo[
'nomos_agent_pk'],
180 $treeInfo[
'monk_agent_pk'],
181 $treeInfo[
'ojo_agent_pk'],
186 if (!empty($licAgentPks)) {
187 $pfileUniq = array_values(array_unique(array_filter(
188 array_map(
function ($c) {
189 return intval($c[
'pfile_fk'] ?? 0);
192 if (!empty($pfileUniq)) {
195 foreach ($licAgentPks as $apk) {
197 $agentPh[] =
'$' . count($params);
200 foreach ($pfileUniq as $pf) {
202 $pfilePh[] =
'$' . count($params);
204 $agentIn = implode(
',', $agentPh);
205 $pfileIn = implode(
',', $pfilePh);
206 $stmt = __METHOD__ .
".licbatch." . implode(
'_', $licAgentPks) .
".p" . count($pfileUniq);
208 "SELECT lf.pfile_fk, lr.rf_pk, lr.rf_shortname
209 FROM ONLY license_ref lr, license_file lf
210 WHERE lf.rf_fk = lr.rf_pk
211 AND lf.agent_fk IN ($agentIn)
212 AND lf.pfile_fk IN ($pfileIn)"
214 $res = $this->
dbManager->execute($stmt, $params);
215 while ($row = $this->
dbManager->fetchArray($res)) {
216 $pf = intval($row[
'pfile_fk']);
218 $licByPfile[$pf][intval($row[
'rf_pk'])] = $row[
'rf_shortname'];
224 foreach ($children as &$child) {
225 $pf = intval($child[
'pfile_fk'] ?? 0);
227 $dataarray = $licByPfile[$pf] ?? [];
231 foreach ($licAgentPks as $agentPk) {
233 $treeInfo[
'uploadtree_tablename']);
236 $child[
'dataarray'] = $dataarray;
237 $child[
'datastr'] = implode(
", ", $dataarray);
238 if (empty($child[
'datastr'])) {
239 $child[
'datastr'] =
"No_license_found";
240 $child[
'dataarray'] = [
"No_license_found" =>
"No_license_found"];
245 } elseif ($mode ===
'copyright' || $mode ===
'ecc') {
246 $table = ($mode ===
'ecc') ?
'ecc' :
'copyright';
247 $agentPk = ($mode ===
'ecc')
248 ? $treeInfo[
'ecc_agent_pk']
249 : $treeInfo[
'copyright_agent_pk'];
254 $pfileUniq = array_values(array_unique(array_filter(
255 array_map(
function ($c) {
256 return intval($c[
'pfile_fk'] ?? 0);
259 if (!empty($pfileUniq)) {
260 $params = [intval($agentPk)];
262 foreach ($pfileUniq as $pf) {
264 $pfilePh[] =
'$' . count($params);
266 $pfileIn = implode(
',', $pfilePh);
267 $stmt = __METHOD__ .
".$table.batch.p" . count($pfileUniq);
269 "SELECT pfile_fk, content FROM $table
270 WHERE agent_fk=\$1 AND pfile_fk IN ($pfileIn)
271 AND content IS NOT NULL AND content!=''
272 ORDER BY pfile_fk, content"
274 $res = $this->
dbManager->execute($stmt, $params);
275 while ($row = $this->
dbManager->fetchArray($res)) {
276 $pf = intval($row[
'pfile_fk']);
277 $dataByPfile[$pf][$row[
'content']] = $row[
'content'];
283 foreach ($children as &$child) {
284 $pf = intval($child[
'pfile_fk'] ?? 0);
285 $dataarray = $dataByPfile[$pf] ?? [];
286 $child[
'dataarray'] = $dataarray;
287 $child[
'datastr'] = implode(
", ", $dataarray);
295 private function FilterN(
string $filter, array &$Master,
int $N): void
327 foreach ($Master as $key => $row) {
329 foreach ($row as $child) {
330 if (!empty($child) && !empty($child[
'pfile_fk'])) {
331 $pfiles[] = $child[
'pfile_fk'];
334 if (count($pfiles) === $N && count(array_unique($pfiles)) === 1) {
335 unset($Master[$key]);
346 foreach ($Master as $key => $row) {
347 $present = array_filter($row, fn($c) => !empty($c));
348 if (count($present) !== $N) {
351 if (count(array_unique(array_column($present,
'ufile_name'))) === 1 &&
352 count(array_unique(array_column($present,
'datastr'))) === 1) {
353 unset($Master[$key]);
363 foreach ($Master as $key => $row) {
364 $present = array_filter($row, fn($c) => !empty($c));
365 if (count($present) !== $N) {
368 if (count(array_unique(array_column($present,
'fuzzyname'))) === 1 &&
369 count(array_unique(array_column($present,
'datastr'))) === 1) {
370 unset($Master[$key]);
382 foreach ($Master as $key => $row) {
383 $present = array_filter($row, fn($c) => !empty($c));
384 if (empty($present)) {
388 foreach ($present as $child) {
389 $ds = $child[
'datastr'];
390 if ($ds !==
'' && $ds !==
'No_license_found') {
396 unset($Master[$key]);
406 foreach ($Master as $key => $row) {
407 $present = array_filter($row, fn($c) => !empty($c));
408 if (count($present) !== $N) {
411 if (count(array_unique(array_column($present,
'datastr'))) === 1) {
412 unset($Master[$key]);
422 private function ChildElt(array $child,
int $colIdx, array $row,
423 array $treeInfoArray,
string $mode,
int $baseline): string
425 $dataarray = $child[
'dataarray'] ?? [];
429 $bIdx = $baseline - 1;
430 if (isset($row[$bIdx]) && !empty($row[$bIdx][
'dataarray'])) {
431 $refKeys = array_keys($row[$bIdx][
'dataarray']);
434 foreach ($row as $c => $other) {
435 if ($c === $colIdx || empty($other) || empty($other[
'dataarray'])) {
438 foreach (array_keys($other[
'dataarray']) as $k) {
442 $refKeys = array_unique($refKeys);
444 $refKeySet = array_flip($refKeys);
447 foreach ($dataarray as $k => $val) {
448 $missing = !empty($refKeys) && !isset($refKeySet[$k]);
450 $badges[] =
"<span class='badge badge-pill'"
451 .
" style='background-color:#ffd6cc;color:#333;font-weight:normal'>"
452 . htmlspecialchars($val) .
"</span>";
454 $badges[] =
"<span class='badge badge-pill badge-light border'>"
455 . htmlspecialchars($val) .
"</span>";
458 $dataStr = implode(
" ", $badges);
460 $ColStr =
"<td class='align-top py-1' id='c{$child['uploadtree_pk']}'>";
461 $ColStr .= $child[
'linkurl'] ?? htmlspecialchars($child[
'ufile_name']);
462 if (!empty($dataStr)) {
463 $ColStr .=
"<div class='mt-1 ml-1'>$dataStr</div>";
467 $agentPk = $treeInfoArray[$colIdx][
'agent_pk'] ?? 0;
468 $uploadtree_tablename = $treeInfoArray[$colIdx][
'uploadtree_tablename'] ??
'uploadtree';
469 $ColStr .=
"<td class='align-top py-1' style='white-space:nowrap'>";
470 $uniqueTagArray = [];
472 $child[
'upload_fk'], $child[
'uploadtree_pk'],
473 $agentPk, $child[
'pfile_fk'],
true,
474 $uniqueTagArray, $uploadtree_tablename
485 string $mode,
int $baseline,
string $view): string
487 $N = count($treeInfoArray);
489 if ($view ===
'matrix') {
490 return $this->FileMatrixRows($Master, $N);
494 foreach ($Master as $row) {
496 for ($c = 0; $c < $N; $c++) {
498 $parts[] =
"<td class='border-left border-success p-0' style='width:3px'></td>";
500 if (empty($row[$c])) {
501 $parts[] =
"<td class='text-muted py-1'>—</td><td></td>";
503 $parts[] = $this->
ChildElt($row[$c], $c, $row, $treeInfoArray, $mode, $baseline);
508 return implode(
"", $parts);
511 private function FileMatrixRows(array $Master,
int $N): string
514 foreach ($Master as $row) {
517 for ($c = 0; $c < $N && empty($firstName); $c++) {
518 if (!empty($row[$c])) {
519 $firstName = htmlspecialchars($row[$c][
'ufile_name']);
522 $parts[] =
"<td class='py-1'>$firstName</td>";
526 for ($c = 0; $c < $N; $c++) {
527 if (!empty($row[$c]) && !empty($row[$c][
'pfile_fk'])) {
528 $pfiles[] = $row[$c][
'pfile_fk'];
531 $allSameHash = count($pfiles) >= 2 && count(array_unique($pfiles)) === 1;
533 for ($c = 0; $c < $N; $c++) {
534 if (!empty($row[$c])) {
536 $parts[] = $allSameHash
537 ?
"<td class='text-center py-1'><span class='badge badge-light border text-muted' title='identical'>✔</span></td>"
538 :
"<td class='text-center py-1'><span class='badge badge-success' title='differs'>✔</span></td>";
540 $parts[] =
"<td class='text-center py-1 text-muted'>—</td>";
545 return implode(
"", $parts);
556 array $treeInfoArray,
string $mode): array
558 $uniqueFiles = array_fill(0, $N, 0);
559 $missingFiles = array_fill(0, $N, 0);
560 $uniqueEntries = array_fill(0, $N, []);
562 foreach ($Master as $row) {
565 for ($c = 0; $c < $N; $c++) {
566 if (!empty($row[$c])) {
567 $presentSet[$c] =
true;
570 $nPresent = count($presentSet);
572 for ($c = 0; $c < $N; $c++) {
573 if (!isset($presentSet[$c])) {
577 if ($nPresent === 1) {
578 $uniqueFiles[key($presentSet)]++;
583 foreach ($presentSet as $c => $_) {
584 foreach ($row[$c][
'dataarray'] ?? [] as $k => $val) {
585 $keyColCount[$k] = ($keyColCount[$k] ?? 0) + 1;
590 foreach ($presentSet as $c => $_) {
591 foreach ($row[$c][
'dataarray'] ?? [] as $k => $val) {
592 if ($keyColCount[$k] === 1) {
593 $uniqueEntries[$c][$k] = $val;
600 for ($c = 0; $c < $N; $c++) {
601 $uniqList = array_unique($uniqueEntries[$c]);
602 $uniqCount = count($uniqList);
603 $shown = array_map(
'htmlspecialchars', array_slice($uniqList, 0, 10));
605 'name' => htmlspecialchars($treeInfoArray[$c][
'display_name'] ?? (
"Col " . ($c + 1))),
606 'uniqueFiles' => $uniqueFiles[$c],
607 'missingFiles' => $missingFiles[$c],
608 'uniqueEntries' => $shown,
609 'moreCount' =>
max(0, $uniqCount - 10),
619 private function buildHistData(array $items, array $treeInfoArray,
string $mode): array
624 for ($c = 0; $c < $N; $c++) {
625 $treeInfo = $treeInfoArray[$c];
627 if ($mode ===
'license') {
628 $licAgentPks = array_values(array_filter([
629 $treeInfo[
'nomos_agent_pk'],
630 $treeInfo[
'monk_agent_pk'],
631 $treeInfo[
'ojo_agent_pk'],
633 if (empty($licAgentPks)) {
636 $lft = intval($treeInfo[
'lft']);
637 $rgt = intval($treeInfo[
'rgt']);
638 $upPk = intval($treeInfo[
'upload_fk']);
639 $table = $treeInfo[
'uploadtree_tablename'];
641 $params = [$lft, $rgt];
643 if ($table ===
'uploadtree_a' || $table ===
'uploadtree') {
645 $upClause =
"upload_fk=\$" . count($params) .
" AND ";
648 $agentPlaceholders = [];
649 foreach ($licAgentPks as $apk) {
651 $agentPlaceholders[] =
"\$" . count($params);
653 $agentIn = implode(
",", $agentPlaceholders);
654 $sql =
"SELECT rf_shortname AS entry, count(DISTINCT pfile_fk) AS cnt
655 FROM ONLY license_ref, license_file,
656 (SELECT DISTINCT(pfile_fk) AS PF FROM $table
657 WHERE {$upClause}{$table}.lft BETWEEN \$1 AND \$2) AS SS
658 WHERE PF=pfile_fk AND agent_fk IN ($agentIn) AND rf_fk=rf_pk
659 GROUP BY rf_shortname ORDER BY cnt DESC";
660 $stmt = __METHOD__ .
".lic.$table.$c." . implode(
"_", $licAgentPks);
662 $res = $this->
dbManager->execute($stmt, $params);
663 while ($row = $this->
dbManager->fetchArray($res)) {
664 $histData[$row[
'entry']][$c] = (int)$row[
'cnt'];
668 } elseif ($mode ===
'copyright' || $mode ===
'ecc') {
669 $table = ($mode ===
'ecc') ?
'ecc' :
'copyright';
670 $agentPk = ($mode ===
'ecc')
671 ? intval($treeInfo[
'ecc_agent_pk'])
672 : intval($treeInfo[
'copyright_agent_pk']);
676 $lft = intval($treeInfo[
'lft']);
677 $rgt = intval($treeInfo[
'rgt']);
678 $upPk = intval($treeInfo[
'upload_fk']);
679 $utbl = $treeInfo[
'uploadtree_tablename'];
681 $params = [$agentPk, $lft, $rgt];
683 if ($utbl ===
'uploadtree_a' || $utbl ===
'uploadtree') {
685 $upClause =
"AND UT.upload_fk=\$" . count($params);
687 $sql =
"SELECT C.content AS entry, count(*) AS cnt
689 INNER JOIN $utbl UT ON C.pfile_fk = UT.pfile_fk
691 AND C.content IS NOT NULL AND C.content!=''
692 AND UT.lft BETWEEN \$2 AND \$3
694 GROUP BY C.content ORDER BY cnt DESC LIMIT 100";
695 $stmt = __METHOD__ .
".$mode.$utbl.$c";
697 $res = $this->
dbManager->execute($stmt, $params);
698 while ($row = $this->
dbManager->fetchArray($res)) {
699 $histData[$row[
'entry']][$c] = (int)$row[
'cnt'];
706 uasort($histData,
function (array $a, array $b):
int {
707 return array_sum($b) - array_sum($a);
714 protected function handle(Request $request): Response
716 $this->createFilePickerMultiTable();
718 $itemsRaw = $request->get(
'items',
'');
720 if (!empty($itemsRaw)) {
721 $items = array_values(array_unique(array_filter(
722 array_map(
'intval', explode(
',', $itemsRaw)),
727 $filter = $request->get(
'filter',
'samehash');
728 $mode = $request->get(
'mode',
'license');
729 $view = $request->get(
'view',
'diff');
730 $baseline = (int)($request->get(
'baseline', 0));
731 $updcache = (int)($request->get(
'updcache', 0));
733 if (!in_array($mode, [
'license',
'copyright',
'ecc'])) {
736 if (!in_array($view, [
'diff',
'matrix'])) {
740 if (count($items) < 2) {
741 return $this->flushContent(
742 "<h3>" . _(
"Please select at least 2 components to compare.") .
"</h3>"
743 .
"<p><a href='javascript:history.back()'>" . _(
"Go back") .
"</a></p>"
747 foreach ($items as $idx => $itemPk) {
751 $permRow = $this->
dbManager->getSingleRow(
752 "SELECT upload_fk FROM uploadtree WHERE uploadtree_pk = \$1",
753 [$itemPk], __METHOD__ .
'.perm'
755 if (!$permRow || !$this->uploadDao->isAccessible($permRow[
'upload_fk'], Auth::getGroupId())) {
756 return $this->flushContent(
757 "<h2>" . _(
"Permission Denied") .
" (item " . ($idx + 1) .
")</h2>"
766 $freezeCol = (int)($request->get(
'freeze', 0));
767 $frozenItem = (int)($request->get(
'itemf', 0));
768 $clickedCol = (int)($request->get(
'col', -1));
769 if ($freezeCol > 0 && $frozenItem > 0 && ($freezeCol - 1) !== $clickedCol) {
770 $colIdx0 = $freezeCol - 1;
771 if (isset($items[$colIdx0])) {
772 $frozenUploadFk = $this->
dbManager->getSingleRow(
773 "SELECT upload_fk FROM uploadtree WHERE uploadtree_pk = \$1",
774 [$frozenItem], __METHOD__ .
'.freeze'
776 if ($frozenUploadFk && $this->uploadDao->isAccessible($frozenUploadFk, Auth::getGroupId())) {
777 $items[$colIdx0] = $frozenItem;
782 $cacheKey =
"?mod=" . self::NAME
783 .
"&items=" . implode(
",", $items)
784 .
"&filter=$filter&mode=$mode&view=$view&baseline=$baseline"
785 . ($freezeCol > 0 ?
"&freeze=$freezeCol&itemf=$frozenItem" :
"");
791 if (!empty($cached)) {
802 foreach ($items as $c => $itemPk) {
804 if (empty($treeInfo)) {
805 return $this->flushContent(
806 "<div class='alert alert-danger'>"
807 . sprintf(_(
"Could not load data for item %d. The item may have been deleted."), $itemPk)
812 if ($mode ===
'license') {
813 $agentPk = $treeInfo[
'nomos_agent_pk'] ?: $treeInfo[
'monk_agent_pk'] ?: $treeInfo[
'ojo_agent_pk'];
814 if ($agentPk == 0 && empty($ErrMsg)) {
816 _(
"No license scan data for component %d (%s). Schedule a nomos, monk, or ojo scan first."),
817 $c + 1, htmlspecialchars($treeInfo[
'display_name'])
820 } elseif ($mode ===
'copyright') {
821 $agentPk = $treeInfo[
'copyright_agent_pk'];
822 } elseif ($mode ===
'ecc') {
823 $agentPk = $treeInfo[
'ecc_agent_pk'];
825 $treeInfo[
'agent_pk'] = $agentPk;
826 $agentPks[$c] = $agentPk;
827 $treeInfoArray[$c] = $treeInfo;
830 if (!empty($ErrMsg)) {
831 return $this->flushContent(
"<div class='alert alert-warning'>$ErrMsg</div>");
835 foreach ($items as $c => $itemPk) {
836 $children = GetNonArtifactChildren($itemPk, $treeInfoArray[$c][
'uploadtree_tablename']);
838 $this->
AddDataStr($treeInfoArray[$c], $children, $mode);
839 $allChildren[$c] = $children;
844 FileListN($Master, $agentPks, $filter, self::NAME, $items, $mode, $baseline);
852 if ($view ===
'matrix') {
853 $tableRows = $this->
ItemComparisonRows($Master, $treeInfoArray, $mode, $baseline, $view);
854 $this->FilterN($filter, $Master, $N);
856 $this->FilterN($filter, $Master, $N);
857 $tableRows = $this->
ItemComparisonRows($Master, $treeInfoArray, $mode, $baseline, $view);
862 for ($c = 0; $c < $N; $c++) {
863 $tableName = $treeInfoArray[$c][
'uploadtree_tablename'] ??
'uploadtree';
864 $path =
Dir2Path($items[$c], $tableName);
865 $pathBanners[] =
Dir2BrowseDiffN($path, $filter, $c, self::NAME, $items, $mode, $baseline);
869 $histData = $this->
buildHistData($items, $treeInfoArray, $mode);
870 $colNames = array_map(
871 fn($ti) => htmlspecialchars($ti[
'display_name'] ??
''),
874 $modeLabel = $mode ===
'license' ? _(
"License")
875 : ($mode ===
'ecc' ? _(
"ECC") : _(
"Copyright"));
879 'none' => _(
"0. Remove nothing"),
880 'samehash' => _(
"1. Remove identical files (same hash)"),
881 'samelic' => _(
"2. Remove files with unchanged data"),
882 'samelicfuzzy' => _(
"2b. Same as 2 but fuzzy name match"),
883 'nolics' => _(
"3. Same as 2b + remove no-license files"),
884 'allsame' => _(
"4. Remove rows where all columns agree"),
886 $filterDescriptions = [
887 'none' => _(
"Show every file. Nothing is hidden."),
888 'samehash' => _(
"Hide files with identical content across all columns."),
889 'samelic' => _(
"Also hide files that share the same name and the same license/copyright data."),
890 'samelicfuzzy' => _(
"Like above, but uses fuzzy filename matching — ignores version numbers in filenames."),
891 'nolics' => _(
"Show only files where a license difference exists. Files with no license found are also hidden."),
892 'allsame' => _(
"Hide any row where every column reports identical data, regardless of filename."),
895 'license' => _(
"Licenses"),
896 'copyright' => _(
"Copyrights"),
901 'matrix' => _(
"Matrix"),
905 'pluginName' => self::NAME,
911 'baseline' => $baseline,
912 'freezeCol' => $freezeCol,
913 'frozenItem' => $frozenItem,
914 'filters' => $filters,
915 'filterDescriptions' => $filterDescriptions,
918 'treeInfoArray' => $treeInfoArray,
919 'summaryData' => $summaryData,
920 'pathBanners' => $pathBanners,
921 'tableRows' => $tableRows,
922 'histData' => $histData,
923 'colNames' => $colNames,
924 'modeLabel' => $modeLabel,
927 $response = $this->
render(
928 'multicompare.html.twig',
929 $this->mergeWithDefault($vars)
932 if (strlen($response->getContent()) > 0) {
Contains the constants and helpers for authentication of user.
render($templateName, $vars=null, $headers=null)
ChildElt(array $child, int $colIdx, array $row, array $treeInfoArray, string $mode, int $baseline)
filterSamehashN(array &$Master, int $N)
buildSummaryData(array $Master, int $N, array $treeInfoArray, string $mode)
filterSamelicN(array &$Master, int $N)
filterSamelicFuzzyN(array &$Master, int $N)
filterAllsame(array &$Master, int $N)
GetTreeInfo(int $uploadtree_pk)
filterNolicsN(array &$Master)
ItemComparisonRows(array $Master, array $treeInfoArray, string $mode, int $baseline, string $view)
batchAgentPks(int $uploadPk)
AddDataStr(array $treeInfo, array &$children, string $mode)
buildHistData(array $items, array $treeInfoArray, string $mode)
ReportCacheGet($CacheKey)
This function is used by Output() to see if the requested report is in the report cache.
ReportCachePut($CacheKey, $CacheValue)
This function is used to write a record to the report cache. If the record already exists,...
ReportCachePurgeByKey($CacheKey)
Purge from the report cache the record with $CacheKey.
FuzzyName(&$Children)
Add fuzzyname and fuzzynameext to $Children.
Dir2Path($uploadtree_pk, $uploadtree_tablename='uploadtree')
Return the path (without artifacts) of an uploadtree_pk.
FileListLinks($upload_fk, $uploadtree_pk, $napk, $pfile_pk, $Recurse=True, &$UniqueTagArray=array(), $uploadtree_tablename="uploadtree", $wantTags=true)
Get list of links: [View][Info][Download]
GetFileLicenses($agent, $pfile_pk, $uploadtree_pk, $uploadtree_tablename='uploadtree', $duplicate="")
get all the licenses for a single file or uploadtree
Dir2BrowseDiffN(array $path, string $filter, int $colIdx, string $pluginName, array $items, string $mode, int $baseline)
Render the folder/path breadcrumb banner for one column.
MakeMasterN(array $ChildrenArrays)
Build the master array for N file lists using hashmap-based O(M·N) matching.
FileListN(array &$Master, array $agentPks, string $filter, string $pluginName, array $items, string $mode, int $baseline)
Attach linkurl to every cell in Master (N-way version of FileList()).
FUNCTION int max(int permGroup, int permPublic)
Get the maximum group privilege.
#define PERM_READ
Read-only permission.
fo_dbManager * dbManager
fo_dbManager object