templates
3 months ago
DataHelper.php
3 days ago
ExceptionalElements.php
3 days ago
Preview.php
3 days ago
Utils.php
3 days ago
ExceptionalElements.php
1537 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Preview script helper class for handle exceptional element |
| 4 | * |
| 5 | * @package kirki |
| 6 | */ |
| 7 | |
| 8 | namespace Kirki\Frontend\Preview; |
| 9 | |
| 10 | if ( ! defined( 'ABSPATH' ) ) { |
| 11 | exit; // Exit if accessed directly. |
| 12 | } |
| 13 | |
| 14 | use Kirki\Ajax\Symbol; |
| 15 | use Kirki\HelperFunctions; |
| 16 | |
| 17 | /** |
| 18 | * ExceptionalElements Class |
| 19 | */ |
| 20 | class ExceptionalElements { |
| 21 | /** |
| 22 | * Get this exceptional element |
| 23 | * |
| 24 | * @param array $this_data single element block. |
| 25 | * @param array $attributes single element all attributes. |
| 26 | * @param array $options single element all options. |
| 27 | * @return string HTML markup. |
| 28 | */ |
| 29 | public function get_this_exceptional_element( $this_data, $attributes, $options ) { |
| 30 | switch ( $this_data['name'] ) { |
| 31 | case 'custom-code': { |
| 32 | return $this->custom_code( $this_data, $attributes ); |
| 33 | } |
| 34 | case 'form': { |
| 35 | return $this->form_element( $this_data, $attributes, $options ); |
| 36 | } |
| 37 | case 'map': |
| 38 | case 'google-map': { |
| 39 | return $this->map_element( $this_data, $attributes ); |
| 40 | } |
| 41 | case 'svg': |
| 42 | case 'svg-icon': |
| 43 | { |
| 44 | return $this->svg_and_icon_element( $this_data, $attributes, $options ); |
| 45 | } |
| 46 | case 'textarea': { |
| 47 | return '<textarea ' . $attributes . '></textarea>'; |
| 48 | } |
| 49 | case 'select': { |
| 50 | return $this->select_element( $this_data, $attributes, $options ); |
| 51 | } |
| 52 | case 'section': { |
| 53 | return $this->section_element( $this_data, $attributes, $options ); |
| 54 | } |
| 55 | case 'video': { |
| 56 | return $this->video_element( $this_data, $attributes, $options ); |
| 57 | } |
| 58 | case 'radio-group': { |
| 59 | return $this->radio_group( $this_data, $attributes ); |
| 60 | } |
| 61 | case 'checkbox-element': { |
| 62 | return $this->checkbox_element( $this_data, $attributes, $options ); |
| 63 | } |
| 64 | case 'radio-button': { |
| 65 | return '<input type="radio" ' . $attributes . ' />'; |
| 66 | } |
| 67 | case 'image': { |
| 68 | return $this->image_element( $this_data, $attributes, $options ); |
| 69 | } |
| 70 | case 'link-block': { |
| 71 | return $this->link_block_element( $this_data, $attributes, $options ); |
| 72 | } |
| 73 | |
| 74 | case 'file-upload-inner': { |
| 75 | return $this->file_input_element( $this_data, $attributes, $options ); |
| 76 | } |
| 77 | |
| 78 | case 'file-upload-threshold-text': { |
| 79 | return $this->file_upload_threshold_text( $this_data, $attributes, $options ); |
| 80 | } |
| 81 | |
| 82 | case 'file-upload': { |
| 83 | return $this->file_upload_element( $this_data, $attributes, $options ); |
| 84 | } |
| 85 | case 'slider': |
| 86 | case 'collection': { |
| 87 | $element_name = $this_data['name']; |
| 88 | $properties = $this_data['properties']; |
| 89 | |
| 90 | $dynamic_content = $element_name === 'slider' |
| 91 | ? ( $properties['dynamicSliderContent'] ?? array() ) |
| 92 | : ( $properties['dynamicContent'] ?? array() ); |
| 93 | |
| 94 | if ( ! empty( $dynamic_content['offset'] ) ) { |
| 95 | $options['offset'] = (int) $dynamic_content['offset']; |
| 96 | } |
| 97 | |
| 98 | if ( $element_name === 'slider' ) { |
| 99 | $options['slider_mode'] = $properties['slider']['mode'] ?? 'manual'; // default manual |
| 100 | $options['element_name'] = $element_name; |
| 101 | $slider_mask_id = $this_data['children'][0]; |
| 102 | |
| 103 | if ( $slider_mask_id && isset( $this->data[ $slider_mask_id ] ) ) { |
| 104 | $slider_mask_data = $this->data[ $slider_mask_id ]; |
| 105 | $options['slider_mask_children'] = $slider_mask_data['children'] ?? array(); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | $children = array(); |
| 110 | |
| 111 | if ( empty( $dynamic_content['collectionType'] ) ) { |
| 112 | $dynamic_content['collectionType'] = 'posts'; // default value |
| 113 | } |
| 114 | |
| 115 | $children = $this->construct_items_collection_markup( $dynamic_content, $this_data, $options ); |
| 116 | |
| 117 | return $this->construct_collection_markup( $children, $this_data, $attributes, $element_name, $options ); |
| 118 | } |
| 119 | case 'loading': { |
| 120 | return $this->collection_loading_element( $this_data, $attributes, $options ); |
| 121 | } |
| 122 | case 'terms': // TODO: migrate and remove |
| 123 | case 'users': // TODO: migrate and remove |
| 124 | case 'collection-wrapper': // TODO: migrate and remove |
| 125 | case 'slider_mask': |
| 126 | case 'items': { |
| 127 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 128 | $collection = isset( $options['collection'] ) ? $options['collection'] : array(); |
| 129 | $itemType = isset( $options['itemType'] ) ? $options['itemType'] : 'post'; |
| 130 | $collection_item_id = $this_data['children'][0]; |
| 131 | $slider_mask_children = $this_data['children']; |
| 132 | $slider_mode = $options['slider_mode'] ?? 'manual'; |
| 133 | $is_slider = isset( $options['element_name'] ) && $options['element_name'] === 'slider'; |
| 134 | |
| 135 | $children = array(); |
| 136 | |
| 137 | if ( ! $options ) { |
| 138 | $options = array(); |
| 139 | } |
| 140 | |
| 141 | if ( $is_slider && $slider_mode === 'manual' ) { |
| 142 | foreach ( $slider_mask_children as $key => $child_id ) { |
| 143 | $children[] = $this->recGenHTML( $child_id, $options ); |
| 144 | } |
| 145 | } else { // for collection and slider (dynamic) |
| 146 | foreach ( $collection as $key => $collection_item ) { |
| 147 | $item_index = HelperFunctions::get_current_item_index( $key + 1, $options ); |
| 148 | $options = array_merge( |
| 149 | $options, |
| 150 | array( |
| 151 | 'itemType' => $itemType, |
| 152 | $itemType => $collection_item, |
| 153 | 'item_index' => $item_index, |
| 154 | ) |
| 155 | ); |
| 156 | |
| 157 | $children[] = HelperFunctions::rec_update_data_id_then_return_new_html( $this->data, $this->style_blocks, $collection_item_id, $options, ( $key === 0 ) ); |
| 158 | }; |
| 159 | } |
| 160 | |
| 161 | return $this->get_template( |
| 162 | 'items', |
| 163 | array( |
| 164 | 'attributes' => $attributes, |
| 165 | 'children' => $children, |
| 166 | 'tag' => $tag, |
| 167 | ) |
| 168 | ); |
| 169 | } |
| 170 | |
| 171 | case 'pagination': { |
| 172 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 173 | $markup = ''; |
| 174 | $show_pagination = isset( $options['pagination'] ) ? $options['pagination'] : true; |
| 175 | $pagination_type = isset( $options['pagination_type'] ) ? $options['pagination_type'] : 'numeric'; |
| 176 | $offset = isset( $options['offset'] ) ? (int) $options['offset'] : 0; |
| 177 | |
| 178 | if ( $show_pagination ) { |
| 179 | $collection_count = 0; |
| 180 | |
| 181 | if ( isset( $options['itemType'], $options['collection_count'] ) ) { |
| 182 | $collection_count = $options['collection_count']; |
| 183 | } |
| 184 | |
| 185 | $current_page = isset( $options['page_no'] ) ? $options['page_no'] : 1; |
| 186 | $items_per_page = isset( $options['items_per_page'] ) ? $options['items_per_page'] : 3; |
| 187 | $total_pages = $collection_count ? (int) ceil( ( $collection_count - $offset ) / $items_per_page ) : 0; |
| 188 | // $pagination_item_id = $this_data['children'][0]; |
| 189 | $pagination_item_id = isset( $this_data['children'][0] ) ? $this_data['children'][0] : ''; |
| 190 | |
| 191 | $children = array(); |
| 192 | |
| 193 | // pagination type: numeric or infinite_scroll |
| 194 | if ( $pagination_type === 'numeric' ) { |
| 195 | $start = 1; |
| 196 | $end = $total_pages; |
| 197 | |
| 198 | /** |
| 199 | * custom for large pagination start |
| 200 | */ |
| 201 | // Determine the range to display |
| 202 | $range = 10; |
| 203 | $half_range = floor( $range / 2 ); |
| 204 | |
| 205 | // Calculate new $start and $end |
| 206 | $start = max( 1, $current_page - $half_range ); |
| 207 | $end = min( $total_pages, $current_page + $half_range ); |
| 208 | |
| 209 | // Adjust $start and $end if at the boundaries |
| 210 | if ( $end - $start < $range - 1 ) { |
| 211 | if ( $start == 1 ) { |
| 212 | $end = min( $start + $range - 1, $total_pages ); |
| 213 | } else { |
| 214 | $start = max( $end - $range + 1, 1 ); |
| 215 | } |
| 216 | } |
| 217 | /** |
| 218 | * custom for large pagination end |
| 219 | */ |
| 220 | |
| 221 | if ( $end > 1 ) { |
| 222 | for ( $i = $start; $i <= $end; $i++ ) { |
| 223 | $options = array( |
| 224 | 'page_number' => $i, |
| 225 | 'current_page' => $current_page === $i, |
| 226 | ); |
| 227 | $children[] = HelperFunctions::rec_update_data_id_then_return_new_html( $this->data, $this->style_blocks, $pagination_item_id, $options, ( $i === $start ) ); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | $markup = $this->get_template( |
| 232 | 'pagination', |
| 233 | array( |
| 234 | 'attributes' => $attributes, |
| 235 | 'children' => $children, |
| 236 | 'tag' => $tag, |
| 237 | ) |
| 238 | ); |
| 239 | } elseif ( $pagination_type === 'infinite_scroll' ) { |
| 240 | $markup = $this->get_template( |
| 241 | 'pagination', |
| 242 | array( |
| 243 | 'attributes' => $attributes . ' data-total-pages="' . $total_pages . '" data-current-page="' . $current_page . '"' . ' data-pagination-type="' . $pagination_type . '"' . 'style="height:1px "', |
| 244 | 'children' => $children, |
| 245 | 'tag' => $tag, |
| 246 | ) |
| 247 | ); |
| 248 | } elseif ( $pagination_type === 'load_more' && $current_page !== $total_pages ) { |
| 249 | $children = isset( $this_data['children'] ) ? $this_data['children'] : array(); |
| 250 | |
| 251 | $child_markup = $this->construct_children_markup( $children, $options ); |
| 252 | |
| 253 | $attr = $attributes . ' data-total-pages="' . $total_pages . '" data-current-page="' . $current_page . '"' . ' data-pagination-type="' . $pagination_type . '"'; |
| 254 | return "<$tag $attr> |
| 255 | $child_markup |
| 256 | </$tag>"; |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | return $markup; |
| 261 | } |
| 262 | |
| 263 | case 'pagination-item': { |
| 264 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 265 | $current_page = isset( $options['current_page'] ) ? $options['current_page'] : false; |
| 266 | $page_number = isset( $options['page_number'] ) ? $options['page_number'] : false; |
| 267 | |
| 268 | $children = array(); |
| 269 | |
| 270 | foreach ( $this_data['children'] as $child ) { |
| 271 | $children[] = $this->recGenHTML( |
| 272 | $child, |
| 273 | array( |
| 274 | 'page_number' => $page_number, |
| 275 | ) |
| 276 | ); |
| 277 | } |
| 278 | |
| 279 | return $this->get_template( |
| 280 | 'pagination-item', |
| 281 | array( |
| 282 | 'attributes' => $attributes, |
| 283 | 'children' => $children, |
| 284 | 'current_page' => $current_page, |
| 285 | 'page_number' => $page_number, |
| 286 | 'tag' => $tag, |
| 287 | ) |
| 288 | ); |
| 289 | } |
| 290 | |
| 291 | case 'pagination-number': { |
| 292 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'span'; |
| 293 | $page_number = isset( $options['page_number'] ) ? $options['page_number'] : 1; |
| 294 | |
| 295 | return $this->get_template( |
| 296 | 'pagination-number', |
| 297 | array( |
| 298 | 'attributes' => $attributes, |
| 299 | 'page_number' => $page_number, |
| 300 | 'tag' => $tag, |
| 301 | ) |
| 302 | ); |
| 303 | } |
| 304 | |
| 305 | case 'common': { |
| 306 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 307 | $type = isset( $this_data['properties']['type'] ) ? $this_data['properties']['type'] : false; |
| 308 | |
| 309 | if ( $type ) { |
| 310 | $attributes .= ' data-kirki-type="' . $type . '"'; |
| 311 | } |
| 312 | |
| 313 | $children = isset( $this_data['children'] ) ? $this_data['children'] : array(); |
| 314 | |
| 315 | $child_markup = $this->construct_children_markup( $children, $options ); |
| 316 | |
| 317 | return "<$tag $attributes> |
| 318 | $child_markup |
| 319 | </$tag>"; |
| 320 | } |
| 321 | |
| 322 | case 'symbol': { |
| 323 | return $this->generate_symbol_html( $this_data, $attributes, $options ); |
| 324 | } |
| 325 | case 'popup-body': { |
| 326 | return $this->popup_element( $this_data, $attributes, $options ); |
| 327 | } |
| 328 | |
| 329 | case 'button': { |
| 330 | return $this->button_element( $this_data, $attributes, $options ); |
| 331 | } |
| 332 | |
| 333 | case 'navigation': { |
| 334 | return $this->navigation_element( $this_data, $attributes, $options ); |
| 335 | } |
| 336 | |
| 337 | case 'navigation-item': { |
| 338 | return $this->navigation_item_element($this_data, $attributes, $options); |
| 339 | } |
| 340 | |
| 341 | case 'navigation-items': { |
| 342 | return $this->navigation_items_element( $this_data, $attributes, $options ); |
| 343 | } |
| 344 | |
| 345 | case 'slider_nav':{ |
| 346 | return $this->slider_nav_element( $this_data, $attributes, $options ); |
| 347 | } |
| 348 | case 'tabs':{ |
| 349 | return $this->tabs_element( $this_data, $attributes, $options ); |
| 350 | } |
| 351 | case 'tab':{ |
| 352 | return $this->tab_element( $this_data, $attributes, $options ); |
| 353 | } |
| 354 | case 'tab_pane':{ |
| 355 | return $this->tab_pane_element( $this_data, $attributes, $options ); |
| 356 | } |
| 357 | case 'tab_content': |
| 358 | case 'tab_menu':{ |
| 359 | return $this->tab_menu_and_content_element( $this_data, $attributes, $options ); |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /** |
| 365 | * Generate collection loading element markup |
| 366 | * |
| 367 | * @param array $this_data single element block. |
| 368 | * @param array $attributes single element all attributes. |
| 369 | * @param array $options single element all options. |
| 370 | * @return string HTML markup. |
| 371 | */ |
| 372 | private function collection_loading_element( $this_data, $attributes, $options ) { |
| 373 | $tag = isset( $this_data['properties'], $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 374 | |
| 375 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 376 | |
| 377 | return "<$tag $attributes kirki-collection=\"loading\" data-element_hide=\"true\"> |
| 378 | $children_markup |
| 379 | </$tag>"; |
| 380 | } |
| 381 | |
| 382 | /** |
| 383 | * Generate section element markup |
| 384 | * |
| 385 | * @param array $this_data single element block. |
| 386 | * @param array $attributes single element all attributes. |
| 387 | * @param array $options single element all options. |
| 388 | * @return string HTML markup. |
| 389 | */ |
| 390 | private function section_element( $this_data, $attributes, $options ) { |
| 391 | $id = isset( $this_data['id'] ) ? $this_data['id'] : ''; |
| 392 | if ( $id ) { |
| 393 | $id = $this->get_unique_section_id_from_title( $id ); |
| 394 | } |
| 395 | |
| 396 | $tag = isset( $this_data['properties'], $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'a'; |
| 397 | |
| 398 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 399 | |
| 400 | return "<$tag $attributes id=\"$id\"> |
| 401 | $children_markup |
| 402 | </$tag>"; |
| 403 | } |
| 404 | |
| 405 | private function navigation_element( $this_data, $attributes, $options ) { |
| 406 | $tag = isset( $this_data['properties'], $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'a'; |
| 407 | |
| 408 | $hamburger = isset($this_data['properties']['navigation']['hamburger']) ? $this_data['properties']['navigation']['hamburger'] : false; |
| 409 | |
| 410 | if ( ! is_array( $options ) ) { |
| 411 | $options = array(); |
| 412 | } |
| 413 | |
| 414 | if ( ! $options ) { |
| 415 | $options = array(); |
| 416 | } |
| 417 | $options = array_merge( |
| 418 | $options, |
| 419 | array( |
| 420 | 'navigation' => array( |
| 421 | 'id' => $this_data['id'], |
| 422 | 'hamburger' => $hamburger, |
| 423 | 'showNavigationChildrenOn' => isset($this_data['properties']['navigation']['showNavigationChildrenOn']) ? $this_data['properties']['navigation']['showNavigationChildrenOn'] : 'hover', |
| 424 | ), |
| 425 | ) |
| 426 | ); |
| 427 | |
| 428 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 429 | |
| 430 | return "<$tag $attributes> |
| 431 | $children_markup |
| 432 | </$tag>"; |
| 433 | } |
| 434 | |
| 435 | private function navigation_item_element($this_data, $attributes, $options) |
| 436 | { |
| 437 | $tag = isset($this_data['properties'], $this_data['properties']['tag']) ? $this_data['properties']['tag'] : 'a'; |
| 438 | |
| 439 | $children_markup = $this->construct_children_markup(isset($this_data['children']) ? $this_data['children'] : array(), $options); |
| 440 | |
| 441 | $extra_attributes = ''; |
| 442 | |
| 443 | $show_on = 'hover'; |
| 444 | |
| 445 | // check showNavigationChildrenOn is hover or click or always then add kirki-navigation-item-trigger-on='hover'/'click'/'always' |
| 446 | if (isset($this_data['properties']['navigationItem']['showNavigationChildrenOn'])) { |
| 447 | $show_on = $this_data['properties']['navigationItem']['showNavigationChildrenOn']; |
| 448 | $extra_attributes .= ' kirki-navigation-item-trigger-on="' . $show_on . '"'; |
| 449 | } else if (isset($options['navigation']['showNavigationChildrenOn'], $options['navigation']['hamburger']) && $options['navigation']['hamburger']) { |
| 450 | $show_on = $options['navigation']['showNavigationChildrenOn']; |
| 451 | $extra_attributes .= ' kirki-navigation-item-trigger-on="' . $show_on . '"'; |
| 452 | } else { |
| 453 | $extra_attributes .= ' kirki-navigation-item-trigger-on="hover"'; |
| 454 | } |
| 455 | |
| 456 | if ('always' !== $show_on) { |
| 457 | $extra_attributes .= ' kirki-navigation-item-dismiss-on="' . ($this_data['properties']['navigationItem']['hideNavigationChildrenOn'] ?? 'mouseleave') . '"'; |
| 458 | } |
| 459 | |
| 460 | if (!$options) { |
| 461 | $options = array(); |
| 462 | } |
| 463 | |
| 464 | // add if kirki-navigation="nav-item" has in $this_data['properties']['attributes'] then set inside_nav_item = true |
| 465 | $options = array_merge( |
| 466 | $options, |
| 467 | array( |
| 468 | 'inside_nav_item' => isset($this_data['properties']['attributes']['kirki-navigation']) && $this_data['properties']['attributes']['kirki-navigation'] === 'nav-item', |
| 469 | ) |
| 470 | ); |
| 471 | |
| 472 | $children_markup = $this->construct_children_markup(isset($this_data['children']) ? $this_data['children'] : array(), $options); |
| 473 | |
| 474 | return "<$tag $attributes $extra_attributes> |
| 475 | $children_markup |
| 476 | </$tag>"; |
| 477 | } |
| 478 | |
| 479 | private function navigation_items_element($this_data, $attributes, $options) |
| 480 | { |
| 481 | |
| 482 | $tag = isset($this_data['properties'], $this_data['properties']['tag']) ? $this_data['properties']['tag'] : 'a'; |
| 483 | |
| 484 | $extra_attr = isset($options['inside_navigation']) && $options['inside_navigation'] ? 'kirki-navigation-hide="true"' : ''; |
| 485 | |
| 486 | if (isset($options['navigation']['hamburger']) && $options['navigation']['hamburger']) { |
| 487 | $extra_attr .= ' kirki-navigation-type="close"'; |
| 488 | } |
| 489 | |
| 490 | if (!$options) { |
| 491 | $options = array(); |
| 492 | } |
| 493 | $options = array_merge( |
| 494 | $options, |
| 495 | array( |
| 496 | 'inside_navigation' => true, |
| 497 | ) |
| 498 | ); |
| 499 | |
| 500 | $children_markup = $this->construct_children_markup(isset($this_data['children']) ? $this_data['children'] : array(), $options); |
| 501 | // check it has kirki-menu-wrapper: true as attribute |
| 502 | // if (isset($this_data['properties']['attributes']['kirki-menu-wrapper']) && $this_data['properties']['attributes']['kirki-menu-wrapper'] === 'true') { |
| 503 | if (isset($options['inside_nav_item']) && $options['inside_nav_item'] === true) { |
| 504 | // Match the content inside class="..." and data-kirki="..." |
| 505 | preg_match('/class="([^"]+)"/', $attributes, $classMatch); |
| 506 | preg_match('/data-kirki="([^"]+)"/', $attributes, $dataMatch); |
| 507 | |
| 508 | $class = $classMatch[1] ?? null; |
| 509 | $data_kirki = $dataMatch[1] ?? null; |
| 510 | |
| 511 | return " |
| 512 | <div kirki-menu-wrapper-div='true'> |
| 513 | <$tag class='$class' data-kirki='$data_kirki'> |
| 514 | $children_markup |
| 515 | </$tag> |
| 516 | </div> |
| 517 | "; |
| 518 | } else { |
| 519 | return "<$tag $attributes $extra_attr> |
| 520 | $children_markup |
| 521 | </$tag>"; |
| 522 | } |
| 523 | |
| 524 | } |
| 525 | |
| 526 | private function form_element( $this_data, $attributes, $options ) { |
| 527 | $properties = $this_data['properties']; |
| 528 | $post_id = HelperFunctions::get_post_id_if_possible_from_url(); |
| 529 | $form_id = $this_data['id']; |
| 530 | $post_data = $form_id . '|' . $post_id; |
| 531 | $form_data = $post_data . '|' . wp_hash( $post_data ); |
| 532 | // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode |
| 533 | $form_id_base64 = base64_encode( base64_encode( $form_data ) ); |
| 534 | |
| 535 | $form_nonce_field = wp_nonce_field( 'wp_rest', '_wpnonce', true, false ); |
| 536 | |
| 537 | if ( ! $options ) { |
| 538 | $options = array(); |
| 539 | } |
| 540 | |
| 541 | $options = array_merge( |
| 542 | $options, |
| 543 | array( |
| 544 | 'form' => array( |
| 545 | 'id' => $form_id, |
| 546 | ), |
| 547 | ) |
| 548 | ); |
| 549 | |
| 550 | $form_children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 551 | |
| 552 | if ( isset( $properties['form']['type'] ) && $properties['form']['type'] !== 'external' ) { |
| 553 | $attributes = $this->getAllAttributes( |
| 554 | $this_data, |
| 555 | array( |
| 556 | 'action' => false, |
| 557 | 'method' => false, |
| 558 | 'rest' => true, |
| 559 | ), |
| 560 | ); |
| 561 | } |
| 562 | |
| 563 | return "<form $attributes> |
| 564 | <input type=\"hidden\" name=\"_kirki_form\" value=\"$form_id_base64\" /> |
| 565 | $form_nonce_field |
| 566 | $form_children_markup |
| 567 | </form>"; |
| 568 | } |
| 569 | |
| 570 | private function select_element( $this_data, $attributes, $options ) { |
| 571 | $properties = $this_data['properties']; |
| 572 | $select_options = isset( $properties['options']['list'] ) ? $properties['options']['list'] : array(); |
| 573 | $selected = isset( $properties['options']['selectedOption'] ) ? $properties['options']['selectedOption'] : ''; |
| 574 | $html = '<select ' . $attributes . '>'; |
| 575 | foreach ( $select_options as $option ) { |
| 576 | $html .= "<option value='"; |
| 577 | $html .= $option['value'] . "'"; |
| 578 | $html .= $selected === $option['value'] ? ' selected' : ''; |
| 579 | $html .= '>'; |
| 580 | $html .= $option['contents']; |
| 581 | $html .= '</option>'; |
| 582 | } |
| 583 | $html .= '</select>'; |
| 584 | |
| 585 | return $html; |
| 586 | } |
| 587 | |
| 588 | /** |
| 589 | * Generate checkbox element markup |
| 590 | * |
| 591 | * @param array $this_data single element block. |
| 592 | * @param array $attributes single element all attributes. |
| 593 | * @param array $options single element all options. |
| 594 | * @return string HTML markup. |
| 595 | */ |
| 596 | private function checkbox_element( $this_data, $attributes, $options ) { |
| 597 | $relation_type = isset( $options['relation_type'] ) ? $options['relation_type'] : 'posts'; |
| 598 | if ( ! isset( $options['form'] ) ) { |
| 599 | // Start: Filter functionality |
| 600 | if ( $relation_type === 'posts' ) { |
| 601 | $checked_ids = isset( $options['selected_post_ids'] ) ? $options['selected_post_ids'] : array(); |
| 602 | $checked = in_array( (string) $options['post']->ID, $checked_ids, true ); |
| 603 | |
| 604 | if ( $checked ) { |
| 605 | $attributes = 'checked ' . $attributes; |
| 606 | } |
| 607 | |
| 608 | $attributes = "name='cm_post' value='" . $options['post']->ID . "' " . $attributes; |
| 609 | } elseif ( $relation_type === 'terms' ) { |
| 610 | $taxonomy = $options['term']['taxonomy']; |
| 611 | $term_id = $options['term']['term_id']; |
| 612 | |
| 613 | $checked_ids = isset( $options['selected_taxonomies'] ) ? $options['selected_taxonomies'] : array(); |
| 614 | $checked = in_array( (string) $term_id, $checked_ids, true ); |
| 615 | |
| 616 | if ( $checked ) { |
| 617 | $attributes = 'checked ' . $attributes; |
| 618 | } |
| 619 | |
| 620 | $attributes = "name='$taxonomy' value='$term_id' " . $attributes; |
| 621 | } |
| 622 | } |
| 623 | // End: Filter functionality |
| 624 | |
| 625 | return '<input type="checkbox" ' . $attributes . ' />'; |
| 626 | } |
| 627 | |
| 628 | private function link_block_element( $this_data, $attributes, $options ) { |
| 629 | $href = $this->get_href_value( $this_data, $options ); |
| 630 | |
| 631 | $preload_link = ''; |
| 632 | |
| 633 | if ( $href ) { |
| 634 | $attributes = preg_replace( '/href="([^"]+")/i', '', $attributes ); |
| 635 | |
| 636 | // check if this link is active |
| 637 | $attributes = $this->add_link_active_class( $href, $attributes, $this_data, $options ); |
| 638 | |
| 639 | $preload_link = $this->get_preload_link( $href, $this_data ); |
| 640 | } |
| 641 | |
| 642 | return '<a ' . $attributes . ' ' . ' href="' . $href . '" >' . $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ) . '</a>' . $preload_link; |
| 643 | } |
| 644 | |
| 645 | private function button_element( $this_data, $attributes, $options ) { |
| 646 | $href = $this->get_href_value( $this_data, $options ); |
| 647 | $preload_link = ''; |
| 648 | |
| 649 | if ( $href ) { |
| 650 | $attributes = preg_replace( '/href="([^"]+")/i', '', $attributes ); |
| 651 | |
| 652 | // check if this link is active |
| 653 | $attributes = $this->add_link_active_class( $href, $attributes, $this_data, $options ); |
| 654 | |
| 655 | $preload_link = $this->get_preload_link( $href, $this_data ); |
| 656 | } |
| 657 | |
| 658 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 659 | $tag = isset( $this_data['properties'], $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'button'; |
| 660 | if ( $href ) { |
| 661 | $tag = 'a'; |
| 662 | } |
| 663 | |
| 664 | return "<$tag $attributes href=\"$href\"> |
| 665 | $children_markup |
| 666 | </$tag> |
| 667 | $preload_link"; |
| 668 | } |
| 669 | |
| 670 | private function svg_and_icon_element( $this_data, $attributes, $options ) { |
| 671 | $properties = $this_data['properties']; |
| 672 | $svg = isset( $properties['svgOuterHtml'] ) ? $properties['svgOuterHtml'] : ''; |
| 673 | return str_replace( '<svg', "<svg $attributes", $svg ); |
| 674 | } |
| 675 | |
| 676 | /** |
| 677 | * Construct children markup |
| 678 | * |
| 679 | * @param array $children single element all childrens. |
| 680 | * @param array $options single element all options. |
| 681 | * @return string HTML markup. |
| 682 | */ |
| 683 | private function construct_children_markup( $children, $options ) { |
| 684 | $markup = ''; |
| 685 | if ( isset( $children ) && is_array( $children ) ) { |
| 686 | foreach ( $children as $child ) { |
| 687 | $markup .= $this->recGenHTML( $child, $options ); |
| 688 | } |
| 689 | } |
| 690 | return $markup; |
| 691 | } |
| 692 | private function construct_items_collection_markup( $dynamic_content, $this_data, $options ) { |
| 693 | $collection_type = isset( $dynamic_content['collectionType'] ) ? $dynamic_content['collectionType'] : 'posts'; |
| 694 | $show_pagination = isset( $dynamic_content['pagination'] ) ? $dynamic_content['pagination'] : true; |
| 695 | $pagination_type = isset( $dynamic_content['pagination_type'] ) ? $dynamic_content['pagination_type'] : 'numeric'; |
| 696 | |
| 697 | if ( ! $options ) { |
| 698 | $options = array(); |
| 699 | } |
| 700 | |
| 701 | $items_data = Utils::get_items_data_from_dynamic_contents( $dynamic_content, $options ); |
| 702 | |
| 703 | $data = $items_data['data']; |
| 704 | $pagination = $items_data['pagination']; |
| 705 | $itemType = $items_data['itemType']; |
| 706 | |
| 707 | $additional_options = array(); |
| 708 | |
| 709 | // START: Filter functionality |
| 710 | if ( $collection_type === 'posts' && isset( $dynamic_content['post_type'] ) && $dynamic_content['post_type'] ) { |
| 711 | if ( isset( $_GET['post'][ $dynamic_content['post_type'] ] ) && is_array( $_GET['post'][ $dynamic_content['post_type'] ] ) ) { |
| 712 | $additional_options['selected_post_ids'] = $_GET['post'][ $dynamic_content['post_type'] ]; |
| 713 | } |
| 714 | } elseif ( $collection_type === 'terms' ) { |
| 715 | if ( isset( $_GET['taxonomy'][ $dynamic_content['taxonomy'] ] ) && is_array( $_GET['taxonomy'][ $dynamic_content['taxonomy'] ] ) ) { |
| 716 | $additional_options['selected_taxonomies'] = $_GET['taxonomy'][ $dynamic_content['taxonomy'] ]; |
| 717 | } |
| 718 | } |
| 719 | |
| 720 | $additional_options['relation_type'] = $collection_type; |
| 721 | // END: Filter functionality |
| 722 | |
| 723 | $options = array_merge( |
| 724 | $options, |
| 725 | $additional_options |
| 726 | ); |
| 727 | |
| 728 | $children = array(); |
| 729 | |
| 730 | foreach ( $this_data['children'] as $child ) { |
| 731 | |
| 732 | if ( count( $data ) > 0 ) { |
| 733 | if ( isset( $this->data[ $child ] ) && $this->data[ $child ]['name'] === 'empty' ) { |
| 734 | continue; |
| 735 | } |
| 736 | } elseif ( count( $data ) === 0 ) { |
| 737 | if ( isset( $this->data[ $child ] ) && ( $this->data[ $child ]['name'] === 'pagination' || $this->data[ $child ]['name'] === 'items' ) ) { |
| 738 | continue; |
| 739 | } |
| 740 | } |
| 741 | |
| 742 | $children[] = $this->recGenHTML( |
| 743 | $child, |
| 744 | array_merge( |
| 745 | $options, |
| 746 | array( |
| 747 | 'collection' => $data, |
| 748 | 'collection_count' => $pagination['total_count'] ?? 0, |
| 749 | 'items_per_page' => $pagination['per_page'] ?? 0, |
| 750 | 'page_no' => $pagination['current_page'] ?? 1, |
| 751 | 'pagination' => $show_pagination, |
| 752 | 'itemType' => $itemType, |
| 753 | 'pagination_type' => $pagination_type, |
| 754 | 'inside_collection' => true |
| 755 | ) |
| 756 | ) |
| 757 | ); |
| 758 | } |
| 759 | |
| 760 | return $children; |
| 761 | } |
| 762 | |
| 763 | |
| 764 | /** |
| 765 | * Construct collection markup |
| 766 | * |
| 767 | * @param array $collection single element collection data. |
| 768 | * @param array $this_data single element. |
| 769 | * @param array $attributes single element all attributes. |
| 770 | * @return string HTML markup. |
| 771 | */ |
| 772 | private function construct_collection_markup( $children, $this_data, $attributes, $element_name = 'collection', $options=[] ) { |
| 773 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 774 | |
| 775 | $collection_info = $this->get_collection_info($options, $this_data); |
| 776 | |
| 777 | if ( is_array( $children ) ) { |
| 778 | return $this->get_template( |
| 779 | 'collection', |
| 780 | array( |
| 781 | 'data' => $collection_info, |
| 782 | 'attributes' => $attributes, |
| 783 | 'children' => $children, |
| 784 | 'tag' => $tag, |
| 785 | ) |
| 786 | ); |
| 787 | } else { |
| 788 | return ''; |
| 789 | } |
| 790 | } |
| 791 | |
| 792 | public function get_collection_info($options, $this_data) { |
| 793 | $collection_info = array( |
| 794 | 'post_id' => isset($options['post']) ? $options['post']->ID : false, |
| 795 | 'collection_data_id' => isset($this_data['original_id']) ? $this_data['original_id'] :$this_data['id'] |
| 796 | ); |
| 797 | if(isset($options['kirki_template_id']) && $options['kirki_template_id']) { |
| 798 | $collection_info['post_id'] = $options['kirki_template_id']; |
| 799 | } |
| 800 | if(isset($options['inside_symbol']) && $options['inside_symbol'] === true){ |
| 801 | $collection_info['post_id'] = $options['symbol_id']; |
| 802 | } |
| 803 | return $collection_info; |
| 804 | } |
| 805 | |
| 806 | /** |
| 807 | * Generate custom code markup |
| 808 | * |
| 809 | * @param array $this_data single element block. |
| 810 | * @param array $attributes single element all attributes. |
| 811 | * @return string HTML markup. |
| 812 | */ |
| 813 | private function custom_code( $this_data, $attributes ) { |
| 814 | $properties = $this_data['properties']; |
| 815 | if ( isset( $properties['content'] ) ) { |
| 816 | if ( isset( $properties['data-type'] ) && $properties['data-type'] === 'url' ) { |
| 817 | return '<div ' . $attributes . '> |
| 818 | <iframe |
| 819 | src="' . $properties['content'] . '" |
| 820 | title="' . $this_data['id'] . '" |
| 821 | allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" |
| 822 | style="width:100%;height:100%;" |
| 823 | ></iframe> |
| 824 | </div>'; |
| 825 | } else { |
| 826 | return '<div ' . $attributes . '>' . $properties['content'] . '</div>'; |
| 827 | } |
| 828 | } |
| 829 | return ''; |
| 830 | } |
| 831 | |
| 832 | /** |
| 833 | * Generate Map element markup |
| 834 | * |
| 835 | * @param array $this_data single element block. |
| 836 | * @param array $attributes single element all attributes. |
| 837 | * @return string HTML markup. |
| 838 | */ |
| 839 | private function map_element( $this_data, $attributes ) { |
| 840 | $properties = isset( $this_data['properties']['map'] ) ? $this_data['properties']['map'] : false; |
| 841 | if ( ! $properties ) { |
| 842 | return ''; |
| 843 | } |
| 844 | return '<div ' . $attributes . '></div>'; |
| 845 | } |
| 846 | |
| 847 | /** |
| 848 | * Generate Video element markup |
| 849 | * |
| 850 | * @param array $this_data single element block. |
| 851 | * @param array $attributes single element all attributes. |
| 852 | * @return string HTML markup. |
| 853 | */ |
| 854 | private function video_element( $this_data, $attributes, $options ) { |
| 855 | $properties = $this_data['properties']; |
| 856 | $name = $properties['attributes']['name']; |
| 857 | $src = $properties['attributes']['src']; |
| 858 | $scale = isset( $properties['scale'] ) ? $properties['scale'] : 'cover'; |
| 859 | $aspectRatio = isset( $properties['aspectRatio'] ) ? $properties['aspectRatio'] : '16 / 9'; |
| 860 | $type = $properties['attributes']['type']; |
| 861 | $controls = $properties['attributes']['controls']; |
| 862 | $play_inline = isset( $properties['attributes']['playInline'] ) ? $properties['attributes']['playInline'] : true; |
| 863 | $duration = isset( $properties['attributes']['duration'] ) ? $properties['attributes']['duration'] : 0; |
| 864 | $start_time = $properties['attributes']['startTime']; |
| 865 | $end_time = isset( $properties['attributes']['endTime'] ) ? $properties['attributes']['endTime'] : $duration; |
| 866 | $span_attr_string = $this->getAllAttributes( |
| 867 | $this_data, |
| 868 | array( |
| 869 | 'class' => true, |
| 870 | 'data-kirki' => true, |
| 871 | 'rest' => false, |
| 872 | ), |
| 873 | ); |
| 874 | $dynamic_content = isset( $properties['dynamicContent'] ) ? $properties['dynamicContent'] : false; |
| 875 | |
| 876 | if ( isset( $this_data['properties']['attributes']['muted'] ) && $this_data['properties']['attributes']['muted'] === false ) { |
| 877 | unset( $this_data['properties']['attributes']['muted'] ); |
| 878 | } |
| 879 | |
| 880 | $video_attr_string = $this->getAllAttributes( |
| 881 | $this_data, |
| 882 | array( |
| 883 | 'class' => false, |
| 884 | 'data-kirki' => false, |
| 885 | 'src' => false, |
| 886 | 'autoPlay' => false, |
| 887 | 'controls' => false, |
| 888 | 'dataVideoPlayListener' => false, |
| 889 | 'rest' => true, |
| 890 | ), |
| 891 | ); |
| 892 | |
| 893 | if ( $play_inline ) { |
| 894 | $video_attr_string .= ' playsinline'; |
| 895 | } |
| 896 | |
| 897 | $poster = ''; |
| 898 | if ( isset( $properties['thumbnail'], $properties['thumbnail']['status'] ) && $properties['thumbnail']['status'] ) { |
| 899 | $poster = isset( $properties['thumbnail'], $properties['thumbnail']['url'] ) ? $properties['thumbnail']['url'] : null; |
| 900 | } |
| 901 | |
| 902 | $video_src = ''; |
| 903 | if ( $dynamic_content ) { |
| 904 | // TODO: Need to get dynamic course video or image url for tutor lms using hook. |
| 905 | if ( isset( $options['itemType'] ) ) { |
| 906 | if ( $options['itemType'] === 'post' ) { |
| 907 | if ( $options['post']->{$dynamic_content['value']} ) { |
| 908 | $video_obj = $options['post']->{$dynamic_content['value']}; |
| 909 | |
| 910 | if ( isset( $video_obj['url'] ) ) { |
| 911 | $video_src = $video_obj['url']; |
| 912 | } |
| 913 | } else { |
| 914 | $video_obj = HelperFunctions::get_post_dynamic_content( $dynamic_content['value'], isset( $options['post'] ) ? $options['post'] : null ); |
| 915 | |
| 916 | if ( isset( $video_obj['url'] ) ) { |
| 917 | $video_src = $video_obj['url']; |
| 918 | } |
| 919 | } |
| 920 | } |
| 921 | } else { |
| 922 | $video_obj = HelperFunctions::get_post_dynamic_content( $dynamic_content['value'], isset( $options['post'] ) ? $options['post'] : null ); |
| 923 | |
| 924 | if ( isset( $video_obj['url'] ) ) { |
| 925 | $video_src = $video_obj['url']; |
| 926 | } |
| 927 | } |
| 928 | } |
| 929 | |
| 930 | // if no dynamic video src then check original source for fallback video url |
| 931 | if ( ! $video_src && ! $src ) { |
| 932 | return ''; |
| 933 | } else { |
| 934 | $src = $video_src ? $video_src : $src; |
| 935 | } |
| 936 | |
| 937 | $video_url_type = $this->video_type( $src ); |
| 938 | |
| 939 | if ( $video_url_type === 'youtube' ) { |
| 940 | $video_src = $this->get_youtube_embed_url( $src ) . '?controls=' . $controls . '&start=' . $start_time . '&end=' . $end_time; |
| 941 | } elseif ( $video_url_type === 'vimeo' ) { |
| 942 | $video_src = $this->get_vimeo_embed_url( $src ) . '?controls=' . $controls . '&start=' . $start_time . '&end=' . $end_time; |
| 943 | } elseif ( $video_url_type === 'tiktok' ) { |
| 944 | $video_src = $this->get_tiktok_embed_url( $src ) . '?controls=' . $controls . '&start=' . $start_time . '&end=' . $end_time; |
| 945 | } else { |
| 946 | $video_src = $src . '#t=' . $start_time . ',' . $duration; |
| 947 | } |
| 948 | |
| 949 | $html = '<span ' . $span_attr_string . '>'; |
| 950 | if ( $video_url_type === 'youtube' || $video_url_type === 'vimeo' || $video_url_type === 'tiktok' ) { |
| 951 | $html .= '<iframe height="100%" width="100%" title="' . $name . '" src="' . $video_src . '" style="aspect-ratio: ' . $aspectRatio . ';" ></iframe>'; |
| 952 | } else { |
| 953 | if ( isset( $properties['attributes']['lazy'] ) && $properties['attributes']['lazy'] ) { |
| 954 | // `data-src` is used in `source` tag to lazy load the video using JS. Check JS preview script for videos. |
| 955 | $html .= '<video' . $video_attr_string . ' style="object-fit: ' . $scale . '; aspect-ratio: ' . $aspectRatio . ';" poster="' . $poster . '"> |
| 956 | <source data-src="' . $video_src . '" type="' . $type . '"></source></video>'; |
| 957 | } else { |
| 958 | $html .= '<video' . $video_attr_string . ' style="object-fit: ' . $scale . '; aspect-ratio: ' . $aspectRatio . ';" poster="' . $poster . '"> |
| 959 | <source src="' . $video_src . '" type="' . $type . '"></source></video>'; |
| 960 | } |
| 961 | } |
| 962 | $html .= '</span>'; |
| 963 | return $html; |
| 964 | } |
| 965 | |
| 966 | /** |
| 967 | * Generate Video element markup |
| 968 | * |
| 969 | * @param array $this_data single element block. |
| 970 | * @param array $attributes single element all attributes. |
| 971 | * @return string HTML markup. |
| 972 | */ |
| 973 | private function radio_group( $this_data, $attributes ) { |
| 974 | $properties = $this_data['properties']; |
| 975 | $data = $properties['data']['child']; |
| 976 | $name = $properties['attributes']['name']; |
| 977 | |
| 978 | $str = '<div ' . $attributes . '>'; |
| 979 | |
| 980 | foreach ( $data as $key => $child ) { |
| 981 | $attrs = "type='radio' name='{$name}' value='{$child['value']}'"; |
| 982 | $attrs .= $child['checked'] ? ' checked' : ''; |
| 983 | |
| 984 | $str .= '<label> |
| 985 | <input ' . $attrs . '/> |
| 986 | <span>' . $child['content'] . '</span> |
| 987 | </label>'; |
| 988 | } |
| 989 | $str .= '</div>'; |
| 990 | return $str; |
| 991 | } |
| 992 | |
| 993 | /** |
| 994 | * Generate popup-body element markup |
| 995 | * |
| 996 | * @param array $this_data single element block. |
| 997 | * @param array $attributes single element all attributes. |
| 998 | * @return string HTML markup. |
| 999 | */ |
| 1000 | private function popup_element( $this_data, $attributes, $options ) { |
| 1001 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 1002 | return '<div class="kirki-popup-body-wrapper"><div ' . $attributes . '>' . $children_markup . '</div></div>'; |
| 1003 | } |
| 1004 | |
| 1005 | /** |
| 1006 | * Recursively Generate menu items element markup |
| 1007 | * |
| 1008 | * @param array $submenus all submenus. |
| 1009 | * @param int $depth menu nesting info. |
| 1010 | * @return string HTML markup. |
| 1011 | */ |
| 1012 | private function rec_gen_menu_items( $submenus, $depth ) { |
| 1013 | if ( count( $submenus ) === 0 ) { |
| 1014 | return ''; |
| 1015 | } |
| 1016 | if ( $depth === 0 ) { |
| 1017 | $str = '<ul class="' . 'kirki-nav-menu">'; |
| 1018 | } else { |
| 1019 | $str = '<ul class="' . 'kirki-element-submenu">'; |
| 1020 | } |
| 1021 | $depth++; |
| 1022 | foreach ( $submenus as $key => $menu ) { |
| 1023 | $str .= '<li class="' . 'kirki-element-nav-item"><a class="' . 'kirki-link-element" href="' . $menu->url . '" target="' . $menu->target . '">' . $menu->title . '</a>' . $this->rec_gen_menu_items( $menu->submenus, $depth ) . '</li>'; |
| 1024 | } |
| 1025 | $str .= '</ul>'; |
| 1026 | return $str; |
| 1027 | } |
| 1028 | |
| 1029 | /** |
| 1030 | * This method will add css value and unit |
| 1031 | * |
| 1032 | * @param array $value css value and unit pair. |
| 1033 | * @return string 5px | auto. |
| 1034 | */ |
| 1035 | private function add_unit( $value ) { |
| 1036 | if ( isset( $value['unit'] ) && $value['unit'] !== 'auto' ) { |
| 1037 | return $value['value'] . $value['unit']; |
| 1038 | } |
| 1039 | return 'auto'; |
| 1040 | } |
| 1041 | |
| 1042 | /** |
| 1043 | * Generate Image element markup |
| 1044 | * |
| 1045 | * @param array $this_data single element block. |
| 1046 | * @param array $attributes single element all attributes. |
| 1047 | * @param array $options single element all options. |
| 1048 | * @return string HTML markup. |
| 1049 | */ |
| 1050 | private function image_element( $this_data, $attributes, $options ) { |
| 1051 | $properties = $this_data['properties']; |
| 1052 | $svg_outer_html = isset( $properties['svgOuterHtml'] ) ? $properties['svgOuterHtml'] : false; |
| 1053 | $dynamic_content = isset( $properties['dynamicContent'] ) ? $properties['dynamicContent'] : false; |
| 1054 | $dynamic_alt = isset( $properties['dynamicAlt'] ) ? $properties['dynamicAlt'] : false; |
| 1055 | |
| 1056 | $user_initials = false; |
| 1057 | |
| 1058 | $src = ''; |
| 1059 | |
| 1060 | if ( $dynamic_content ) { |
| 1061 | $image_data = array(); |
| 1062 | |
| 1063 | if ( $dynamic_content['type'] === 'reference' && isset( $options['post'], $options['post']->ID ) ) { |
| 1064 | $content_info = array( |
| 1065 | 'collectionItem' => array( |
| 1066 | 'ID' => $options['post']->ID, |
| 1067 | ), |
| 1068 | 'dynamicContent' => $dynamic_content, |
| 1069 | ); |
| 1070 | |
| 1071 | $content = apply_filters( 'kirki_dynamic_content', false, $content_info ); |
| 1072 | $image_data = $content; |
| 1073 | } elseif ( $dynamic_content['type'] === 'gallery' ) { |
| 1074 | $content_info = array( |
| 1075 | 'collectionItem' => array( |
| 1076 | 'id' => $options['gallery']['id'], |
| 1077 | 'url' => $options['gallery']['url'], |
| 1078 | |
| 1079 | ), |
| 1080 | 'dynamicContent' => $dynamic_content, |
| 1081 | ); |
| 1082 | |
| 1083 | $content = apply_filters( 'kirki_dynamic_content', false, $content_info ); |
| 1084 | |
| 1085 | $image_data = $content; |
| 1086 | } elseif ( $dynamic_content['type'] === 'user' ) { |
| 1087 | $user_id = isset( $options['user'], $options['user']['ID'] ) ? $options['user']['ID'] : null; |
| 1088 | $src = HelperFunctions::get_user_dynamic_content( $dynamic_content['value'], $user_id, $dynamic_content['meta'] ?? '' ); |
| 1089 | $image_data = array( |
| 1090 | 'src' => $src, |
| 1091 | ); |
| 1092 | } elseif ( isset( $options['itemType'] ) ) { |
| 1093 | if ( $options['itemType'] === 'post' ) { |
| 1094 | if ( isset( $options['post']->{$dynamic_content['value']} ) && $options['post']->{$dynamic_content['value']} ) { |
| 1095 | $image_data = $options['post']->{$dynamic_content['value']}; |
| 1096 | } else { |
| 1097 | $image_data = HelperFunctions::get_post_dynamic_content( $dynamic_content['value'], isset( $options['post'] ) ? $options['post'] : null ); |
| 1098 | } |
| 1099 | } elseif ( $options['itemType'] === 'comment' ) { |
| 1100 | if ( isset( $options['comment']->{$dynamic_content['value']} ) && $options['comment']->{$dynamic_content['value']} ) { |
| 1101 | $image_data = $options['comment']->{$dynamic_content['value']}; |
| 1102 | } |
| 1103 | } elseif ( $options['itemType'] === 'user' ) { |
| 1104 | if ( isset( $options['user'], $options['user'][ $dynamic_content['value'] ] ) ) { |
| 1105 | $image_data = array( |
| 1106 | 'src' => $options['user'][ $dynamic_content['value'] ], |
| 1107 | ); |
| 1108 | } |
| 1109 | } |
| 1110 | } else { |
| 1111 | $post = isset( $options['post'] ) ? $options['post'] : get_post( HelperFunctions::get_post_id_if_possible_from_url() ); |
| 1112 | $image_data = HelperFunctions::get_post_dynamic_content( $dynamic_content['value'], $post, isset( $dynamic_content['meta'] ) ? $dynamic_content['meta'] : null ); |
| 1113 | if ( is_string( $image_data ) ) { |
| 1114 | $image_data = array( |
| 1115 | 'src' => $image_data, |
| 1116 | ); |
| 1117 | } |
| 1118 | } |
| 1119 | |
| 1120 | if ( isset( $image_data['src'] ) ) { |
| 1121 | $src = $image_data['src']; |
| 1122 | } |
| 1123 | |
| 1124 | if ( isset( $image_data['wp_attachment_id'] ) ) { |
| 1125 | $properties['wp_attachment_id'] = $image_data['wp_attachment_id']; |
| 1126 | } |
| 1127 | } |
| 1128 | |
| 1129 | if ( $dynamic_content && $src ) { |
| 1130 | // replace src and alt. |
| 1131 | $attributes = preg_replace( array( '/src="([^"]+")/i' ), array( '' ), $attributes ); |
| 1132 | } else { |
| 1133 | $src = isset( $properties['attributes']['src'] ) ? $properties['attributes']['src'] : ''; |
| 1134 | } |
| 1135 | |
| 1136 | // set dynamic alt here |
| 1137 | if ( $dynamic_alt ) { |
| 1138 | $new_alt = Utils::getDynamicRichTextValue( $dynamic_alt, $options ); |
| 1139 | |
| 1140 | // Update properties array for consistency |
| 1141 | $properties['attributes']['alt'] = $new_alt; |
| 1142 | |
| 1143 | // Replace alt attribute inside the HTML string |
| 1144 | $attributes = preg_replace( |
| 1145 | '/alt="[^"]*"/i', |
| 1146 | 'alt="' . esc_attr( $new_alt ) . '"', |
| 1147 | $attributes |
| 1148 | ); |
| 1149 | } elseif ( empty( $properties['attributes']['alt'] ) ) { |
| 1150 | // get WordPress attachment alt text if alt is empty |
| 1151 | if ( isset( $properties['wp_attachment_id'] ) && $properties['wp_attachment_id'] ) { |
| 1152 | $alt_text = get_post_meta( $properties['wp_attachment_id'], '_wp_attachment_image_alt', true ); |
| 1153 | $attributes = preg_replace( '/alt="([^"]*)"/i', 'alt="' . esc_attr( $alt_text ) . '"', $attributes ); |
| 1154 | } |
| 1155 | } |
| 1156 | |
| 1157 | $srcset = null; |
| 1158 | if ( ! $dynamic_content && isset( $properties['wp_attachment_id'] ) && $properties['wp_attachment_id'] ) { |
| 1159 | $srcset = wp_get_attachment_image_srcset( $properties['wp_attachment_id'] ); |
| 1160 | $attributes .= $srcset ? ' srcset="' . $srcset . '"' : ''; |
| 1161 | |
| 1162 | $sizes = ''; |
| 1163 | $a_meta_data = wp_get_attachment_metadata( $properties['wp_attachment_id'] ); |
| 1164 | if ( $a_meta_data && isset( $a_meta_data['width'] ) ) { |
| 1165 | $width = $a_meta_data['width']; |
| 1166 | $sizes = '(max-width: ' . $width . 'px) 100vw, ' . $width . 'px'; |
| 1167 | $attributes .= $sizes ? ' sizes="' . $sizes . '"' : ''; |
| 1168 | } |
| 1169 | } |
| 1170 | |
| 1171 | if ( ( isset( $properties['load'] ) && $properties['load'] !== 'auto' ) || ! isset( $properties['load'] ) ) { |
| 1172 | $attributes .= isset( $properties['load'] ) ? ' loading="' . $properties['load'] . '"' : ' loading="lazy"'; |
| 1173 | } |
| 1174 | |
| 1175 | if ( isset( $properties['width'] ) ) { |
| 1176 | $attributes .= ' width="' . $this->add_unit( $properties['width'] ) . '"'; |
| 1177 | |
| 1178 | } |
| 1179 | if ( isset( $properties['height'] ) ) { |
| 1180 | $attributes .= ' height="' . $this->add_unit( $properties['height'] ) . '"'; |
| 1181 | } |
| 1182 | |
| 1183 | if ( ! $src ) { |
| 1184 | return ''; |
| 1185 | } |
| 1186 | |
| 1187 | $str = ''; |
| 1188 | |
| 1189 | if ( $svg_outer_html ) { |
| 1190 | $str .= '<img ' . $attributes . ' src="' . $src . '"/> |
| 1191 | <span>' . $svg_outer_html . '</span>'; |
| 1192 | } else { |
| 1193 | $str .= '<img ' . $attributes . ' src="' . $src . '"/>'; |
| 1194 | } |
| 1195 | |
| 1196 | return $str; |
| 1197 | } |
| 1198 | |
| 1199 | /** |
| 1200 | * Get video type from url |
| 1201 | * |
| 1202 | * @param string $url single element block. |
| 1203 | * @return string|bool video url type. |
| 1204 | */ |
| 1205 | private function video_type( $url ) { |
| 1206 | if ( strpos( $url, 'youtube' ) > 0 || strpos( $url, 'youtu.be' ) > 0 ) { |
| 1207 | return 'youtube'; |
| 1208 | } elseif ( strpos( $url, 'vimeo' ) > 0 ) { |
| 1209 | return 'vimeo'; |
| 1210 | } elseif ( strpos( $url, 'tiktok' ) > 0 ) { |
| 1211 | return 'tiktok'; |
| 1212 | } else { |
| 1213 | return false; |
| 1214 | } |
| 1215 | } |
| 1216 | |
| 1217 | /** |
| 1218 | * Get video type from url |
| 1219 | * |
| 1220 | * @param string $url single element block. |
| 1221 | * @return string youtube url type. |
| 1222 | */ |
| 1223 | private function get_youtube_embed_url( $url ) { |
| 1224 | preg_match( '%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match ); |
| 1225 | return isset( $match[1] ) ? 'https://www.youtube.com/embed/' . $match[1] : '#'; |
| 1226 | } |
| 1227 | |
| 1228 | private function get_vimeo_embed_url( $url ) { |
| 1229 | preg_match( '/vimeo\.com\/(?:.*\/)?(\d+)/', $url, $matches ); |
| 1230 | return isset( $matches[1] ) ? 'https://player.vimeo.com/video/' . $matches[1] : '#'; |
| 1231 | } |
| 1232 | |
| 1233 | private function get_tiktok_embed_url( $url ) { |
| 1234 | preg_match( '/tiktok\.com\/(?:@[\w.-]+\/)?video\/(\d+)/', $url, $matches ); |
| 1235 | return isset( $matches[1] ) ? 'https://www.tiktok.com/embed/' . $matches[1] : '#'; |
| 1236 | } |
| 1237 | |
| 1238 | /** |
| 1239 | * Generate symbol markup |
| 1240 | * |
| 1241 | * @param array $this_data single element block. |
| 1242 | * @param array $attributes single element all attributes. |
| 1243 | * @return string HTML markup. |
| 1244 | */ |
| 1245 | private function generate_symbol_html( $this_data, $attributes, $options = array() ) { |
| 1246 | $properties = $this_data['properties']; |
| 1247 | $symbol_id = $properties['symbolId']; |
| 1248 | $symbolElementProp = isset( $properties['symbolElProps'] ) ? $properties['symbolElProps'] : false; |
| 1249 | $symbol = Symbol::get_single_symbol( $symbol_id, true, false, $symbolElementProp ); |
| 1250 | |
| 1251 | if ( ! $symbol ) { |
| 1252 | return ''; |
| 1253 | } |
| 1254 | |
| 1255 | $symbol_data = $symbol['symbolData']; |
| 1256 | if ( ! $symbol_data || ! isset( $symbol_data['data'] ) ) { |
| 1257 | return ''; |
| 1258 | } |
| 1259 | $options['symbol_id'] = $symbol_id; |
| 1260 | $options['inside_symbol'] = true; |
| 1261 | |
| 1262 | $s = HelperFunctions::rec_update_data_id_then_return_new_html( $symbol_data['data'], $symbol_data['styleBlocks'], $symbol_data['root'], $options ); |
| 1263 | $fonts_links = ''; |
| 1264 | if ( isset( $symbol_data['customFonts'] ) ) { |
| 1265 | foreach ( $symbol_data['customFonts'] as $key => $f ) { |
| 1266 | if ( isset( $f['fontUrl'] ) ) { |
| 1267 | $fonts_links .= HelperFunctions::getFontsHTMLMarkup( $f ); |
| 1268 | } |
| 1269 | } |
| 1270 | } |
| 1271 | return '<div ' . $attributes . '>' . $fonts_links . $s . '</div>'; |
| 1272 | } |
| 1273 | |
| 1274 | /** |
| 1275 | * Get html template. |
| 1276 | * |
| 1277 | * @param string $template template file name. |
| 1278 | * @param array $vars if extra variable needs inside template file. |
| 1279 | * @return string $message |
| 1280 | */ |
| 1281 | private function get_template( $template, $vars ) { |
| 1282 | ob_start(); |
| 1283 | include __DIR__ . "/templates/$template.view.php"; |
| 1284 | $message = ob_get_contents(); |
| 1285 | ob_end_clean(); |
| 1286 | return $message; |
| 1287 | } |
| 1288 | |
| 1289 | /** |
| 1290 | * Generate File upload element markup |
| 1291 | * |
| 1292 | * @param array $this_data single element block. |
| 1293 | * @param array $attributes single element all attributes. |
| 1294 | * @param array $options single element all options. |
| 1295 | * @return string HTML markup. |
| 1296 | */ |
| 1297 | private function file_upload_element( $this_data, $attributes, $options ) { |
| 1298 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1299 | $data_attr = isset( $this_data['properties']['attributes'] ) ? $this_data['properties']['attributes'] : array(); |
| 1300 | $options = array_merge( |
| 1301 | $options, |
| 1302 | array( |
| 1303 | 'file_upload' => array( |
| 1304 | 'name' => isset( $data_attr['name'] ) ? $data_attr['name'] : '', |
| 1305 | 'accept' => isset( $data_attr['accept'] ) ? $data_attr['accept'] : '', |
| 1306 | 'required' => isset( $data_attr['required'] ) ? $data_attr['required'] : '', |
| 1307 | 'maxFileSize' => isset( $this_data['properties']['maxFileSize'] ) ? $this_data['properties']['maxFileSize'] : 2, |
| 1308 | ), |
| 1309 | ) |
| 1310 | ); |
| 1311 | |
| 1312 | $attributes = $this->getAllAttributes( |
| 1313 | $this_data, |
| 1314 | array( |
| 1315 | 'name' => false, |
| 1316 | 'accept' => false, |
| 1317 | 'required' => false, |
| 1318 | 'rest' => true, |
| 1319 | ), |
| 1320 | ); |
| 1321 | |
| 1322 | $children_markup = $this->construct_children_markup( isset( $this_data['children'] ) ? $this_data['children'] : array(), $options ); |
| 1323 | return "<$tag $attributes> |
| 1324 | $children_markup |
| 1325 | </$tag>"; |
| 1326 | } |
| 1327 | |
| 1328 | /** |
| 1329 | * Generate File input threshold text element markup |
| 1330 | * |
| 1331 | * @param array $this_data single element block. |
| 1332 | * @param array $attributes single element all attributes. |
| 1333 | * @param array $options single element all options. |
| 1334 | * @return string HTML markup. |
| 1335 | */ |
| 1336 | |
| 1337 | private function file_upload_threshold_text( $this_data, $attributes, $options ) { |
| 1338 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'span'; |
| 1339 | $max_file_size = isset( $options['file_upload']['maxFileSize'] ) ? $options['file_upload']['maxFileSize'] : 2; |
| 1340 | |
| 1341 | return "<$tag $attributes>Max file size " . $max_file_size . "MB.</$tag>"; |
| 1342 | } |
| 1343 | |
| 1344 | /** |
| 1345 | * Generate File input element markup |
| 1346 | * |
| 1347 | * @param array $this_data single element block. |
| 1348 | * @param array $attributes single element all attributes. |
| 1349 | * @param array $options single element all options. |
| 1350 | * @return string HTML markup. |
| 1351 | */ |
| 1352 | private function file_input_element( $this_data, $attributes, $options ) { |
| 1353 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1354 | $children = $this_data['children'] ?? array(); |
| 1355 | $markup = ''; |
| 1356 | |
| 1357 | $name = isset( $options['file_upload']['name'] ) ? $options['file_upload']['name'] : ''; |
| 1358 | $accept = isset( $options['file_upload']['accept'] ) ? $options['file_upload']['accept'] : ''; |
| 1359 | $required = isset( $options['file_upload']['required'] ) ? $options['file_upload']['required'] : ''; |
| 1360 | $max_file_size = isset( $options['file_upload']['maxFileSize'] ) ? $options['file_upload']['maxFileSize'] : 2; |
| 1361 | |
| 1362 | foreach ( $children as $child ) { |
| 1363 | $markup .= $this->recGenHTML( $child, $options ); |
| 1364 | } |
| 1365 | |
| 1366 | return "<$tag $attributes> |
| 1367 | $markup |
| 1368 | <input |
| 1369 | type=\"file\" |
| 1370 | readonly |
| 1371 | style=\"display: none;\" |
| 1372 | name=\"$name\" |
| 1373 | accept=\"$accept\" |
| 1374 | required=\"$required\" |
| 1375 | kirki-max_file_size=$max_file_size |
| 1376 | /> |
| 1377 | </$tag>"; |
| 1378 | } |
| 1379 | |
| 1380 | private function slider_nav_element( $this_data, $attributes, $options ) { |
| 1381 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1382 | $collection = isset( $options['collection'] ) ? $options['collection'] : array(); |
| 1383 | $itemType = isset( $options['itemType'] ) ? $options['itemType'] : 'post'; |
| 1384 | $slider_nav_item_id = isset( $this_data['children'][0] ) ? $this_data['children'][0] : ''; |
| 1385 | $slider_nav_children = isset( $this_data['children'] ) ? $this_data['children'] : array(); |
| 1386 | $slider_mode = $options['slider_mode'] ?? 'manual'; |
| 1387 | $page_no = isset( $options['page_no'] ) ? (int) $options['page_no'] : 1; |
| 1388 | |
| 1389 | $children = array(); |
| 1390 | |
| 1391 | if ( $slider_mode === 'manual' ) { |
| 1392 | foreach ( $slider_nav_children as $key => $child_id ) { |
| 1393 | $children[] = $this->recGenHTML( $child_id, $options ); |
| 1394 | } |
| 1395 | } else { // dynamic |
| 1396 | if ( empty( $collection ) || ! $slider_nav_item_id ) { |
| 1397 | return ''; |
| 1398 | } |
| 1399 | |
| 1400 | $items_per_page = isset( $options['items_per_page'] ) ? (int) $options['items_per_page'] : count( $collection ); |
| 1401 | |
| 1402 | $start = ( $page_no - 1 ) * $items_per_page; |
| 1403 | $items_to_render = array_slice( $collection, $start, $items_per_page ); |
| 1404 | |
| 1405 | foreach ( $items_to_render as $key => $collection_item ) { |
| 1406 | $item_index = HelperFunctions::get_current_item_index( $key + 1, $options ); |
| 1407 | |
| 1408 | $merged_options = array_merge( |
| 1409 | $options, |
| 1410 | array( |
| 1411 | 'itemType' => $itemType, |
| 1412 | $itemType => $collection_item, |
| 1413 | 'item_index' => $item_index, |
| 1414 | 'nav_index' => $start + $key, |
| 1415 | 'is_active' => $key === 0, |
| 1416 | ) |
| 1417 | ); |
| 1418 | |
| 1419 | $children[] = HelperFunctions::rec_update_data_id_then_return_new_html( $this->data, $this->style_blocks, $slider_nav_item_id, $merged_options, ( $key === 0 ) ); |
| 1420 | } |
| 1421 | } |
| 1422 | |
| 1423 | return $this->get_template( |
| 1424 | 'pagination-item', |
| 1425 | array( |
| 1426 | 'attributes' => $attributes, |
| 1427 | 'children' => $children, |
| 1428 | 'current_page' => 1, |
| 1429 | 'page_number' => $page_no, |
| 1430 | 'tag' => $tag, |
| 1431 | ) |
| 1432 | ); |
| 1433 | } |
| 1434 | |
| 1435 | private function tabs_element( $this_data, $attributes, $options ) { |
| 1436 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1437 | $children = $this_data['children'] ?? array(); |
| 1438 | $markup = ''; |
| 1439 | |
| 1440 | foreach ( $children as $child ) { |
| 1441 | $merged_options = array_merge( |
| 1442 | $options, |
| 1443 | array( |
| 1444 | 'active_tab_index' => isset($this_data['properties'],$this_data['properties']['active_tab']) ? $this_data['properties']['active_tab'] : 0, |
| 1445 | ) |
| 1446 | ); |
| 1447 | |
| 1448 | $markup .= $this->recGenHTML( $child, $merged_options ); |
| 1449 | } |
| 1450 | |
| 1451 | return "<$tag $attributes> |
| 1452 | $markup |
| 1453 | </$tag>"; |
| 1454 | } |
| 1455 | |
| 1456 | private function tab_element( $this_data, $attributes, $options ) { |
| 1457 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1458 | $children = $this_data['children'] ?? array(); |
| 1459 | $markup = ''; |
| 1460 | |
| 1461 | $active_tab_index = isset( $options['active_tab_index'] ) ? $options['active_tab_index'] : 0; |
| 1462 | $item_index = isset( $options['item_index'] ) ? $options['item_index'] : 0; |
| 1463 | |
| 1464 | if ( $active_tab_index === $item_index ) { |
| 1465 | // Add kirki-current-tab class to attributes |
| 1466 | if ( preg_match( '/class="([^"]*)"/', $attributes, $matches ) ) { |
| 1467 | // Class attribute exists, append to it |
| 1468 | $existing_classes = $matches[1]; |
| 1469 | $new_classes = trim( $existing_classes . ' kirki-current-tab' ); |
| 1470 | $attributes = preg_replace( |
| 1471 | '/class="[^"]*"/', |
| 1472 | 'class="' . esc_attr( $new_classes ) . '"', |
| 1473 | $attributes |
| 1474 | ); |
| 1475 | } else { |
| 1476 | // No class attribute, add it |
| 1477 | $attributes .= ' class="kirki-current-tab"'; |
| 1478 | } |
| 1479 | } |
| 1480 | |
| 1481 | // foreach ( $children as $child ) { |
| 1482 | // $markup .= $this->recGenHTML( $child, $options ); |
| 1483 | // } |
| 1484 | $markup = $this->get_child_content_or_childrens( $this_data, $options ); |
| 1485 | return "<$tag $attributes> |
| 1486 | $markup |
| 1487 | </$tag>"; |
| 1488 | } |
| 1489 | |
| 1490 | private function tab_pane_element( $this_data, $attributes, $options ) { |
| 1491 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1492 | $children = $this_data['children'] ?? array(); |
| 1493 | $markup = ''; |
| 1494 | |
| 1495 | $active_tab_index = isset( $options['active_tab_index'] ) ? $options['active_tab_index'] : 0; |
| 1496 | $item_index = isset( $options['item_index'] ) ? $options['item_index'] : 0; |
| 1497 | |
| 1498 | if ( $active_tab_index === $item_index ) { |
| 1499 | // Add kirki-tab-active class to attributes |
| 1500 | if ( preg_match( '/class="([^"]*)"/', $attributes, $matches ) ) { |
| 1501 | // Class attribute exists, append to it |
| 1502 | $existing_classes = $matches[1]; |
| 1503 | $new_classes = trim( $existing_classes . ' kirki-tab-active' ); |
| 1504 | $attributes = preg_replace( |
| 1505 | '/class="[^"]*"/', |
| 1506 | 'class="' . esc_attr( $new_classes ) . '"', |
| 1507 | $attributes |
| 1508 | ); |
| 1509 | } else { |
| 1510 | // No class attribute, add it |
| 1511 | $attributes .= ' class="kirki-tab-active"'; |
| 1512 | } |
| 1513 | } |
| 1514 | |
| 1515 | $markup = $this->get_child_content_or_childrens( $this_data, $options ); |
| 1516 | return "<$tag $attributes> |
| 1517 | $markup |
| 1518 | </$tag>"; |
| 1519 | } |
| 1520 | |
| 1521 | private function tab_menu_and_content_element( $this_data, $attributes, $options ) { |
| 1522 | $tag = isset( $this_data['properties']['tag'] ) ? $this_data['properties']['tag'] : 'div'; |
| 1523 | $children = $this_data['children'] ?? array(); |
| 1524 | $markup = ''; |
| 1525 | |
| 1526 | $markup = $this->get_child_content_or_childrens( $this_data, $options ); |
| 1527 | if($this_data['name'] === 'tab_menu'){ |
| 1528 | $attributes .= ' data-kirki_tab="tab_menu"'; |
| 1529 | }else{ |
| 1530 | $attributes .= ' data-kirki_tab="tab_content"'; |
| 1531 | } |
| 1532 | return "<$tag $attributes> |
| 1533 | $markup |
| 1534 | </$tag>"; |
| 1535 | } |
| 1536 | |
| 1537 | } |