Skip to content

Instantly share code, notes, and snippets.

@lrealdi
Last active December 20, 2018 09:53
Show Gist options
  • Select an option

  • Save lrealdi/6add304e83b289981009f8550b00d046 to your computer and use it in GitHub Desktop.

Select an option

Save lrealdi/6add304e83b289981009f8550b00d046 to your computer and use it in GitHub Desktop.
<?php
/**
* Genarates formatted tables for CLI output
*/
class Table {
/**
* Table header, array of names
* @var array
*/
private $header = array();
/**
* Data for the table, array of arrays (rows)
* @var array of arrays
*/
private $data = array();
/**
* Maximum length of each column
* @var array if ints
*/
private $maxLength = array();
/**
* Number of columns
* @var int
*/
private $columns;
/**
* Line at the start and the end of the table
* @var string
*/
private $line;
/**
* The final table
* @var string
*/
private $table;
/**
*
* @param array $data Array of arrays or objects
* @param array $header Table header [optional]
*
* Table expects $data to be either array of objects or array of arrays. In
* case array of numerically indexed arrays is used, header array must be
* passed, because the script has no way to generate table header. $header
* can also be used for passing custom table headers.
*/
public function __construct($data, $header = null){
$this->data = $data;
$header ? $this->header = $header : $this->header = null;
$header? $this->columns = count($header) : $this->columns = null;
$this->prepareData();
$this->verifyHeader();
$this->verifyData();
$this->getLengths();
$this->generateHeader();
$this->generateBody();
}
/**
* Get the generated table
*
* @return string
*/
public function getTable(){
return $this->table;
}
//==========================================================================
// Private methods
//==========================================================================
private function prepareData(){
if(!is_array($this->data)){
throw new \Exception('Data passed must be an array');
}
if(is_object($this->data[0])){
$this->generateHeaderFromData();
$this->convertObjectToArray();
}
elseif(is_array($this->data[0])){
$this->generateHeaderFromData();
}
else{
throw new \Exception('Passed data must be array of objects or arrays');
}
}
private function convertObjectToArray(){
$temp = array();
foreach($this->data as $obj){
$arr = array();
foreach($obj as $item){
$arr[] = $item;
}
$temp[] = $arr;
}
$this->data = $temp;
}
private function generateHeaderFromData(){
//do not overwrite
if(!$this->header){
$temp = array();
foreach($this->data[0] as $key => $item){
$temp[] = $key;
}
$this->header = $temp;
$this->columns = count($temp);
}
}
private function generateHeader(){
$table = '';
//starting line
for($i=0; $i<$this->columns; $i++){
$table .= '+';
$len = $this->maxLength[$i] + 2; //ensures that the longest string has a space after it
$table .= sprintf("%'={$len}s",'');
}
$table .= '+'.PHP_EOL;
$this->line = $table; //the first and the last line of the header
//column names
for($i=0; $i<$this->columns; $i++){
$len = $this->maxLength[$i] + 1; //ensures that the longest string has a space after it
$table .= '| ';
$table .= sprintf("%' -{$len}s",$this->header[$i]);
}
$table .= '|'.PHP_EOL;
//add the ending line
$table .= $this->line;
$this->table = $table;
}
private function generateBody(){
$table = '';
foreach($this->data as $row){
$i = 0;
foreach($row as $field){
$len = $this->maxLength[$i] + 1; //ensures that the longest string has a space after it
$table .= '| '.sprintf("%' -{$len}s",$field);
$i++;
}
$table .= '|'.PHP_EOL;
for($i=0; $i<$this->columns; $i++){
$table .= '+';
$len = $this->maxLength[$i] + 2; //ensures that the longest string has a space after it
$table .= sprintf("%'-{$len}s",'');
}
$table .= '|'.PHP_EOL;
}
$this->table .= $table;
//$this->table .= $this->line;
}
/**
* Find maximum lengths for each column
*/
private function getLengths(){
for($i=0; $i<$this->columns; $i++){
$this->maxLength[$i] = 0;
//headers
foreach($this->header as $field){
//set initial max lengths to the length of each header cell
if(strlen($field) > $this->maxLength[$i]){
$this->maxLength[$i] = strlen($field);
}
}
}
//data
foreach($this->data as $row){
//test each field in each row
$i=0;
foreach($row as $field){
if(strlen($field) > $this->maxLength[$i]){
$this->maxLength[$i] = strlen($field);
}
$i++;
}
}
}
/**
* Checks that table header is an array
*/
private function verifyHeader(){
if(!is_array($this->header)){
throw new \Exception('Table header must be an array');
}
}
/**
* Verifies that data passed is an array and that it matches the array
* passed to header
*/
private function verifyData(){
if(!is_array($this->data)){
throw new \Exception('Data passed must be an array');
}
if(!is_array($this->data[0])){
throw new \Exception('Data must be an array of arrays');
}
if(count($this->data[0]) != $this->columns){
throw new \Exception('Array length mismatch between table header and the data');
}
}
}
$arguments = $GLOBALS['argv'];
$program = $arguments[0];
array_shift( $arguments );
$showAll = false;
if ($arguments[0] == '--show-all'){
$showAll = true;
array_shift( $arguments );
}
function loadJson($file)
{
$jsonData = file_get_contents($file);
$data = json_decode($jsonData, 1);
return $data;
}
function findRepositoryUrl($repository)
{
if ($repository['type'] == 'vcs'){
return $repository['url'];
}
if ($repository['type'] == 'package'){
return $repository['package']['dist']['url'];
}
return '?';
}
$mergeRequire = array();
$mergeRepositories = array();
foreach ($arguments as $file) {
$data = loadJson($file);
$require = $data["require"];
ksort($require);
foreach ($require as $package => $version) {
if (!isset($mergeRequire[$package])){
$mergeRequire[$package] = array();
}
$mergeRequire[$package][$file] = $version;
}
$repositories = $data["repositories"];
foreach ($repositories as $repository) {
$repositoryUrl = findRepositoryUrl($repository);
if (!isset($mergeRepositories[$repositoryUrl])){
$mergeRepositories[$repositoryUrl] = array();
}
$mergeRepositories[$repositoryUrl][$file] = $repositoryUrl;
}
}
ksort($mergeRequire);
$tableDataRequire = array();
foreach ($mergeRequire as $package => $item) {
$tableRow = array(
'package' => $package
);
foreach ($arguments as $argument) {
if (isset($item[$argument])){
$tableRow[$argument] = $item[$argument];
}else{
$tableRow[$argument] = '';
}
}
$isChanged = count(array_values($item)) != count($arguments);
if (count($item) > 1 && count(array_unique(array_values($item))) != 1 ){
$isChanged = true;
}
if ($isChanged || $showAll){
$tableDataRequire[] = $tableRow;
}
}
ksort($mergeRepositories);
$tableDataRepositories = array();
foreach ($mergeRepositories as $repository => $item) {
$tableRow = array();
foreach ($arguments as $argument) {
if (isset($item[$argument])){
$tableRow[$argument] = $item[$argument];
}else{
$tableRow[$argument] = '';
}
}
$isChanged = count(array_values($item)) != count($arguments);
if (count($item) > 1 && count(array_unique(array_values($item))) != 1 ){
$isChanged = true;
}
if ($isChanged || $showAll){
$tableDataRepositories[] = $tableRow;
}
}
echo "Diff in require \n";
$table = new Table($tableDataRequire);
echo $table->getTable();
echo "\nDiff in repositories \n";
$table = new Table($tableDataRepositories);
echo $table->getTable();
@lrealdi
Copy link
Author

lrealdi commented Dec 20, 2018

Esempio:
php diff-composer.php ~/old_composer.json ~/new_composer.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment