1
|
<?php
|
2
|
|
3
|
|
4
|
class DerivationTreeComposer {
|
5
|
|
6
|
private $root_unit_dtos;
|
7
|
private $focused_unit_uuid = null;
|
8
|
private $with_details = false;
|
9
|
private $collapsible = false;
|
10
|
private $use_field_unit_short_label = null;
|
11
|
|
12
|
/**
|
13
|
* @return bool
|
14
|
*/
|
15
|
public function isCollapsible() {
|
16
|
return $this->collapsible;
|
17
|
}
|
18
|
|
19
|
/**
|
20
|
* @param bool $collapsible
|
21
|
*/
|
22
|
public function setCollapsible($collapsible) {
|
23
|
$this->collapsible = $collapsible;
|
24
|
}
|
25
|
|
26
|
/**
|
27
|
* @return bool
|
28
|
*/
|
29
|
public function isWithDetails() {
|
30
|
return $this->with_details;
|
31
|
}
|
32
|
|
33
|
private function useFieldUnitShortLabel() {
|
34
|
if($this->use_field_unit_short_label === null){
|
35
|
$specimen_derivate_tree_options = get_array_variable_merged(CDM_SPECIMEN_DERIVATE_TREE_OPTIONS, CDM_SPECIMEN_DERIVATE_TREE_OPTIONS_DEFAULT);
|
36
|
$this->use_field_unit_short_label = $specimen_derivate_tree_options['field_unit_short_label'];
|
37
|
}
|
38
|
return $this->use_field_unit_short_label;
|
39
|
}
|
40
|
|
41
|
public function collapsibleItemClassAttribute($has_sub_derivatives) {
|
42
|
return $this->isCollapsible() & $has_sub_derivatives === TRUE ? ' tree-item-collapsible' : '';
|
43
|
|
44
|
}
|
45
|
|
46
|
public function subItemsClassAttribute($has_sub_derivatives) {
|
47
|
return $has_sub_derivatives === true ? ' with-sub-items' : '';
|
48
|
}
|
49
|
|
50
|
public function itemCollapsedStateClassAttribute() {
|
51
|
return $this->isCollapsible() ? ' collapsed' : '';
|
52
|
}
|
53
|
|
54
|
/**
|
55
|
* @param bool $with_details
|
56
|
*/
|
57
|
public function setWithDetails($with_details) {
|
58
|
$this->with_details = $with_details;
|
59
|
}
|
60
|
|
61
|
/**
|
62
|
* DerivationTreeComposer constructor.
|
63
|
*/
|
64
|
public function __construct($root_unit_dtos ) {
|
65
|
$this->root_unit_dtos = $root_unit_dtos;
|
66
|
}
|
67
|
|
68
|
/**
|
69
|
* @return array
|
70
|
* list of SpecimenOrObservationDTOs
|
71
|
*/
|
72
|
public function getRootUnitDtos() {
|
73
|
return $this->root_unit_dtos;
|
74
|
}
|
75
|
|
76
|
/**
|
77
|
* @param array $root_unit_dtos
|
78
|
* list of SpecimenOrObservationDTOs
|
79
|
*/
|
80
|
public function setRootUnitDtos($root_unit_dtos) {
|
81
|
$this->root_unit_dtos = $root_unit_dtos;
|
82
|
}
|
83
|
|
84
|
/**
|
85
|
* @return null
|
86
|
*/
|
87
|
public function getFocusedUnitUuid() {
|
88
|
return $this->focused_unit_uuid;
|
89
|
}
|
90
|
|
91
|
/**
|
92
|
* @param null $focused_unit_uuid
|
93
|
*/
|
94
|
public function setFocusedUnitUuid($focused_unit_uuid) {
|
95
|
$this->focused_unit_uuid = $focused_unit_uuid;
|
96
|
}
|
97
|
|
98
|
public function compose() {
|
99
|
$derivation_tree = $this->derived_units_tree($this->root_unit_dtos);
|
100
|
|
101
|
$render_array = [];
|
102
|
$render_array['derived-unit-tree'] = $derivation_tree;
|
103
|
|
104
|
_add_js_derivation_tree('.item-tree');
|
105
|
|
106
|
return $render_array;
|
107
|
}
|
108
|
|
109
|
/* ======= member compose methods ========== */
|
110
|
|
111
|
|
112
|
/**
|
113
|
* Creates the root levels and trees for all subordinate derivatives.
|
114
|
*
|
115
|
* See derived_units_sub_tree()
|
116
|
*
|
117
|
* @return array
|
118
|
* An array which can be used in render arrays to be passed to the
|
119
|
* theme_table() and theme_list().
|
120
|
*/
|
121
|
|
122
|
private function derived_units_tree() {
|
123
|
RenderHints::pushToRenderStack('derived-unit-tree');
|
124
|
RenderHints::setFootnoteListKey('derived-unit-tree');
|
125
|
|
126
|
$list_items = $this->derived_units_as_list_items($this->root_unit_dtos);
|
127
|
|
128
|
$root_items = [
|
129
|
'#theme' => 'item_list',
|
130
|
'#type' => 'ul',
|
131
|
'#prefix' => '<div class="item-tree">',
|
132
|
'#suffix' => '</div>',
|
133
|
'#attributes' => [
|
134
|
],
|
135
|
'#items' => $list_items,
|
136
|
];
|
137
|
|
138
|
$root_items['footnotes'] = markup_to_render_array(render_footnotes());
|
139
|
RenderHints::popFromRenderStack();
|
140
|
|
141
|
return $root_items;
|
142
|
|
143
|
}
|
144
|
|
145
|
/**
|
146
|
* Creates render array items for FieldUnitDTO or DerivedUnitDTO.
|
147
|
*
|
148
|
* @param array $root_unit_dtos
|
149
|
* list of SpecimenOrObservationDTOs
|
150
|
*
|
151
|
* @return array
|
152
|
* An array which can be used in render arrays to be passed to the
|
153
|
* theme_table() and theme_list().
|
154
|
*/
|
155
|
private function derived_units_as_list_items(array $root_unit_dtos) {
|
156
|
|
157
|
$list_items = [];
|
158
|
//we need one more item to contain the items of one level (fieldunit, derivate data etc.)
|
159
|
foreach ($root_unit_dtos as &$sob_dto) {
|
160
|
$has_sub_derivatives = isset($sob_dto->derivatives) && sizeof($sob_dto->derivatives) > 0;
|
161
|
$item = [];
|
162
|
$item['class'] = [
|
163
|
'derived-unit-item ',
|
164
|
html_class_attribute_ref($sob_dto),
|
165
|
$this->itemCollapsedStateClassAttribute(),
|
166
|
$this->collapsibleItemClassAttribute($has_sub_derivatives),
|
167
|
$this->subItemsClassAttribute($has_sub_derivatives)
|
168
|
];
|
169
|
// data" element of the array is used as the contents of the list item
|
170
|
$item['data'] = [];
|
171
|
$unit_content_markup = '';
|
172
|
if($this->with_details){
|
173
|
$unit_dto_render_array = compose_cdm_specimen_or_observation_dto_details_grid($sob_dto);
|
174
|
$this->applyUnitContentGrid($unit_dto_render_array);
|
175
|
$unit_content_markup = drupal_render($unit_dto_render_array);
|
176
|
}
|
177
|
$item['data'] = $this->applyItemWrapper(
|
178
|
$this->derived_units_tree_node_header($sob_dto)
|
179
|
. $unit_content_markup
|
180
|
, $has_sub_derivatives);
|
181
|
if ($has_sub_derivatives) {
|
182
|
usort($sob_dto->derivatives, 'compare_specimen_or_observation_dtos');
|
183
|
// children are displayed in a nested list.
|
184
|
$item['children'] = $this->derived_units_as_list_items($sob_dto->derivatives);
|
185
|
}
|
186
|
$list_items[] = $item;
|
187
|
}
|
188
|
|
189
|
return $list_items;
|
190
|
}
|
191
|
|
192
|
|
193
|
/**
|
194
|
* @param $unit_dto_render_array
|
195
|
*
|
196
|
* @return mixed
|
197
|
*
|
198
|
* FIXME: merge into compose_cdm_specimen_or_observation_dto_details_grid() again
|
199
|
*/
|
200
|
function applyUnitContentGrid(&$unit_dto_render_array){
|
201
|
$unit_dto_render_array['#prefix'] = '<div class="unit-content derived-unit-details-grid">';
|
202
|
$unit_dto_render_array['#suffix'] = '</div>';
|
203
|
return $unit_dto_render_array;
|
204
|
}
|
205
|
|
206
|
function applyItemWrapper($item_markup, $has_children){
|
207
|
$sub_item_line_class_attribute = $has_children ? ' item-wrapper-with-sub-items' : '';
|
208
|
return '<div class="item-wrapper' . $sub_item_line_class_attribute . '">' // allows to apply the borders between .derived-unit-tree-root and .unit-content
|
209
|
. $item_markup
|
210
|
. '</div>';
|
211
|
}
|
212
|
|
213
|
/**
|
214
|
* @param $sob_dto
|
215
|
*
|
216
|
* @return string
|
217
|
*/
|
218
|
function derived_units_tree_node_header($sob_dto) {
|
219
|
$link = '';
|
220
|
$focused_attribute = '';
|
221
|
$hover_effect_attribute = '';
|
222
|
$collapse_open_icons = '';
|
223
|
$unit_header_wrapper_sub_items_class_attr = '';
|
224
|
if(is_uuid($this->getFocusedUnitUuid()) & $sob_dto->uuid == $this->getFocusedUnitUuid()) {
|
225
|
$focused_attribute = " focused_item";
|
226
|
} else {
|
227
|
$link = cdm_internal_link(path_to_specimen($sob_dto->uuid), NULL);
|
228
|
}
|
229
|
if($this->isWithDetails()){
|
230
|
$hover_effect_attribute = ' unit-label-hover-effect';
|
231
|
}
|
232
|
$icon_link_markup = '';
|
233
|
if($link) {
|
234
|
$icon_link_markup = '<span class="page-link">' . $link . '</span>';
|
235
|
}
|
236
|
$has_sub_derivatives = isset($sob_dto->derivatives) && sizeof($sob_dto->derivatives) > 0;
|
237
|
if($has_sub_derivatives){
|
238
|
if($this->isCollapsible()){
|
239
|
$collapse_open_icons = '<span class="tree-node-symbol tree-node-symbol-collapsible">'
|
240
|
. font_awesome_icon_markup('fa-' . SYMBOL_COLLAPSIBLE_CLOSED)
|
241
|
. '</span>';
|
242
|
} else {
|
243
|
$collapse_open_icons = '<span class="tree-node-symbol">'
|
244
|
. font_awesome_icon_markup('fa-' . SYMBOL_COLLAPSIBLE_OPEN)
|
245
|
. '</span>';
|
246
|
}
|
247
|
}
|
248
|
if($has_sub_derivatives){
|
249
|
$unit_header_wrapper_sub_items_class_attr = ' unit-header-wrapper-with-sub-items';
|
250
|
}
|
251
|
if( $sob_dto->type == 'FieldUnit' ){
|
252
|
if($this->useFieldUnitShortLabel() && isset_not_empty($sob_dto->collectingString)){
|
253
|
$label = $sob_dto->collectingString;
|
254
|
} else {
|
255
|
$label = $sob_dto->label;
|
256
|
}
|
257
|
} else {
|
258
|
$label = $sob_dto->specimenShortTitle;
|
259
|
}
|
260
|
return '<div class="unit-header-wrapper' . $unit_header_wrapper_sub_items_class_attr . $focused_attribute . '"><div class="unit-header"><div class="unit-label' . $hover_effect_attribute .' ">' . $collapse_open_icons . '<span class="symbol">' . $this->symbol_markup($sob_dto) . '</span>' . $label . $icon_link_markup . '</div></div></div>';
|
261
|
}
|
262
|
|
263
|
/**
|
264
|
* @param $sob_dto
|
265
|
*
|
266
|
* @return String
|
267
|
*/
|
268
|
public function symbol_markup($sob_dto) {
|
269
|
if(count($sob_dto->specimenTypeDesignations)){
|
270
|
$base_of_record_symbol = font_awesome_icon_stack([
|
271
|
symbol_for_base_of_record($sob_dto->recordBase->uuid,
|
272
|
[
|
273
|
'class' => ['fas', 'fa-stack-1x'],
|
274
|
'style' => ['--fa-primary-color: red;']
|
275
|
]),
|
276
|
font_awesome_icon_markup('fa-tag',
|
277
|
[
|
278
|
'class' => ['fas', 'fa-rotate-180', 'fa-stack-1x'],
|
279
|
'style' => ['color: red; vertical-align:bottom; text-align:left; font-size:.75em; bottom: -0.35em;']
|
280
|
]
|
281
|
)
|
282
|
]);
|
283
|
} else {
|
284
|
$base_of_record_symbol = symbol_for_base_of_record($sob_dto->recordBase->uuid);
|
285
|
}
|
286
|
return $base_of_record_symbol;
|
287
|
}
|
288
|
|
289
|
}
|