├── .github
└── workflows
│ └── tests.yml
├── .gitignore
├── .php-cs-fixer.php
├── README.md
├── composer.json
├── docs
├── _config.yml
└── index.md
├── img.png
├── phpunit.xml
├── src
├── ArrayToTextTable.php
├── ArrayToTextTableException.php
└── formatters
│ ├── AlignFormatter.php
│ ├── BaseColumnFormatter.php
│ ├── ColorFormatter.php
│ └── SprintfFormatter.php
├── test.php
└── tests
├── AlignFormatterTest.php
├── ColorTest.php
├── CombinedAlignSprintfFormatterTest.php
└── SimpleTest.php
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: tests
2 |
3 | on:
4 | push:
5 | paths:
6 | - 'src/**'
7 |
8 | env:
9 | COMPOSER_ROOT_VERSION: 1.99
10 |
11 | jobs:
12 | tests:
13 | runs-on: ubuntu-latest
14 |
15 | strategy:
16 | matrix:
17 | php-version: [5.6, 8.2]
18 |
19 | dependencies:
20 | - "highest"
21 |
22 | name: P${{ matrix.php-version }} - ${{ matrix.dependencies }}
23 |
24 | steps:
25 | - name: Checkout project
26 | uses: actions/checkout@v3
27 |
28 | - name: Install PHP
29 | uses: shivammathur/setup-php@2.24.0
30 | with:
31 | php-version: "${{ matrix.php-version }}"
32 | extensions: xdebug
33 | ini-values: zend.assertions=1
34 |
35 | - name: Get composer cache directory
36 | id: composercache
37 | run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
38 |
39 | - name: Cache dependencies
40 | uses: actions/cache@v3
41 | with:
42 | path: ${{ steps.composercache.outputs.dir }}
43 | key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.json') }}
44 | restore-keys: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-
45 |
46 | - name: Install lowest dependencies
47 | if: ${{ matrix.dependencies == 'lowest' }}
48 | run: composer update --no-interaction --no-progress --prefer-lowest
49 |
50 | - name: Install highest dependencies
51 | if: ${{ matrix.dependencies == 'highest' }}
52 | run: composer update --no-interaction --no-progress
53 |
54 | - name: Run tests
55 | timeout-minutes: 3
56 | run: vendor/bin/phpunit --coverage-clover clover.xml
57 |
58 | - name: Get lines of code (more sophisticated)
59 | id: scc
60 | uses: iryanbell/scc-docker-action@v1.0.2
61 | with:
62 | args: ${{ env.workspace }} -i php --exclude-dir vendor --format json src
63 |
64 | - name: Make lines of code badge
65 | uses: emibcn/badge-action@v2.0.2
66 | with:
67 | label: Lines of Code
68 | status: ${{ fromJson(steps.scc.outputs.scc)[0].Code }}
69 | color: 'blue'
70 | path: .github/lines.svg
71 |
72 | - name: Make code coverage badge
73 | uses: timkrase/phpunit-coverage-badge@v1.2.1
74 | with:
75 | coverage_badge_path: .github/coverage.svg
76 | # push badge later on
77 | push_badge: false
78 |
79 | - name: Git push badges to image-data branch
80 | uses: peaceiris/actions-gh-pages@v3
81 | with:
82 | publish_dir: .github
83 | publish_branch: image-data
84 | github_token: ${{ secrets.GITHUB_TOKEN }}
85 | user_name: 'github-actions[bot]'
86 | user_email: 'github-actions[bot]@users.noreply.github.com'
87 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | phpunit.phar
3 | phpunit
4 | .phpunit.result.cache
5 | coverage/
6 | .idea
7 | vendor
8 | .php-cs-fixer.cache
9 |
--------------------------------------------------------------------------------
/.php-cs-fixer.php:
--------------------------------------------------------------------------------
1 | exclude('vendor/')
5 | ->in('.');
6 |
7 | $fixer = (new PhpCsFixer\Config('', ''))
8 | ->setRules([
9 | '@PhpCsFixer' => true,
10 | 'concat_space' => [
11 | 'spacing' => 'one',
12 | ],
13 | 'global_namespace_import' => [
14 | 'import_classes' => false,
15 | 'import_constants' => false,
16 | 'import_functions' => true,
17 | ],
18 | 'no_superfluous_phpdoc_tags' => false,
19 | 'phpdoc_add_missing_param_annotation' => true,
20 | 'phpdoc_no_empty_return' => false,
21 | 'phpdoc_summary' => false,
22 | 'phpdoc_trim' => true,
23 | 'phpdoc_trim_consecutive_blank_line_separation' => true,
24 | 'yoda_style' => false,
25 | ])
26 | ->setFinder($finder);
27 |
28 | if (isset($GLOBALS['argv']) && in_array('--allow-risky=yes', $GLOBALS['argv'], true)) {
29 | echo 'Risky rules enabled' . PHP_EOL;
30 |
31 | $fixer
32 | ->setRules([
33 | '@PhpCsFixer:risky' => true,
34 | ]);
35 | }
36 |
37 | return $fixer;
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP Array To Text Table
2 |
3 | [](https://packagist.org/packages/dekor/php-array-table)
4 | [](https://packagist.org/packages/dekor/php-array-table)
5 | [](https://packagist.org/packages/dekor/php-array-table)
6 | [](https://packagist.org/packages/dekor/php-array-table)
7 | [](https://github.com/deniskoronets/php-array-table/actions/workflows/tests.yml)
8 | 
9 | 
10 |
11 | PHP-class, which allows to transform php associative arrays to cool ASCII tables.
12 |
13 |  [Ukraine ❤](https://woo.zp.ua/en/support-ukraine/)
14 |
15 | # Quick doc:
16 | https://deniskoronets.github.io/php-array-table/
17 |
18 | ## Installation
19 | Simply run composer require:
20 |
composer require dekor/php-array-table
21 |
22 | or add to composer.json:
23 | "dekor/php-array-table": "^2.0"
24 |
25 | ## Usage
26 |
27 | ```php
28 | use dekor\ArrayToTextTable;
29 |
30 | $data = [
31 | [
32 | 'id' => 1,
33 | 'name' => 'Denis Koronets',
34 | 'role' => 'php developer',
35 | ],
36 | [
37 | 'id' => 2,
38 | 'name' => 'Maxim Ambroskin',
39 | 'role' => 'java developer',
40 | ],
41 | [
42 | 'id' => 3,
43 | 'name' => 'Andrew Sikorsky',
44 | 'role' => 'php developer',
45 | ]
46 | ];
47 |
48 | echo (new ArrayToTextTable($data))->render();
49 | ```
50 |
51 | Will draw the next output:
52 |
53 |
54 | +----+-----------------+----------------+
55 | | id | name | role |
56 | +----+-----------------+----------------+
57 | | 1 | Denis Koronets | php developer |
58 | | 2 | Maxim Ambroskin | java developer |
59 | | 3 | Andrew Sikorsky | php developer |
60 | +----+-----------------+----------------+
61 |
62 |
63 | ## Formatters (since v2)
64 |
65 | Version 2 introduces a new feature that allows to pre and postprocess column data by applying filters.
66 |
67 | You're able to develop your own formatters by extending `BaseColumnFormatter` and implementing abstract methods.
68 |
69 | List of formatters out of the box:
70 | - `AlignFormatter` - allows to set text align for inner column (useful for numbers):
71 |
72 | ```php
73 | use dekor\ArrayToTextTable;
74 | use dekor\formatters\AlignFormatter;
75 |
76 | $data = [
77 | [
78 | 'left' => 2,
79 | 'center' => 'Dummy one',
80 | 'right' => 14.33,
81 | ],
82 | [
83 | 'left' => 3,
84 | 'center' => 'Another great day for a great inventers!',
85 | 'right' => 1,
86 | ],
87 | ];
88 |
89 | $builder = new ArrayToTextTable($data);
90 | $builder->applyFormatter(new AlignFormatter(['center' => 'center', 'right' => 'right']));
91 |
92 | echo $builder->render();
93 | ```
94 |
95 | outputs:
96 |
97 | +------+------------------------------------------+-------+
98 | | left | center | right |
99 | +------+------------------------------------------+-------+
100 | | 2 | Dummy one | 14.33 |
101 | | 3 | Another great day for a great inventers! | 1 |
102 | +------+------------------------------------------+-------+
103 |
104 |
105 | - `SprintfFormatter` - allows to format column value before rendering using sprintf function (ex: %01.3f)
106 | ```php
107 | use dekor\ArrayToTextTable;
108 | use dekor\formatters\SprintfFormatter;
109 |
110 | $data = [
111 | [
112 | 'left' => 1,
113 | 'right' => 2.89,
114 | ]
115 | ];
116 |
117 | $builder = new ArrayToTextTable($data);
118 | $builder->applyFormatter(new SprintfFormatter(['left' => '%01.3f', 'right' => '%03.3f']));
119 |
120 | echo $builder->render();
121 | ```
122 |
123 | outputs:
124 |
125 | +-------+-------+
126 | | left | right |
127 | +-------+-------+
128 | | 1.000 | 2.890 |
129 | +-------+-------+
130 |
131 |
132 | - `ColorFormatter` - allows to highlight text with specific color (only works in terminal):
133 | ```php
134 | use dekor\ArrayToTextTable;
135 | use dekor\formatters\ColorFormatter;
136 |
137 | $data = [
138 | ['test' => 1],
139 | ['test' => -1],
140 | ];
141 |
142 | $builder = new ArrayToTextTable($data);
143 | $builder->applyFormatter(new ColorFormatter(['test' => fn ($value) => $value > 0 ? 'Red' : 'Green']));
144 |
145 | echo $builder->render() . PHP_EOL;
146 | ```
147 |
148 | outputs:
149 |
150 | 
151 |
152 | Allowed colors list (see `ColorFormatter::$colors`)
153 | - Black
154 | - Dark Grey
155 | - Red
156 | - Light Red
157 | - Green
158 | - Light Green
159 | - Brown
160 | - Yellow
161 | - Blue
162 | - Light Blue
163 | - Magenta
164 | - Light Magenta
165 | - Cyan
166 | - Light Cyan
167 | - Light Grey
168 | - White
169 |
170 | ## Our sponsors list:
171 |
172 |
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dekor/php-array-table",
3 | "description": "PHP Library for printing associative arrays as text table (similar to mysql terminal console)",
4 | "keywords": [
5 | "php",
6 | "library"
7 | ],
8 | "license": "BSD-3-Clause",
9 | "authors": [
10 | {
11 | "name": "Denis Koronets",
12 | "email": "deniskoronets@woo.zp.ua",
13 | "homepage": "https://woo.zp.ua/"
14 | }
15 | ],
16 | "require": {
17 | "php": ">=5.6.0",
18 | "ext-mbstring": "*"
19 | },
20 | "require-dev": {
21 | "phpunit/phpunit": "^5|^6|^7|^8|^9|^10",
22 | "friendsofphp/php-cs-fixer": "^2|^3"
23 | },
24 | "autoload": {
25 | "psr-4" : {
26 | "dekor\\" : "src"
27 | }
28 | },
29 | "scripts": {
30 | "test": "phpunit --coverage-html=coverage",
31 | "fix": "php-cs-fixer fix --verbose",
32 | "fix-risky": "php-cs-fixer fix --allow-risky=yes --verbose"
33 | }
34 | }
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
2 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # PHP Array To Text Table
2 | PHP-class, which allows to transform php associative arrays to cool ASCII tables.
3 |
4 |  [Ukraine ❤](https://woo.zp.ua/en/support-ukraine/)
5 |
6 | ## Installation
7 | Simply run composer require:
8 | composer require dekor/php-array-table
9 |
10 | or add to composer.json:
11 | "dekor/php-array-table": "^2.0"
12 |
13 | or try out using it in a sandbox:
14 | https://play.phpsandbox.io/dekor/php-array-table/6WdN1pkx8NK43yOV
15 |
16 | ## Usage
17 |
18 | ```php
19 | use dekor\ArrayToTextTable;
20 |
21 | $data = [
22 | [
23 | 'id' => 1,
24 | 'name' => 'Denis Koronets',
25 | 'role' => 'php developer',
26 | ],
27 | [
28 | 'id' => 2,
29 | 'name' => 'Maxim Ambroskin',
30 | 'role' => 'java developer',
31 | ],
32 | [
33 | 'id' => 3,
34 | 'name' => 'Andrew Sikorsky',
35 | 'role' => 'php developer',
36 | ]
37 | ];
38 |
39 | echo (new ArrayToTextTable($data))->render();
40 | ```
41 |
42 | Will draw the next output:
43 |
44 |
45 | +----+-----------------+----------------+
46 | | id | name | role |
47 | +----+-----------------+----------------+
48 | | 1 | Denis Koronets | php developer |
49 | | 2 | Maxim Ambroskin | java developer |
50 | | 3 | Andrew Sikorsky | php developer |
51 | +----+-----------------+----------------+
52 |
53 |
54 | ## Formatters (since v2)
55 |
56 | Version 2 introduces a new feature that allows to pre and postprocess column data by applying filters.
57 |
58 | You're able to develop your own formatters by extending `BaseColumnFormatter` and implementing abstract methods.
59 |
60 | List of formatters out of the box:
61 | - `AlignFormatter` - allows to set text align for inner column (useful for numbers):
62 |
63 | ```php
64 | use dekor\ArrayToTextTable;
65 | use dekor\formatters\AlignFormatter;
66 |
67 | $data = [
68 | [
69 | 'left' => 2,
70 | 'center' => 'Dummy one',
71 | 'right' => 14.33,
72 | ],
73 | [
74 | 'left' => 3,
75 | 'center' => 'Another great day for a great inventers!',
76 | 'right' => 1,
77 | ],
78 | ];
79 |
80 | $builder = new ArrayToTextTable($data);
81 | $builder->applyFormatter(new AlignFormatter(['center' => 'center', 'right' => 'right']));
82 |
83 | echo $builder->render();
84 | ```
85 |
86 | outputs:
87 |
88 | +------+------------------------------------------+-------+
89 | | left | center | right |
90 | +------+------------------------------------------+-------+
91 | | 2 | Dummy one | 14.33 |
92 | | 3 | Another great day for a great inventers! | 1 |
93 | +------+------------------------------------------+-------+
94 |
95 |
96 | - `SprintfFormatter` - allows to format column value before rendering using sprintf function (ex: %01.3f)
97 | ```php
98 | use dekor\ArrayToTextTable;
99 | use dekor\formatters\SprintfFormatter;
100 |
101 | $data = [
102 | [
103 | 'left' => 1,
104 | 'right' => 2.89,
105 | ]
106 | ];
107 |
108 | $builder = new ArrayToTextTable($data);
109 | $builder->applyFormatter(new SprintfFormatter(['left' => '%01.3f', 'right' => '%03.3f']));
110 |
111 | echo $builder->render();
112 | ```
113 |
114 | outputs:
115 |
116 | +-------+-------+
117 | | left | right |
118 | +-------+-------+
119 | | 1.000 | 2.890 |
120 | +-------+-------+
121 |
122 |
123 | - `ColorFormatter` - allows to highlight text with specific color (only works in terminal):
124 | ```php
125 | use dekor\ArrayToTextTable;
126 | use dekor\formatters\ColorFormatter;
127 |
128 | $data = [
129 | ['test' => 1],
130 | ['test' => -1],
131 | ];
132 |
133 | $builder = new ArrayToTextTable($data);
134 | $builder->applyFormatter(new ColorFormatter(['test' => fn ($value) => $value > 0 ? 'Red' : 'Green']));
135 |
136 | echo $builder->render() . PHP_EOL;
137 | ```
138 |
139 | outputs:
140 |
141 | 
142 |
143 | Allowed colors list (see `ColorFormatter::$colors`)
144 | - Black
145 | - Dark Grey
146 | - Red
147 | - Light Red
148 | - Green
149 | - Light Green
150 | - Brown
151 | - Yellow
152 | - Blue
153 | - Light Blue
154 | - Magenta
155 | - Light Magenta
156 | - Cyan
157 | - Light Cyan
158 | - Light Grey
159 | - White
160 |
161 | ## Our sponsors list:
162 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deniskoronets/php-array-table/1f8ac1fbdfe5ff49b28d50d29f31244bcb36ac72/img.png
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 | ./tests/
18 |
19 |
20 |
21 |
22 | ./src
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/ArrayToTextTable.php:
--------------------------------------------------------------------------------
1 | data = $data;
56 | }
57 |
58 | public function applyFormatter(BaseColumnFormatter $formatter)
59 | {
60 | $this->columnFormatters[] = $formatter;
61 |
62 | return $this;
63 | }
64 |
65 | /**
66 | * Set custom charset for columns values
67 | *
68 | * @param $charset
69 | *
70 | * @return \dekor\ArrayToTextTable
71 | *
72 | * @throws \Exception
73 | */
74 | public function charset($charset)
75 | {
76 | if (!in_array($charset, mb_list_encodings())) {
77 | throw new \Exception(
78 | 'This charset `' . $charset . '` is not supported by mbstring.' .
79 | 'Please check it: http://php.net/manual/ru/function.mb-list-encodings.php'
80 | );
81 | }
82 |
83 | $this->charset = $charset;
84 |
85 | return $this;
86 | }
87 |
88 | /**
89 | * Set mode to print no header in the table
90 | *
91 | * @return self
92 | */
93 | public function noHeader()
94 | {
95 | $this->renderHeader = false;
96 |
97 | return $this;
98 | }
99 |
100 | /**
101 | * Build your ascii table and return the result
102 | *
103 | * @return string
104 | */
105 | public function render()
106 | {
107 | if (empty($this->data)) {
108 | return 'Empty';
109 | }
110 |
111 | $this->validateData();
112 |
113 | $this->applyBeforeFormatters();
114 | $this->calcColumnsList();
115 | $this->calcColumnsLength();
116 |
117 | // render section
118 | $this->renderHeader();
119 | $this->renderBody();
120 | $this->lineSeparator();
121 | // end render section
122 |
123 | return str_replace(
124 | ['++', '||'],
125 | ['+', '|'],
126 | implode(PHP_EOL, $this->result)
127 | );
128 | }
129 |
130 | protected function validateData()
131 | {
132 | foreach ($this->data as &$row) {
133 | foreach ($row as &$column) {
134 | if (!is_scalar($column)) {
135 | if (is_null($column)) {
136 | $column = 'NULL';
137 | continue;
138 | } elseif (is_object($column) && method_exists($column, '__toString')) {
139 | continue;
140 | }
141 |
142 | throw new ArrayToTextTableException(
143 | 'Tried to render invalid data: ' . var_export($column, 1) . '. Only scalars allowed'
144 | );
145 | }
146 | }
147 | }
148 | }
149 |
150 | /**
151 | * Apply formatters to data before calculating length
152 | *
153 | * @return void
154 | */
155 | protected function applyBeforeFormatters()
156 | {
157 | foreach ($this->data as $key => $row) {
158 | foreach ($row as $columnKey => $value) {
159 | foreach ($this->columnFormatters as $formatter) {
160 | $this->data[$key][$columnKey] = $formatter->process($columnKey, $value, true);
161 | }
162 | }
163 | }
164 | }
165 |
166 | /**
167 | * Calculates list of columns in data
168 | */
169 | protected function calcColumnsList()
170 | {
171 | $this->columnsList = array_keys((array) reset($this->data));
172 | }
173 |
174 | /**
175 | * Calculates length for string
176 | *
177 | * @param $str
178 | *
179 | * @return int
180 | */
181 | protected function length($str)
182 | {
183 | return mb_strlen($str, $this->charset);
184 | }
185 |
186 | /**
187 | * Calculate maximum string length for each column
188 | */
189 | private function calcColumnsLength()
190 | {
191 | foreach ($this->data as $row) {
192 | if ($row === '---') {
193 | continue;
194 | }
195 |
196 | foreach ($this->columnsList as $column) {
197 | $this->columnsLength[$column] = max(
198 | isset($this->columnsLength[$column])
199 | ? $this->columnsLength[$column]
200 | : 0,
201 | $this->length($row[$column]),
202 | $this->length($column)
203 | );
204 | }
205 | }
206 | }
207 |
208 | /**
209 | * Append a line separator to result
210 | */
211 | private function lineSeparator()
212 | {
213 | $tmp = [];
214 |
215 | foreach ($this->columnsList as $column) {
216 | $tmp[] = str_repeat(self::H_LINE_CHAR, $this->columnsLength[$column] + 2);
217 | }
218 |
219 | $this->result[] = self::INTERSECT_CHAR . implode(self::INTERSECT_CHAR, $tmp) . self::INTERSECT_CHAR;
220 | }
221 |
222 | /**
223 | * @param $columnKey
224 | * @param $value
225 | *
226 | * @return string
227 | */
228 | private function column($columnKey, $value)
229 | {
230 | return ' ' . $value . str_repeat(
231 | ' ',
232 | $this->columnsLength[$columnKey] - $this->length($value)
233 | ) . ' ';
234 | }
235 |
236 | /**
237 | * Render header part
238 | *
239 | * @return void
240 | */
241 | private function renderHeader()
242 | {
243 | $this->lineSeparator();
244 |
245 | if (!$this->renderHeader) {
246 | return;
247 | }
248 |
249 | $tmp = [];
250 |
251 | foreach ($this->columnsList as $column) {
252 | $tmp[] = $this->column($column, $column);
253 | }
254 |
255 | $this->result[] = self::V_LINE_CHAR . implode(self::V_LINE_CHAR, $tmp) . self::V_LINE_CHAR;
256 |
257 | $this->lineSeparator();
258 | }
259 |
260 | /**
261 | * Render body section of table
262 | *
263 | * @return void
264 | */
265 | private function renderBody()
266 | {
267 | foreach ($this->data as $row) {
268 | if ($row === '---') {
269 | $this->lineSeparator();
270 |
271 | continue;
272 | }
273 |
274 | $tmp = [];
275 |
276 | foreach ($this->columnsList as $column) {
277 | $value = $this->column($column, $row[$column]);
278 |
279 | foreach ($this->columnFormatters as $formatter) {
280 | $value = $formatter->process($column, $value, false);
281 | }
282 |
283 | $tmp[] = $value;
284 | }
285 |
286 | $this->result[] = self::V_LINE_CHAR . implode(self::V_LINE_CHAR, $tmp) . self::V_LINE_CHAR;
287 | }
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/src/ArrayToTextTableException.php:
--------------------------------------------------------------------------------
1 | config = $config;
22 | }
23 |
24 | /**
25 | * @param string $columnName
26 | * @param string $value
27 | * @param bool $isBefore
28 | *
29 | * @return string
30 | */
31 | public function process($columnName, $value, $isBefore)
32 | {
33 | if (!isset($this->config[$columnName])) {
34 | return $value;
35 | }
36 |
37 | $formatterValue = $this->config[$columnName];
38 |
39 | // compute formatter value in case we accepted closure
40 | if (is_callable($this->config[$columnName])) {
41 | $formatterValue = call_user_func($formatterValue, $value);
42 | }
43 |
44 | if ($isBefore) {
45 | return $this->applyBefore($value, $formatterValue);
46 | }
47 |
48 | return $this->applyAfter($value, $formatterValue);
49 | }
50 |
51 | /**
52 | * Allows to apply some formatting to column value before calculating columns length.
53 | * Just return $value in case you don't want to do anything with the column at this stage
54 | *
55 | * @param $value
56 | * @param string $formatterValue
57 | *
58 | * @return string
59 | */
60 | abstract protected function applyBefore($value, $formatterValue);
61 |
62 | /**
63 | * Allows to apply some formatting to column value after adding spaces to column value
64 | * Just return $value in case you don't want to do anything with the column at this stage
65 | *
66 | * @param $value
67 | * @param string $formatterValue
68 | *
69 | * @return string
70 | */
71 | abstract protected function applyAfter($value, $formatterValue);
72 | }
73 |
--------------------------------------------------------------------------------
/src/formatters/ColorFormatter.php:
--------------------------------------------------------------------------------
1 | self::DEFAULT_COLOR,
12 |
13 | 'Black' => '0;30',
14 | 'Dark Grey' => '1;30',
15 | 'Red' => '0;31',
16 | 'Light Red' => '1;31',
17 | 'Green' => '0;32',
18 | 'Light Green' => '1;32',
19 | 'Brown' => '0;33',
20 | 'Yellow' => '1;33',
21 | 'Blue' => '0;34',
22 | 'Light Blue' => '1;34',
23 | 'Magenta' => '0;35',
24 | 'Light Magenta' => '1;35',
25 | 'Cyan' => '0;36',
26 | 'Light Cyan' => '1;36',
27 | 'Light Grey' => '0;37',
28 | 'White' => '1;37',
29 | ];
30 |
31 | protected function applyBefore($value, $formatterValue)
32 | {
33 | return $value;
34 | }
35 |
36 | protected function applyAfter($value, $formatterValue)
37 | {
38 | if ($formatterValue == 'Default') {
39 | return $value;
40 | }
41 |
42 | if (!isset($this->colors[$formatterValue])) {
43 | throw new ArrayToTextTableException('Unknown color to apply: ' . $formatterValue);
44 | }
45 |
46 | $color = $this->colors[$formatterValue];
47 |
48 | return "\e[" . $color . 'm' . $value . "\e[" . self::DEFAULT_COLOR;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/formatters/SprintfFormatter.php:
--------------------------------------------------------------------------------
1 | 1],
13 | ['test' => -1],
14 | ];
15 |
16 | $builder = new ArrayToTextTable($data);
17 | $builder->applyFormatter(new ColorFormatter(['test' => fn ($value) => $value > 0 ? 'Red' : 'Green']));
18 |
19 | echo $builder->render() . PHP_EOL;
20 |
--------------------------------------------------------------------------------
/tests/AlignFormatterTest.php:
--------------------------------------------------------------------------------
1 | applyFormatter(new AlignFormatter(['center' => 'center', 'right' => 'right']));
25 |
26 | $this->assertEquals($expectResult, $builder->render());
27 | }
28 |
29 | public static function getCases()
30 | {
31 | return [
32 | [
33 | 'data' => [
34 | [
35 | 'left' => 1,
36 | 'center' => 'Denis Koronets',
37 | 'right' => 2.89,
38 | ],
39 | [
40 | 'left' => 2,
41 | 'center' => 'Dummy one',
42 | 'right' => 14.33,
43 | ],
44 | ],
45 | 'expected' =>
46 | '+------+----------------+-------+' . PHP_EOL .
47 | '| left | center | right |' . PHP_EOL .
48 | '+------+----------------+-------+' . PHP_EOL .
49 | '| 1 | Denis Koronets | 2.89 |' . PHP_EOL .
50 | '| 2 | Dummy one | 14.33 |' . PHP_EOL .
51 | '+------+----------------+-------+',
52 | ],
53 | ];
54 | }
55 |
56 | public function testInCorrectBuilding()
57 | {
58 | $data = [['test' => 1]];
59 |
60 | $builder = new ArrayToTextTable($data);
61 | $builder->applyFormatter(new AlignFormatter(['test' => 'imposible']));
62 |
63 | $this->expectException(ArrayToTextTableException::class);
64 | $builder->render();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tests/ColorTest.php:
--------------------------------------------------------------------------------
1 | applyFormatter(new ColorFormatter([
26 | 'test' => function ($value) {
27 | return $value > 0 ? 'Red' : 'Green';
28 | }
29 | ]));
30 |
31 | $this->assertEquals($expectResult, $builder->render());
32 | }
33 |
34 | public static function getCases()
35 | {
36 | return [
37 | [
38 | 'data' => [
39 | ['test' => 1],
40 | ['test' => -1],
41 | ],
42 | 'expected' =>
43 | '+------+' . PHP_EOL .
44 | '| test |' . PHP_EOL .
45 | '+------+' . PHP_EOL .
46 | '|[0;31m 1 [0m|' . PHP_EOL .
47 | '|[0;32m -1 [0m|' . PHP_EOL .
48 | '+------+',
49 | ],
50 | ];
51 | }
52 |
53 | public function testInCorrectBuilding()
54 | {
55 | $data = [['test' => 1]];
56 |
57 | $builder = new ArrayToTextTable($data);
58 | $builder->applyFormatter(new AlignFormatter(['test' => 'imposible']));
59 |
60 | $this->expectException(ArrayToTextTableException::class);
61 | $builder->render();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/CombinedAlignSprintfFormatterTest.php:
--------------------------------------------------------------------------------
1 | applyFormatter(new AlignFormatter(['center' => 'center', 'right' => 'right']));
26 | $builder->applyFormatter(new SprintfFormatter(['right' => '%01.3f']));
27 |
28 | $this->assertEquals($expectResult, $builder->render());
29 | }
30 |
31 | public static function getCases()
32 | {
33 | return [
34 | [
35 | 'data' => [
36 | [
37 | 'left' => 1,
38 | 'center' => 'Denis Koronets',
39 | 'right' => 2.89,
40 | ],
41 | [
42 | 'left' => 2,
43 | 'center' => 'Dummy one',
44 | 'right' => 14.33,
45 | ],
46 | [
47 | 'left' => 3,
48 | 'center' => 'Another great day for a great inventors!',
49 | 'right' => 1,
50 | ],
51 | ],
52 | 'expected' =>
53 | '+------+------------------------------------------+--------+' . PHP_EOL .
54 | '| left | center | right |' . PHP_EOL .
55 | '+------+------------------------------------------+--------+' . PHP_EOL .
56 | '| 1 | Denis Koronets | 2.890 |' . PHP_EOL .
57 | '| 2 | Dummy one | 14.330 |' . PHP_EOL .
58 | '| 3 | Another great day for a great inventors! | 1.000 |' . PHP_EOL .
59 | '+------+------------------------------------------+--------+',
60 | ],
61 | ];
62 | }
63 |
64 | public function testInCorrectBuilding()
65 | {
66 | $data = [['test' => 1]];
67 |
68 | $builder = new ArrayToTextTable($data);
69 | $builder->applyFormatter(new AlignFormatter(['test' => 'imposible']));
70 |
71 | $this->expectException(ArrayToTextTableException::class);
72 | $builder->render();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/SimpleTest.php:
--------------------------------------------------------------------------------
1 | assertEquals($expectResult, $builder->render());
25 | }
26 |
27 | public static function getCases()
28 | {
29 | return [
30 | [
31 | 'data' => [
32 | [
33 | 'id' => 1,
34 | 'name' => 'Denis Koronets',
35 | 'role' => 'php developer',
36 | ],
37 | [
38 | 'id' => 2,
39 | 'name' => 'Maxim Ambroskin',
40 | 'role' => 'java developer',
41 | ],
42 | [
43 | 'id' => 3,
44 | 'name' => 'Andrew Sikorsky',
45 | 'role' => 'php developer',
46 | ],
47 | ],
48 | 'expected' =>
49 | '+----+-----------------+----------------+' . PHP_EOL .
50 | '| id | name | role |' . PHP_EOL .
51 | '+----+-----------------+----------------+' . PHP_EOL .
52 | '| 1 | Denis Koronets | php developer |' . PHP_EOL .
53 | '| 2 | Maxim Ambroskin | java developer |' . PHP_EOL .
54 | '| 3 | Andrew Sikorsky | php developer |' . PHP_EOL .
55 | '+----+-----------------+----------------+',
56 | ],
57 | [
58 | 'data' => [
59 | [
60 | 'singleColumn' => 'test value',
61 | ],
62 | ],
63 | 'expected' =>
64 | '+--------------+' . PHP_EOL .
65 | '| singleColumn |' . PHP_EOL .
66 | '+--------------+' . PHP_EOL .
67 | '| test value |' . PHP_EOL .
68 | '+--------------+',
69 | ],
70 | [
71 | 'data' => [
72 | [
73 | 'id' => 1,
74 | 'name' => 'Денис Коронец',
75 | 'role' => 'Тест кириллических символов',
76 | ],
77 | ],
78 | 'expected' =>
79 | '+----+---------------+-----------------------------+' . PHP_EOL .
80 | '| id | name | role |' . PHP_EOL .
81 | '+----+---------------+-----------------------------+' . PHP_EOL .
82 | '| 1 | Денис Коронец | Тест кириллических символов |' . PHP_EOL .
83 | '+----+---------------+-----------------------------+',
84 | ],
85 | [
86 | 'data' => [
87 | [
88 | 'id' => 1,
89 | 'name' => 'Денис Коронец',
90 | 'role' => 'Тест кириллических символов',
91 | ],
92 | '---',
93 | [
94 | 'id' => 2,
95 | 'name' => 'Артем Малеев',
96 | 'role' => 'Тест кириллических символов 2',
97 | ],
98 | ],
99 | 'expected' =>
100 | '+----+---------------+-------------------------------+' . PHP_EOL .
101 | '| id | name | role |' . PHP_EOL .
102 | '+----+---------------+-------------------------------+' . PHP_EOL .
103 | '| 1 | Денис Коронец | Тест кириллических символов |' . PHP_EOL .
104 | '+----+---------------+-------------------------------+' . PHP_EOL .
105 | '| 2 | Артем Малеев | Тест кириллических символов 2 |' . PHP_EOL .
106 | '+----+---------------+-------------------------------+',
107 | ],
108 | [
109 | 'data' => [
110 | ['test' => 1],
111 | ['test' => -1],
112 | ['test' => null],
113 | ],
114 | 'expected' =>
115 | '+------+' . PHP_EOL .
116 | '| test |' . PHP_EOL .
117 | '+------+' . PHP_EOL .
118 | '| 1 |' . PHP_EOL .
119 | '| -1 |' . PHP_EOL .
120 | '| NULL |' . PHP_EOL .
121 | '+------+',
122 | ],
123 | ];
124 | }
125 |
126 | public function testInCorrectDataBuilding()
127 | {
128 | $data = [['test' => []]];
129 |
130 | $builder = new ArrayToTextTable($data);
131 |
132 | $this->expectException(ArrayToTextTableException::class);
133 | $builder->render();
134 | }
135 | }
136 |
--------------------------------------------------------------------------------