Skip to content

Commit 354b43a

Browse files
authored
Merge pull request #6538 from ddevsr/feat-table-attribute
fix: table attribute cannot applied on td element
2 parents ac2ad22 + df614a7 commit 354b43a

File tree

2 files changed

+266
-4
lines changed

2 files changed

+266
-4
lines changed

system/View/Table.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,14 +295,20 @@ public function generate($tableData = null)
295295

296296
// Is there a table heading to display?
297297
if (! empty($this->heading)) {
298+
$headerTag = null;
299+
300+
if (preg_match('/(<)(td|th)(?=\h|>)/i', $this->template['heading_cell_start'], $matches) === 1) {
301+
$headerTag = $matches[0];
302+
}
303+
298304
$out .= $this->template['thead_open'] . $this->newline . $this->template['heading_row_start'] . $this->newline;
299305

300306
foreach ($this->heading as $heading) {
301307
$temp = $this->template['heading_cell_start'];
302308

303309
foreach ($heading as $key => $val) {
304-
if ($key !== 'data') {
305-
$temp = str_replace('<th', '<th ' . $key . '="' . $val . '"', $temp);
310+
if ($key !== 'data' && $headerTag !== null) {
311+
$temp = str_replace($headerTag, $headerTag . ' ' . $key . '="' . $val . '"', $temp);
306312
}
307313
}
308314

@@ -355,14 +361,20 @@ public function generate($tableData = null)
355361

356362
// Any table footing to display?
357363
if (! empty($this->footing)) {
364+
$footerTag = null;
365+
366+
if (preg_match('/(<)(td|th)(?=\h|>)/i', $this->template['footing_cell_start'], $matches)) {
367+
$footerTag = $matches[0];
368+
}
369+
358370
$out .= $this->template['tfoot_open'] . $this->newline . $this->template['footing_row_start'] . $this->newline;
359371

360372
foreach ($this->footing as $footing) {
361373
$temp = $this->template['footing_cell_start'];
362374

363375
foreach ($footing as $key => $val) {
364-
if ($key !== 'data') {
365-
$temp = str_replace('<th', '<th ' . $key . '="' . $val . '"', $temp);
376+
if ($key !== 'data' && $footerTag !== null) {
377+
$temp = str_replace($footerTag, $footerTag . ' ' . $key . '="' . $val . '"', $temp);
366378
}
367379
}
368380

tests/system/View/TableTest.php

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
final class TableTest extends CIUnitTestCase
2323
{
2424
private Table $table;
25+
private string $styleTableOne = 'background:#F99;text-align:right;width:5em;';
26+
private string $styleTableTwo = 'background:cyan;color:white;text-align:right;width:5em;';
2527

2628
protected function setUp(): void
2729
{
@@ -92,6 +94,58 @@ public function testSetFooting()
9294
);
9395
}
9496

97+
public function testSetHeadingWithStyle()
98+
{
99+
$template = [
100+
'heading_cell_start' => '<td>',
101+
'heading_cell_end' => '</td>',
102+
];
103+
104+
$this->table->setTemplate($template);
105+
$this->table->setHeading([['data' => 'Name', 'class' => 'tdh'], ['data' => 'Amount', 'class' => 'tdf', 'style' => $this->styleTableOne]]);
106+
107+
$this->assertSame(
108+
[
109+
[
110+
'data' => 'Name',
111+
'class' => 'tdh',
112+
],
113+
[
114+
'data' => 'Amount',
115+
'class' => 'tdf',
116+
'style' => $this->styleTableOne,
117+
],
118+
],
119+
$this->table->heading
120+
);
121+
}
122+
123+
public function testSetFootingWithStyle()
124+
{
125+
$template = [
126+
'footing_cell_start' => '<td>',
127+
'footing_cell_end' => '</td>',
128+
];
129+
130+
$this->table->setTemplate($template);
131+
$this->table->setFooting([['data' => 'Total', 'class' => 'tdf'], ['data' => 3, 'class' => 'tdh', 'style' => $this->styleTableTwo]]);
132+
133+
$this->assertSame(
134+
[
135+
[
136+
'data' => 'Total',
137+
'class' => 'tdf',
138+
],
139+
[
140+
'data' => 3,
141+
'class' => 'tdh',
142+
'style' => $this->styleTableTwo,
143+
],
144+
],
145+
$this->table->footing
146+
);
147+
}
148+
95149
/**
96150
* @depends testPrepArgs
97151
*/
@@ -375,6 +429,202 @@ public function testGenerate()
375429
$this->assertStringContainsString('<td>12345</td>', $table);
376430
}
377431

432+
public function testGenerateTdWithClassStyle()
433+
{
434+
$template = [
435+
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
436+
'thead_open' => '<thead>',
437+
'thead_close' => '</thead>',
438+
'heading_row_start' => '<tr>',
439+
'heading_row_end' => '</tr>',
440+
'heading_cell_start' => '<td>',
441+
'heading_cell_end' => '</td>',
442+
'tfoot_open' => '<tfoot>',
443+
'tfoot_close' => '</tfoot>',
444+
'footing_row_start' => '<tr>',
445+
'footing_row_end' => '</tr>',
446+
'footing_cell_start' => '<td>',
447+
'footing_cell_end' => '</td>',
448+
'tbody_open' => '<tbody>',
449+
'tbody_close' => '</tbody>',
450+
'row_start' => '<tr>',
451+
'row_end' => '</tr>',
452+
'cell_start' => '<td>',
453+
'cell_end' => '</td>',
454+
'row_alt_start' => '<tr>',
455+
'row_alt_end' => '</tr>',
456+
'cell_alt_start' => '<td>',
457+
'cell_alt_end' => '</td>',
458+
'table_close' => '</table>',
459+
];
460+
461+
$this->table->setTemplate($template);
462+
$this->table->setHeading([['data' => 'Name', 'class' => 'tdk'], ['data' => 'Amount', 'class' => 'tdr', 'style' => $this->styleTableOne]]);
463+
464+
$this->table->addRow(['Fred', 1]);
465+
$this->table->addRow(['Mary', 3]);
466+
$this->table->addRow(['John', 6]);
467+
468+
$this->table->setFooting([['data' => 'Total', 'class' => 'thk'], ['data' => '<small class="text-light">IDR <span class="badge badge-info">10</span></small>', 'class' => 'thr', 'style' => $this->styleTableTwo]]);
469+
470+
$table = $this->table->generate();
471+
472+
// Header
473+
$this->assertStringContainsString('<td class="tdk">Name</td>', $table);
474+
$this->assertStringContainsString('<td style="' . $this->styleTableOne . '" class="tdr">Amount</td>', $table);
475+
476+
// Footer
477+
$this->assertStringContainsString('<td class="thk">Total</td>', $table);
478+
$this->assertStringContainsString('<td style="' . $this->styleTableTwo . '" class="thr"><small class="text-light">IDR <span class="badge badge-info">10</span></small></td>', $table);
479+
}
480+
481+
public function testGenerateThWithClassStyle()
482+
{
483+
$template = [
484+
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
485+
'thead_open' => '<thead>',
486+
'thead_close' => '</thead>',
487+
'heading_row_start' => '<tr>',
488+
'heading_row_end' => '</tr>',
489+
'heading_cell_start' => '<th>',
490+
'heading_cell_end' => '</th>',
491+
'tfoot_open' => '<tfoot>',
492+
'tfoot_close' => '</tfoot>',
493+
'footing_row_start' => '<tr>',
494+
'footing_row_end' => '</tr>',
495+
'footing_cell_start' => '<th>',
496+
'footing_cell_end' => '</th>',
497+
'tbody_open' => '<tbody>',
498+
'tbody_close' => '</tbody>',
499+
'row_start' => '<tr>',
500+
'row_end' => '</tr>',
501+
'cell_start' => '<td>',
502+
'cell_end' => '</td>',
503+
'row_alt_start' => '<tr>',
504+
'row_alt_end' => '</tr>',
505+
'cell_alt_start' => '<td>',
506+
'cell_alt_end' => '</td>',
507+
'table_close' => '</table>',
508+
];
509+
510+
$this->table->setTemplate($template);
511+
$this->table->setHeading([['data' => 'Name', 'class' => 'tdk'], ['data' => 'Amount', 'class' => 'tdr', 'style' => $this->styleTableOne]]);
512+
513+
$this->table->addRow(['Fred', 1]);
514+
$this->table->addRow(['Mary', 3]);
515+
$this->table->addRow(['John', 6]);
516+
517+
$this->table->setFooting([['data' => 'Total', 'class' => 'thk'], ['data' => '<small class="text-light">IDR <span class="badge badge-info">10</span></small>', 'class' => 'thr', 'style' => $this->styleTableTwo]]);
518+
519+
$table = $this->table->generate();
520+
521+
// Header
522+
$this->assertStringContainsString('<th class="tdk">Name</th>', $table);
523+
$this->assertStringContainsString('<th style="' . $this->styleTableOne . '" class="tdr">Amount</th>', $table);
524+
525+
// Footer
526+
$this->assertStringContainsString('<th class="thk">Total</th>', $table);
527+
$this->assertStringContainsString('<th style="' . $this->styleTableTwo . '" class="thr"><small class="text-light">IDR <span class="badge badge-info">10</span></small></th>', $table);
528+
}
529+
530+
public function testGenerateInvalidHeadingFooting()
531+
{
532+
$template = [
533+
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
534+
'thead_open' => '<thead>',
535+
'thead_close' => '</thead>',
536+
'heading_row_start' => '<tr>',
537+
'heading_row_end' => '</tr>',
538+
'heading_cell_start' => '<header>',
539+
'heading_cell_end' => '</header>',
540+
'tfoot_open' => '<tfoot>',
541+
'tfoot_close' => '</tfoot>',
542+
'footing_row_start' => '<tr>',
543+
'footing_row_end' => '</tr>',
544+
'footing_cell_start' => '<footer>',
545+
'footing_cell_end' => '</footer>',
546+
'tbody_open' => '<tbody>',
547+
'tbody_close' => '</tbody>',
548+
'row_start' => '<tr>',
549+
'row_end' => '</tr>',
550+
'cell_start' => '<td>',
551+
'cell_end' => '</td>',
552+
'row_alt_start' => '<tr>',
553+
'row_alt_end' => '</tr>',
554+
'cell_alt_start' => '<td>',
555+
'cell_alt_end' => '</td>',
556+
'table_close' => '</table>',
557+
];
558+
559+
$this->table->setTemplate($template);
560+
$this->table->setHeading([['data' => 'Name', 'class' => 'tdk'], ['data' => 'Amount', 'class' => 'tdr', 'style' => $this->styleTableOne]]);
561+
562+
$this->table->addRow(['Fred', 1]);
563+
$this->table->addRow(['Mary', 3]);
564+
$this->table->addRow(['John', 6]);
565+
566+
$this->table->setFooting([['data' => 'Total', 'class' => 'thk'], ['data' => '<small class="text-light">IDR <span class="badge badge-info">10</span></small>', 'class' => 'thr', 'style' => $this->styleTableTwo]]);
567+
568+
$table = $this->table->generate();
569+
570+
// Header
571+
$this->assertStringContainsString('<header>Name</header>', $table);
572+
$this->assertStringContainsString('<header>Amount</header>', $table);
573+
574+
// Footer
575+
$this->assertStringContainsString('<footer>Total</footer>', $table);
576+
$this->assertStringContainsString('<footer><small class="text-light">IDR <span class="badge badge-info">10</span></small></footer>', $table);
577+
}
578+
579+
public function testGenerateInvalidHeadingFootingHTML()
580+
{
581+
$template = [
582+
'table_open' => '<table border="1" cellpadding="4" cellspacing="0">',
583+
'thead_open' => '<thead>',
584+
'thead_close' => '</thead>',
585+
'heading_row_start' => '<tr>',
586+
'heading_row_end' => '</tr>',
587+
'heading_cell_start' => 'th>',
588+
'heading_cell_end' => '</th>',
589+
'tfoot_open' => '<tfoot>',
590+
'tfoot_close' => '</tfoot>',
591+
'footing_row_start' => '<tr>',
592+
'footing_row_end' => '</tr>',
593+
'footing_cell_start' => 'td>',
594+
'footing_cell_end' => '</td>',
595+
'tbody_open' => '<tbody>',
596+
'tbody_close' => '</tbody>',
597+
'row_start' => '<tr>',
598+
'row_end' => '</tr>',
599+
'cell_start' => '<td>',
600+
'cell_end' => '</td>',
601+
'row_alt_start' => '<tr>',
602+
'row_alt_end' => '</tr>',
603+
'cell_alt_start' => '<td>',
604+
'cell_alt_end' => '</td>',
605+
'table_close' => '</table>',
606+
];
607+
608+
$this->table->setTemplate($template);
609+
$this->table->setHeading([['data' => 'Name', 'class' => 'tdk'], ['data' => 'Amount', 'class' => 'tdr', 'style' => $this->styleTableOne]]);
610+
611+
$this->table->addRow(['Fred', 1]);
612+
$this->table->addRow(['Mary', 3]);
613+
$this->table->addRow(['John', 6]);
614+
615+
$this->table->setFooting([['data' => 'Total', 'class' => 'thk'], ['data' => '<small class="text-light">IDR <span class="badge badge-info">10</span></small>', 'class' => 'thr', 'style' => $this->styleTableTwo]]);
616+
617+
$table = $this->table->generate();
618+
619+
// Header
620+
$this->assertStringContainsString('th>Name</th>', $table);
621+
$this->assertStringContainsString('th>Amount</th>', $table);
622+
623+
// Footer
624+
$this->assertStringContainsString('td>Total</td>', $table);
625+
$this->assertStringContainsString('td><small class="text-light">IDR <span class="badge badge-info">10</span></small></td>', $table);
626+
}
627+
378628
public function testGenerateEmptyCell()
379629
{
380630
// Prepare the data

0 commit comments

Comments
 (0)