1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
<?php
namespace SMW\Utils;
/**
* @license GNU GPL v2+
* @since 3.0
*
* @author mwjames
*/
class Csv {
const DEFAULT_SEP = ',';
/**
* @var boolean
*/
private $show = false;
/**
* @var boolean
*/
private $bom = false;
/**
* @since 3.0
*
* @param boolean $show
* @param boolean $bom
*/
public function __construct( $show = false, $bom = false ) {
$this->show = $show;
$this->bom = $bom;
}
/**
* @since 3.0
*
* @param array $header
* @param array $rows
* @param string $sep
*
* @return string
*/
public function toString( array $header, array $rows, $sep = self::DEFAULT_SEP ) {
$handle = fopen( 'php://temp', 'r+' );
// fputcsv(): delimiter must be a single character
$sep = $sep !== '' ? $sep{0} : self::DEFAULT_SEP;
// https://en.wikipedia.org/wiki/Comma-separated_values#Standardization
// http://php.net/manual/en/function.fputcsv.php
if ( $this->bom ) {
fputs( $handle, ( chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) ) );
}
// https://en.wikipedia.org/wiki/Comma-separated_values#Application_support
if ( $this->show ) {
fputs( $handle, "sep=" . $sep . "\n" );
}
if ( $header !== [] ) {
fputcsv( $handle, $header, $sep );
}
foreach ( $rows as $row ) {
fputcsv( $handle, $row, $sep );
}
rewind( $handle );
return stream_get_contents( $handle );
}
/**
* Merge row and column values where the subject (first column) uses the same
* identifier.
*
* @since 3.0
*
* @param array $rows
* @param string $sep
*
* @return array
*/
public function merge( $rows, $sep = ',' ) {
$map = [];
$order = [];
foreach ( $rows as $key => $row ) {
// First column is used to build the hash index to find rows with
// the same hash
$hash = md5( $row[0] );
// Retain the order
if ( !isset( $order[$hash] ) ) {
$order[$hash] = $key;
}
if ( !isset( $map[$hash] ) ) {
$map[$hash] = $row;
} else {
$concat = [];
foreach ( $map[$hash] as $k => $v ) {
// Index 0 represents the first column, same hash, only
// concatenate the rest of the columns
if ( $k != 0 ) {
$v = $v . ( isset( $row[$k] ) ? "$sep" . $row[$k] : '' );
// Filter duplicate values
$v = array_flip( explode( $sep, $v ) );
// Make it a simple list
$v = implode( $sep, array_keys( $v ) );
}
$concat[$k] = $v;
}
$map[$hash] = $concat;
}
}
$order = array_flip( $order );
foreach ( $order as $key => $hash ) {
$order[$key] = $map[$hash];
}
return $order;
}
}
|