Multiline   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 8
Bugs 1 Features 2
Metric Value
wmc 16
c 8
b 1
f 2
lcom 1
cbo 3
dl 0
loc 152
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 11 1
A __toString() 0 3 1
A getEol() 0 3 1
A getMaxLength() 0 7 2
A setEol() 0 7 2
A append() 0 7 2
A prefix() 0 6 1
A pad() 0 9 2
A getLineIndexByCharacterPosition() 0 11 4
1
<?php
2
namespace nochso\Omni;
3
4
/**
5
 * Multiline string class for working with lines of text.
6
 */
7
final class Multiline extends ArrayCollection {
8
	/**
9
	 * @var \nochso\Omni\EOL
10
	 */
11
	private $eol;
12
13
	/**
14
	 * Create a new Multiline object from a string.
15
	 *
16
	 * First the input string is split into lines by the detected end-of-line
17
	 * character. Afterwards any extra EOL chars will be trimmed.
18
	 *
19
	 * @see \nochso\Omni\EOL
20
	 *
21
	 * @param string $input      A string to split into a Multiline object
22
	 * @param string $defaultEol Default end-of-line type to split the input by. This is a fallback in case it could
23
	 *                           not be detected from the input string. Optional, defaults to `EOL::EOL_LF` i.e. "\n".
24
	 *                           See the `EOL::EOL_*` class constants.
25
	 *
26
	 * @return \nochso\Omni\Multiline
27
	 */
28
	public static function create($input, $defaultEol = \nochso\Omni\EOL::EOL_LF) {
29
		$eol = EOL::detectDefault($input, $defaultEol);
30
		$lines = explode($eol, $input);
31
		$multiline = new self($lines);
32
		// Remove left-over line feeds
33
		$multiline->apply(function ($line) {
34
				return trim($line, "\r\n");
35
			});
36
		$multiline->setEol($eol);
37
		return $multiline;
38
	}
39
40
	/**
41
	 * __toString returns a single string using the current EOL style.
42
	 *
43
	 * @return string
44
	 */
45
	public function __toString() {
46
		return implode((string) $this->eol, $this->list);
47
	}
48
49
	/**
50
	 * Get EOL style ending.
51
	 *
52
	 * @return \nochso\Omni\EOL
53
	 */
54
	public function getEol() {
55
		return $this->eol;
56
	}
57
58
	/**
59
	 * getMaxLength of all lines.
60
	 *
61
	 * @return int
62
	 */
63
	public function getMaxLength() {
64
		$length = 0;
65
		foreach ($this->list as $line) {
66
			$length = max($length, mb_strlen($line));
67
		}
68
		return $length;
69
	}
70
71
	/**
72
	 * Set EOL used by this Multiline string.
73
	 *
74
	 * @param \nochso\Omni\EOL|string $eol Either an `EOL` object or a string ("\r\n" or "\n")
75
	 *
76
	 * @return $this
77
	 */
78
	public function setEol($eol) {
79
		if (!$eol instanceof EOL) {
80
			$eol = new EOL($eol);
81
		}
82
		$this->eol = $eol;
83
		return $this;
84
	}
85
86
	/**
87
	 * Append text to a certain line.
88
	 *
89
	 * @param string   $text
90
	 * @param null|int $index Optional, defaults to the last line. Other
91
	 *
92
	 * @return $this
93
	 */
94
	public function append($text, $index = null) {
95
		if ($index === null) {
96
			$index = count($this) - 1;
97
		}
98
		$this->list[$index] .= $text;
99
		return $this;
100
	}
101
102
	/**
103
	 * Prefix all lines with a string.
104
	 *
105
	 * @param string $prefix The prefix to add to the start of the string.
106
	 *
107
	 * @return string
108
	 */
109
	public function prefix($prefix) {
110
		$prefixer = function ($line) use ($prefix) {
111
			return $prefix . $line;
112
		};
113
		return $this->apply($prefixer);
114
	}
115
116
	/**
117
	 * Pad all lines to the same length using `str_pad`.
118
	 *
119
	 * @param int    $length      If length is larger than the maximum line length, all lines will be padded up to the
120
	 *                            given length. If length is null, the maximum of all line lengths is used. Optional,
121
	 *                            defaults to null.
122
	 * @param string $padding     Optional, defaults to a space character. Can be more than one character. The padding
123
	 *                            may be truncated if the required number of padding characters can't be evenly
124
	 *                            divided.
125
	 * @param int    $paddingType Optional argument pad_type can be STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH.
126
	 *                            Defaults to STR_PAD_RIGHT.
127
	 *
128
	 * @return string
129
	 */
130
	public function pad($length = null, $padding = ' ', $paddingType = STR_PAD_RIGHT) {
131
		if ($length === null) {
132
			$length = $this->getMaxLength();
133
		}
134
		$padder = function ($line) use ($length, $padding, $paddingType) {
135
			return Strings::padMultibyte($line, $length, $padding, $paddingType);
136
		};
137
		return $this->apply($padder);
138
	}
139
140
	/**
141
	 * getLineIndexByCharacterPosition returns the line index containing a certain position.
142
	 *
143
	 * @param int $characterPosition Position of a character as if Multiline was a raw string.
144
	 *
145
	 * @return int|null The array index of the line containing the character position.
146
	 */
147
	public function getLineIndexByCharacterPosition($characterPosition) {
148
		$position = 0;
149
		foreach ($this->list as $key => $line) {
150
			$length = mb_strlen($line . $this->getEol());
151
			if ($characterPosition >= $position && $characterPosition <= $position + $length) {
152
				return $key;
153
			}
154
			$position += $length;
155
		}
156
		return null;
157
	}
158
}
159