summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Utils/Csv.php
blob: 3a3c03094941b45f6a41f49e31b59869c5bbb743 (plain)
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;
	}

}