$record) { if (is_object($record)) { $result[$key] = $record->{$prop}; } else { $result[$key] = $record[$prop]; } } } return $result; } function index($keys, $records) { $final_key = array_pop($keys); $result = array(); foreach ($records as $record) { $node = &$result; foreach ($keys as $key) { if (is_array($record)) { $keyvalue = isset($record[$key]) ? $record[$key] : NULL; } else { $keyvalue = isset($record->{$key}) ? $record->{$key} : NULL; } if (isset($node[$keyvalue]) && !is_array($node[$keyvalue])) { $node[$keyvalue] = array(); } $node = &$node[$keyvalue]; } if (is_array($record)) { $node[$record[$final_key]] = $record; } else { $node[$record->{$final_key}] = $record; } } return $result; } function save_csv($file, $rows) { if ($fh = fopen($file, 'w')) { $header = array('File', 'Line', 'Column', 'Type', 'Message', 'Source', 'Severity', 'Fixable'); fputcsv($fh, $header); foreach ($rows as $row) { fputcsv($fh, $row['raw']); } fclose($fh); } else { throw new Exception("Failed to open $file"); } } /** * @param string $file * @return array */ function read_csv($file) { if ($fh = fopen($file, 'r')) { $recs = array(); $csvRowNum = 0; while ($row = fgetcsv($fh)) { if (count($row) < 6) { var_dump(array('Incomplete row', $csvRowNum, $row)); continue; } if ($row[0] == 'File') { continue; } $rec = array(); $rec['raw'] = $row; $rec['id'] = count($recs); list ($rec['file'], $rec['lineNo'], $rec['charNo'], $rec['category'], $rec['msg'], $rec['name']) = $row; $recs[] = $rec; } fclose($fh); return $recs; } else { throw new Exception("Failed to read "); } } /** * @param array $allRecs * @return array */ function createBatchesByFile($allRecs, $batchSize) { $recs = index(array('file', 'id'), $allRecs); uasort($recs, function ($a, $b) { return count($a) - count($b); }); $recs = array_reverse($recs); $batches = array( 0 => array(), 1 => array(), 2 => array(), 3 => array(), 4 => array(), 5 => array(), 6 => array(), 7 => array(), 8 => array(), 9 => array(), 10 => array(), 11 => array(), 12 => array(), 13 => array(), 14 => array(), 15 => array(), 16 => array(), 17 => array(), 18 => array(), 19 => array(), 20 => array(), ); $sucksToBeYou = 0; foreach ($recs as $rec) { $placed = FALSE; foreach (array_keys($batches) as $batchId) { if (!$placed && count($batches[$batchId]) + count($rec) < $batchSize) { $batches[$batchId] = array_merge($batches[$batchId], $rec); $placed = TRUE; } } if (!$placed) { $batches[$sucksToBeYou] = array_merge($batches[$sucksToBeYou], $rec); $sucksToBeYou = ($sucksToBeYou + 1) % count($batches); $placed = TRUE; } } return $batches; } function createBatchesGroupedByType($recs, $batchSize) { $recs = index(array('name', 'id'), $recs); $doAgain = TRUE; while ($doAgain) { $doAgain = FALSE; foreach (array_keys($recs) as $i) { if (count($recs[$i]) > $batchSize) { $first = array_slice($recs[$i], 0, $batchSize); $second = array_slice($recs[$i], $batchSize); $recs[$i] = $first; $recs[] = $second; $doAgain = TRUE; } } } uasort($recs, function ($a, $b) { return count($a) - count($b); }); $recs = array_reverse($recs); $batches = array(); foreach ($recs as $matchingRecs) { $placed = FALSE; foreach (array_keys($batches) as $batchId) { if (!$placed && count($batches[$batchId]) + count($matchingRecs) <= $batchSize) { $batches[$batchId] = array_merge($batches[$batchId], $matchingRecs); $placed = TRUE; } } if (!$placed) { $batches[] = $matchingRecs; } } return $batches; } /** * @param string $message * @return string */ function bash_echo($message) { return "echo " . escapeshellarg($message) . "\n"; } function write_bash($file, $allRecs) { $allByName = index(array('name', 'id'), $allRecs); //uasort($allByName, function ($a, $b) { // return count($a) - count($b); //}); $buf = "#!/bin/bash\n"; $buf .= "## usage: bash $file vi\n"; $buf .= "## usage: bash $file joe\n"; $buf .= ' [ -n "$1" ] && EDITOR="$1" if [ -z "$EDITOR" ]; then echo "Please provide parameter 1 (editor). Example: vi, joe" exit 1 fi function edit_at_line() { local f="$1" local l="$2" $EDITOR +$l "$f" } function ask_continue() { local line="" while [ "$line" != "y" -a "$line" != "n" ]; do echo -n "$1 (Y/n) " read line if [ -z "$line" ]; then line=y fi done if [ "$line" == "y" ]; then return 0 else return 1 fi } '; $buf .= bash_echo('Welcome and thanks for helping with the cleanup!'); $buf .= bash_echo(''); $buf .= bash_echo('This script will walk through a series of code-style issues in Civi\'s PHP code.'); $buf .= bash_echo('For each issue, it will show a summary of the issue (ie how many files are'); $buf .= bash_echo('affected, how many lines of code are affected, and what detailed messages'); $buf .= bash_echo('are available about the issues.'); $buf .= bash_echo(''); $buf .= bash_echo('The script will open the first file at the offending line so that you can fix'); $buf .= bash_echo('it. Please save, edit, close. The script will then repeat -- re-opening the text'); $buf .= bash_echo('editor at each offending line.'); $buf .= bash_echo(''); $buf .= "ask_continue 'Continue?' || exit\n"; foreach ($allByName as $name => $recsPerName) { $buf .= bash_echo("==============================================================="); $buf .= bash_echo("Formatting issue: $name"); $buf .= bash_echo("Files:" . print_r( array_values(array_unique(collect('file', $recsPerName))), TRUE )); $buf .= bash_echo("Messages:" . print_r( array_values(array_unique(collect('msg', $recsPerName))), TRUE )); $buf .= bash_echo(""); $buf .= bash_echo("Total number of edits to perform: " . count($recsPerName)); $buf .= "if ask_continue 'Edit these files?'; then\n"; foreach ($recsPerName as $rec) { $edFile = preg_replace(':^.*modules/civicrm/:', '', $rec['file']); $buf .= sprintf("edit_at_line %s %s\n", escapeshellarg($edFile), $rec['lineNo']); } $buf .= "fi\n"; $buf .= bash_echo("Completed formatting issue $name!"); } file_put_contents($file, $buf); } $allRecs = read_csv($argv[1]); $batches = createBatchesByFile($allRecs, 170); foreach ($batches as $batchId => $recs) { printf("Batch %d has %d records\n", $batchId, count($recs)); save_csv("batch-$batchId.csv", $recs); write_bash("batch-$batchId.sh.txt", $recs); //$subBatches = createBatchesGroupedByType($recs, 185); //foreach ($subBatches as $subBatchId => $subBatch) { // save_csv("batch-$batchId-$subBatchId.csv", $subBatch); //} }