|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace ViewComponents\Grids; |
|
4
|
|
|
|
|
5
|
|
|
use Nayjest\Collection\Extended\ObjectCollectionReadInterface; |
|
6
|
|
|
use RuntimeException; |
|
7
|
|
|
use ViewComponents\Grids\Component\Column; |
|
8
|
|
|
use ViewComponents\ViewComponents\Component\Html\Tag; |
|
9
|
|
|
use ViewComponents\ViewComponents\Component\ManagedList; |
|
10
|
|
|
use ViewComponents\ViewComponents\Component\ManagedList\RecordView; |
|
11
|
|
|
use ViewComponents\ViewComponents\Component\Part; |
|
12
|
|
|
use ViewComponents\Grids\Component\SolidRow; |
|
13
|
|
|
|
|
14
|
|
|
/** |
|
15
|
|
|
* Grid component. |
|
16
|
|
|
*/ |
|
17
|
|
|
class Grid extends ManagedList |
|
18
|
|
|
{ |
|
19
|
|
|
const TABLE_ID = 'table'; |
|
20
|
|
|
const TABLE_HEADING_ID = 'table_heading'; |
|
21
|
|
|
const TABLE_FOOTER_ID = 'table_footer'; |
|
22
|
|
|
const TABLE_BODY_ID = 'table_body'; |
|
23
|
|
|
const TITLE_ROW_ID = 'title_row'; |
|
24
|
|
|
const CONTROL_ROW_ID = 'control_row'; |
|
25
|
|
|
|
|
26
|
|
|
use GridPartsAccessTrait; |
|
27
|
|
|
|
|
28
|
|
|
/** @var mixed|null */ |
|
29
|
|
|
protected $currentRow; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Returns column collection (readonly). |
|
33
|
|
|
* |
|
34
|
|
|
* @return Column[]|ObjectCollectionReadInterface |
|
35
|
|
|
*/ |
|
36
|
|
|
public function getColumns() |
|
37
|
|
|
{ |
|
38
|
|
|
return $this->getComponents()->filterByType(Column::class); |
|
39
|
|
|
} |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* Returns column with specified id, |
|
43
|
|
|
* throws exception if grid does not have specified column. |
|
44
|
|
|
* |
|
45
|
|
|
* @param string $id |
|
46
|
|
|
* @return Column |
|
47
|
|
|
*/ |
|
48
|
|
|
public function getColumn($id) |
|
49
|
|
|
{ |
|
50
|
|
|
$column = $this->getComponent($id); |
|
51
|
|
|
if (!$column) { |
|
52
|
|
|
throw new RuntimeException("Column '$id' is not defined."); |
|
53
|
|
|
} |
|
54
|
|
|
if (!$column instanceof Column) { |
|
55
|
|
|
throw new RuntimeException("'$id' is not a column."); |
|
56
|
|
|
} |
|
57
|
|
|
return $column; |
|
58
|
|
|
} |
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* Returns current grid row, used internally for grid rendering. |
|
62
|
|
|
* |
|
63
|
|
|
* @internal |
|
64
|
|
|
* @return mixed |
|
65
|
|
|
*/ |
|
66
|
|
|
public function getCurrentRow() |
|
67
|
|
|
{ |
|
68
|
|
|
return $this->currentRow; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Sets current grid row for rendering, used internally for grid rendering. |
|
73
|
|
|
* |
|
74
|
|
|
* @internal |
|
75
|
|
|
* @param mixed $currentRow |
|
76
|
|
|
* @return $this |
|
77
|
|
|
*/ |
|
78
|
|
|
public function setCurrentRow($currentRow) |
|
79
|
|
|
{ |
|
80
|
|
|
$this->currentRow = $currentRow; |
|
81
|
|
|
return $this; |
|
82
|
|
|
} |
|
83
|
|
|
|
|
84
|
|
|
protected function makeDataInjector() |
|
85
|
|
|
{ |
|
86
|
|
|
return [$this, 'setCurrentRow']; |
|
|
|
|
|
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
protected function makeDefaultComponents() |
|
90
|
|
|
{ |
|
91
|
|
|
$components = parent::makeDefaultComponents(); |
|
92
|
|
|
unset($components[ManagedList::RECORD_VIEW_ID]); |
|
93
|
|
|
$components[ManagedList::CONTROL_CONTAINER_ID]->setDestinationParentId(static::CONTROL_ROW_ID); |
|
94
|
|
|
$components[ManagedList::LIST_CONTAINER_ID]->setDestinationParentId(static::TABLE_BODY_ID); |
|
95
|
|
|
$components[ManagedList::SUBMIT_BUTTON_ID]->setDestinationParentId(static::CONTROL_ROW_ID); |
|
96
|
|
|
return array_merge( |
|
97
|
|
|
$components, |
|
98
|
|
|
[ |
|
99
|
|
|
static::TABLE_ID => new Part( |
|
100
|
|
|
new Tag('table'), |
|
101
|
|
|
static::TABLE_ID, |
|
102
|
|
|
static::FORM_ID |
|
103
|
|
|
), |
|
104
|
|
|
static::TABLE_HEADING_ID => new Part( |
|
105
|
|
|
new Tag('thead'), |
|
106
|
|
|
static::TABLE_HEADING_ID, |
|
107
|
|
|
static::TABLE_ID |
|
108
|
|
|
), |
|
109
|
|
|
static::TITLE_ROW_ID => new Part( |
|
110
|
|
|
new Tag('tr'), |
|
111
|
|
|
static::TITLE_ROW_ID, |
|
112
|
|
|
static::TABLE_HEADING_ID |
|
113
|
|
|
), |
|
114
|
|
|
static::CONTROL_ROW_ID => new Part( |
|
115
|
|
|
new SolidRow(), |
|
116
|
|
|
static::CONTROL_ROW_ID, |
|
117
|
|
|
static::TABLE_HEADING_ID |
|
118
|
|
|
), |
|
119
|
|
|
static::TABLE_BODY_ID => new Part(new Tag('tbody'), static::TABLE_BODY_ID, static::TABLE_ID), |
|
120
|
|
|
static::RECORD_VIEW_ID => new RecordView(new Tag('tr')), |
|
121
|
|
|
static::TABLE_FOOTER_ID => new Part(new Tag('tfoot'), static::TABLE_FOOTER_ID, static::TABLE_ID), |
|
122
|
|
|
] |
|
123
|
|
|
); |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* Prepares component for rendering. |
|
128
|
|
|
*/ |
|
129
|
|
|
protected function prepare() |
|
130
|
|
|
{ |
|
131
|
|
|
parent::prepare(); |
|
132
|
|
|
$this->hideControlRowIfEmpty(); |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
protected function hideControlRowIfEmpty() |
|
136
|
|
|
{ |
|
137
|
|
|
$row = $this->getControlRow(); |
|
138
|
|
|
$container = $this->getControlContainer(); |
|
139
|
|
|
if (!$row |
|
140
|
|
|
|| !$container |
|
141
|
|
|
|| !$container->children()->isEmpty() |
|
142
|
|
|
|| ($row->children()->count() > 2) // submit button + control_container |
|
143
|
|
|
) { |
|
144
|
|
|
return; |
|
145
|
|
|
} |
|
146
|
|
|
/** @var Part $rowPart */ |
|
147
|
|
|
$rowPart = $this->getComponent(static::CONTROL_ROW_ID, false); |
|
148
|
|
|
$rowPart->setView(null); |
|
149
|
|
|
} |
|
150
|
|
|
} |
|
151
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.