<?php /** * COmanage Match Matchgrid Reconcile Template * * Portions licensed to the University Corporation for Advanced Internet * Development, Inc. ("UCAID") under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * UCAID licenses this file to you under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @link http://www.internet2.edu/comanage COmanage Project * @package match * @since COmanage Match v1.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ declare(strict_types = 1); use \App\Lib\Util\ArrayUtil; // Ensure that the candidates array is sorted by referenceid so we can easily match up identical adjacent referenceids. // Note that this will retain the "New" record in first position (because the referenceid is empty). array_multisort(array_column($vv_candidates, 'referenceid'), SORT_ASC, $vv_candidates); // Generate the referenceid label output by creating a simple array that contains the unique referenceid values // along with the count of how many occurrences each has in the $vv_candidates structure (for colspan). // Note that we must assign an empty string when encountering a NULL referenceid because array_count_values // can only work on integers or strings. $refIds = array(); foreach ($vv_candidates as $candidate) { $refIds[] = !empty($candidate['referenceid']) ? $candidate['referenceid'] : ''; } $refIds = array_count_values($refIds); // Extract the attribute field names into a simple array. $fieldNames = array(); foreach ($vv_candidates as $candidate) { $fieldNames = array_keys($candidate); break; } // Remove "referenceid" from the field names - it is given special treatment and should not be included in our // attributes structure. array_splice($fieldNames, array_search('referenceid',$fieldNames), 1); // Build the data for the candidates into a structure for generating the view: // String: attribute field name | Array of arrays: [attribute value, candidate id, different?1:0] $canAttr = array(); for($i = 0; $i < count($fieldNames); $i++) { // Put the field name in the first column. $canAttr[$i][0] = $fieldNames[$i]; // Put all the values for the current attribute into the second column. $canAttr[$i][1] = array(); foreach($vv_candidates as $c) { foreach($c as $key => $val) { if($key == $fieldNames[$i]) { $id = $c['id']; $diff = (isset($vv_candidate_diff[$id]) && in_array($key,$vv_candidate_diff[$id])) ? 1 : 0; $canAttr[$i][1][] = [$val, $id, $diff]; } } } } // Move request_time and resolution_time to the bottom $tempArr = []; foreach ($canAttr as $key => $val) { if($val[0] == 'request_time' || $val[0] == 'resolution_time') { $tempArr[] = $val; unset($canAttr[$key]); } } $canAttr = array_merge($canAttr, $tempArr); // $flashArgs pass banner messages to the flash element container $flashArgs = []; if(!empty($indexBanners)) { $flashArgs['vv_index_banners'] = $indexBanners; } if(!empty($banners)) { $flashArgs['vv_banners'] = $banners; } ?> <div class="pageTitleContainer"> <div class="pageTitle"> <h1><?= __('match.op.reconcile.requests'); ?></h1> </div> </div> <?= $this->element('flash', $flashArgs); ?> <div class="view-controls"> <span class="view-controls-title"><?= __('match.op.highlight'); ?></span> <div class="form-check form-check-inline"> <input id="view-mode-diff" class="form-check-input" name="view-mode" type="radio" checked> <label for="view-mode-diff" class="form-check-label"><?= __('match.op.highlight.differences'); ?></label> </div> <div class="form-check form-check-inline"> <input id="view-mode-match" class="form-check-input" name="view-mode" type="radio"> <label for="view-mode-match" class="form-check-label"><?= __('match.op.highlight.matches'); ?></label> </div> <div class="form-check form-check-inline"> <input id="view-mode-both" class="form-check-input" name="view-mode" type="radio"> <label for="view-mode-both" class="form-check-label"><?= __('match.op.highlight.both'); ?></label> </div> </div> <div id="reconcile-table-container" class="table-container"> <table id="reconcile-table" class="side-by-side view-mode-diff"> <thead> <tr> <td class="empty"></td> <?php $i = 0; // used to print the suggestion number in the output. ?> <?php foreach($refIds as $refId => $refIdCount): ?> <th class="col-names" scope="col" colspan="<?= $refIdCount; ?>"> <?= !empty($refId) ? __('match.fd.suggestion.a',[$i]) : __('match.fd.new_record'); ?> <?php $i++; ?> </th> <?php endforeach; ?> </tr> </thead> <tbody> <!-- Reference IDs --> <tr> <th class="attr-title" scope="row"> <?= __('match.fd.referenceid', [99]); ?> </th> <?php foreach($refIds as $refId => $refIdCount): ?> <td class="reference-ids" colspan="<?= $refIdCount; ?>"> <?= !empty($refId) ? $refId : __('match.op.new'); ?> </td> <?php endforeach; ?> </tr> <!-- Actions --> <tr> <th class="attr-title" scope="row"> <?= __('match.fd.action'); ?> </th> <?php foreach($refIds as $refId => $refIdCount): ?> <td class="reconcile-actions" colspan="<?= $refIdCount; ?>"> <?= $this->Form->postLink(__('match.op.reconcile.' . (!empty($refId) ? 'assign' : 'generate')), ['action' => 'reconcile', $vv_cur_mg->id], ['data' => [ 'rowid' => $vv_request['id'], // Default value needs to be the literal string "new" and not a localized text string 'referenceid' => (!empty($refId) ? $refId : 'new') ], 'confirm' => __('match.op.assign.confirm'), 'class' => 'btn btn-primary nospin']); ?> </td> <?php endforeach; ?> </tr> <!-- All other attributes --> <?php for($i = 0; $i < count($canAttr); $i++): ?> <?php $atr = $canAttr[$i][0]; $definedAttr = false; // Set the row css class: 'matr-'+attribute-name plus 'standard' or 'defined-attr'. $matchClass = 'matr-' . $atr; if( $atr == 'id' || $atr == 'sor' || $atr == 'sorid' || $atr == 'request_time' || $atr == 'resolution_time' ) { $matchClass .= ' standard'; } else { $definedAttr = true; $matchClass .= ' defined-attr'; } ?> <tr class="<?= $matchClass ?>"> <th class="attr-title" scope="row"><?= $canAttr[$i][0] ?></th> <?php foreach($canAttr[$i][1] as $key => $val): ?> <?php // Set the cell css class: standard, new, diff, or match // Only defined attributes are given the diff or match classes used for highlighting. // The others are marked as "standard" and the new record is marked as "new". $matchClass = 'standard'; if($key == 0) { // The first column is our potentially new record $matchClass = 'new'; } elseif($definedAttr) { $matchClass = ($val[2] ? 'diff' : 'match'); } ?> <td class="<?= $matchClass ?>"> <?php if($atr == 'id'): ?> <?= $this->Html->link( $val[0], ['controller' => 'matchgrid-records', 'action' => 'edit', $val[0], '?' => ['matchgrid_id' => $vv_cur_mg->id]]); ?> <?php else: ?> <?= $val[0]; ?> <?php endif; ?> </td> <?php endforeach; ?> </tr> <?php endfor; ?> </tbody> </table> </div> <script> function js_local_onload() { // Handle display-mode switching $('.view-controls input').click(function () { // Remove existing view-mode classes and add the new class equal to the view-controls switch ID $('#reconcile-table').removeClass('view-mode-diff view-mode-match view-mode-both').addClass($(this).attr('id')); }); } </script>