Advertisement
Guenni007

tabs

Aug 2nd, 2021
1,416
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 18.44 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Tabs
  4.  * Changed line 626 to h2 tab titles
  5.  * Creates a tabbed content area
  6.  */
  7. if ( ! defined( 'ABSPATH' ) ) {  exit;  }    // Exit if accessed directly
  8.  
  9.  
  10. if ( ! class_exists( 'avia_sc_tab' ) )
  11. {
  12.     class avia_sc_tab extends aviaShortcodeTemplate
  13.     {  
  14.         /**
  15.          *
  16.          * @var int
  17.          */
  18.         static protected $tab_id = 1;
  19.        
  20.         /**
  21.          *
  22.          * @var int
  23.          */
  24.         static protected $counter = 1;
  25.        
  26.         /**
  27.          *
  28.          * @var int
  29.          */
  30.         static protected $initial = 1;
  31.        
  32.         /**
  33.          *
  34.          * @since 4.5.5
  35.          * @var array
  36.          */
  37.         protected $screen_options;
  38.        
  39.         /**
  40.          *
  41.          * @since 4.5.5
  42.          * @param AviaBuilder $builder
  43.          */
  44.         public function __construct( $builder )
  45.         {
  46.             $this->screen_options = array();
  47.            
  48.             parent::__construct( $builder );
  49.         }
  50.        
  51.         /**
  52.          * @since 4.5.5
  53.          */
  54.         public function __destruct()
  55.         {
  56.             parent::__destruct();
  57.            
  58.             unset( $this->screen_options );
  59.         }
  60.  
  61.         /**
  62.          * Create the config array for the shortcode button
  63.          */
  64.         function shortcode_insert_button()
  65.         {
  66.             $this->config['version']        = '1.0';
  67.             $this->config['self_closing']   = 'no';
  68.             $this->config['base_element']   = 'yes';
  69.  
  70.             $this->config['name']           = __( 'Tabs', 'avia_framework' );
  71.             $this->config['tab']            = __( 'Content Elements', 'avia_framework' );
  72.             $this->config['icon']           = AviaBuilder::$path['imagesURL'] . 'sc-tabs.png';
  73.             $this->config['order']          = 75;
  74.             $this->config['target']         = 'avia-target-insert';
  75.             $this->config['shortcode']      = 'av_tab_container';
  76.             $this->config['shortcode_nested'] = array( 'av_tab' );
  77.             $this->config['tooltip']        = __( 'Creates a tabbed content area', 'avia_framework' );
  78.             $this->config['disabling_allowed'] = true;
  79.             $this->config['id_name']        = 'id';
  80.             $this->config['id_show']        = 'yes';
  81.             $this->config['alb_desc_id']    = 'alb_description';
  82.             $this->config['name_item']      = __( 'Tabs Item', 'avia_framework' );
  83.             $this->config['tooltip_item']   = __( 'A single tabs item', 'avia_framework' );
  84.         }
  85.        
  86.        
  87.         function admin_assets()
  88.         {
  89.             $ver = AviaBuilder::VERSION;
  90.            
  91.             wp_register_script( 'avia_tab_toggle_js', AviaBuilder::$path['assetsURL'] . 'js/avia-tab-toggle.js', array( 'avia_modal_js' ), $ver, true );
  92.             Avia_Builder()->add_registered_admin_script( 'avia_tab_toggle_js' );
  93.         }
  94.  
  95.         function extra_assets()
  96.         {
  97.             //load css
  98.             wp_enqueue_style( 'avia-module-tabs', AviaBuilder::$path['pluginUrlRoot'] . 'avia-shortcodes/tabs/tabs.css', array( 'avia-layout' ), false );
  99.  
  100.             //load js
  101.             wp_enqueue_script( 'avia-module-tabs', AviaBuilder::$path['pluginUrlRoot'] . 'avia-shortcodes/tabs/tabs.js', array( 'avia-shortcodes' ), false, true );
  102.         }
  103.  
  104.  
  105.         /**
  106.          * Popup Elements
  107.          *
  108.          * If this function is defined in a child class the element automatically gets an edit button, that, when pressed
  109.          * opens a modal window that allows to edit the element properties
  110.          *
  111.          * @return void
  112.          */
  113.         function popup_elements()
  114.         {
  115.            
  116.             $this->elements = array(
  117.                
  118.                 array(
  119.                         'type'  => 'tab_container',
  120.                         'nodescription' => true
  121.                     ),
  122.                        
  123.                 array(
  124.                         'type'  => 'tab',
  125.                         'name'  => __( 'Content', 'avia_framework' ),
  126.                         'nodescription' => true
  127.                     ),
  128.                
  129.                     array(
  130.                             'type'          => 'template',
  131.                             'template_id'   => $this->popup_key( 'content_tabs' )
  132.                         ),
  133.                
  134.                 array(
  135.                         'type'  => 'tab_close',
  136.                         'nodescription' => true
  137.                     ),
  138.                
  139.                 array(
  140.                         'type'  => 'tab',
  141.                         'name'  => __( 'Styling', 'avia_framework' ),
  142.                         'nodescription' => true
  143.                     ),
  144.                
  145.                     array(
  146.                             'type'          => 'template',
  147.                             'template_id'   => $this->popup_key( 'styling_tabs' )
  148.                         ),
  149.                
  150.                 array(
  151.                         'type'  => 'tab_close',
  152.                         'nodescription' => true
  153.                     ),
  154.                
  155.                 array(
  156.                         'type'  => 'tab',
  157.                         'name'  => __( 'Advanced', 'avia_framework' ),
  158.                         'nodescription' => true
  159.                     ),
  160.                
  161.                     array(
  162.                             'type'  => 'toggle_container',
  163.                             'nodescription' => true
  164.                         ),
  165.                
  166.                         array( 
  167.                                 'type'          => 'template',
  168.                                 'template_id'   => $this->popup_key( 'advanced_animation' )
  169.                             ),
  170.                
  171.                         array( 
  172.                                 'type'          => 'template',
  173.                                 'template_id'   => 'screen_options_toggle',
  174.                                 'lockable'      => true
  175.                             ),
  176.  
  177.                         array( 
  178.                                 'type'          => 'template',
  179.                                 'template_id'   => 'developer_options_toggle',
  180.                                 'args'          => array( 'sc' => $this )
  181.                             ),
  182.                
  183.                     array(
  184.                             'type'  => 'toggle_container_close',
  185.                             'nodescription' => true
  186.                         ),
  187.                
  188.                 array(
  189.                         'type'  => 'tab_close',
  190.                         'nodescription' => true
  191.                     ),
  192.                
  193.                 array( 
  194.                         'type'          => 'template',
  195.                         'template_id'   => 'element_template_selection_tab',
  196.                         'args'          => array( 'sc' => $this )
  197.                     ),
  198.  
  199.                 array(
  200.                         'type'  => 'tab_container_close',
  201.                         'nodescription' => true
  202.                     )
  203.                
  204.             );
  205.  
  206.         }
  207.        
  208.         /**
  209.          * Create and register templates for easier maintainance
  210.          *
  211.          * @since 4.6.4
  212.          */
  213.         protected function register_dynamic_templates()
  214.         {
  215.            
  216.             $this->register_modal_group_templates();
  217.            
  218.             /**
  219.              * Content Tab
  220.              * ===========
  221.              */
  222.            
  223.             $c = array(
  224.                         array(
  225.                             'name'          => __( 'Add/Edit Tabs', 'avia_framework' ),
  226.                             'desc'          => __( 'Here you can add, remove and edit the Tabs you want to display.', 'avia_framework' ),
  227.                             'type'          => 'modal_group',
  228.                             'id'            => 'content',
  229.                             'modal_title'   => __( 'Edit Form Element', 'avia_framework' ),
  230.                             'container_class' => 'avia-element-fullwidth avia-tab-container',
  231.                             'editable_item' => true,
  232.                             'lockable'      => true,
  233.                             'tmpl_set_default'  => false,
  234.                             'std'           => array(
  235.                                                     array( 'title' => __( 'Tab 1', 'avia_framework' ) ),
  236.                                                     array( 'title' => __( 'Tab 2', 'avia_framework' ) ),
  237.                                                 ),
  238.                             'subelements'   => $this->create_modal()
  239.                         ),
  240.                
  241.                         array(
  242.                             'name'  => __( 'Initial Open', 'avia_framework' ),
  243.                             'desc'  => __( 'Enter the Number of the Tab that should be open initially.', 'avia_framework' ),
  244.                             'id'    => 'initial',
  245.                             'type'  => 'input',
  246.                             'std'   => '1',                        
  247.                             'lockable'  => true
  248.                         )
  249.                 );
  250.            
  251.             AviaPopupTemplates()->register_dynamic_template( $this->popup_key( 'content_tabs' ), $c );
  252.            
  253.             /**
  254.              * Content Tab
  255.              * ===========
  256.              */
  257.            
  258.             $c = array(
  259.                         array(
  260.                             'name'  => __( 'Tab Position', 'avia_framework' ),
  261.                             'desc'  => __( 'Where should the tabs be displayed', 'avia_framework' ),
  262.                             'id'    => 'position',
  263.                             'type'  => 'select',
  264.                             'std'   => 'top_tab',
  265.                             'container_class' => 'avia-element-fullwidth',
  266.                             'target'    => array( '#aviaTBcontent-form-container', 'class' ),
  267.                             'lockable'  => true,
  268.                             'subtype'   => array(
  269.                                                 __( 'Display tabs at the top', 'avia_framework' )   => 'top_tab',
  270.                                                 __( 'Display Tabs on the left', 'avia_framework' )  => 'sidebar_tab sidebar_tab_left',
  271.                                                 __( 'Display Tabs on the right', 'avia_framework' ) => 'sidebar_tab sidebar_tab_right'
  272.                                             )
  273.                         ),
  274.  
  275.                         array(
  276.                             'name'  => __( 'Boxed Tabs', 'avia_framework' ),
  277.                             'desc'  => __( 'Do you want to display a border around your tabs or without border', 'avia_framework' ),
  278.                             'id'    => 'boxed',
  279.                             'type'  => 'select',
  280.                             'std'   => 'border_tabs',
  281.                             'lockable'  => true,
  282.                             'required'  => array( 'position', 'contains', 'sidebar_tab' ),
  283.                             'subtype'   => array(
  284.                                                 __( 'With border', 'avia_framework' )       => 'border_tabs',
  285.                                                 __( 'Without border', 'avia_framework' )    => 'noborder_tabs'
  286.                                             )
  287.                         )
  288.  
  289.                 );
  290.            
  291.             AviaPopupTemplates()->register_dynamic_template( $this->popup_key( 'styling_tabs' ), $c );
  292.            
  293.         }
  294.        
  295.         /**
  296.          * Creates the modal popup for a single entry
  297.          *
  298.          * @since 4.6.4
  299.          * @return array
  300.          */
  301.         protected function create_modal()
  302.         {
  303.             $elements = array(
  304.                
  305.                 array(
  306.                         'type'  => 'tab_container',
  307.                         'nodescription' => true
  308.                     ),
  309.                        
  310.                 array(
  311.                         'type'  => 'tab',
  312.                         'name'  => __( 'Content', 'avia_framework' ),
  313.                         'nodescription' => true
  314.                     ),
  315.                
  316.                     array(
  317.                             'type'          => 'template',
  318.                             'template_id'   => $this->popup_key( 'modal_content_tab' )
  319.                         ),
  320.                
  321.                 array(
  322.                         'type'  => 'tab_close',
  323.                         'nodescription' => true
  324.                     ),
  325.                
  326.                 array(
  327.                         'type'  => 'tab',
  328.                         'name'  => __( 'Advanced', 'avia_framework' ),
  329.                         'nodescription' => true
  330.                     ),
  331.                
  332.                 array(
  333.                             'type'  => 'toggle_container',
  334.                             'nodescription' => true
  335.                         ),
  336.                
  337.                     array( 
  338.                                 'type'          => 'template',
  339.                                 'template_id'   => 'developer_options_toggle',
  340.                                 'args'          => array(
  341.                                                         'sc'        => $this,
  342.                                                         'nested'    => 'av_tab'
  343.                                                     )
  344.                             ),
  345.                
  346.                 array(
  347.                             'type'  => 'toggle_container_close',
  348.                             'nodescription' => true
  349.                         ),
  350.                
  351.                 array(
  352.                         'type'  => 'tab_close',
  353.                         'nodescription' => true
  354.                     ),
  355.                
  356.                 array( 
  357.                         'type'          => 'template',
  358.                         'template_id'   => 'element_template_selection_tab',
  359.                         'args'          => array(
  360.                                                 'sc'            => $this,
  361.                                                 'modal_group'   => true
  362.                                             )
  363.                     ),
  364.                
  365.                 array(
  366.                         'type'  => 'tab_container_close',
  367.                         'nodescription' => true
  368.                     )
  369.                
  370.                 );
  371.            
  372.             return $elements;
  373.         }
  374.        
  375.         /**
  376.          * Register all templates for the modal group popup
  377.          *
  378.          * @since 4.6.4
  379.          */
  380.         protected function register_modal_group_templates()
  381.         {
  382.             /**
  383.              * Content Tab
  384.              * ===========
  385.              */
  386.             $c = array(
  387.                         array(
  388.                             'name'  => __( 'Tab Title', 'avia_framework' ),
  389.                             'desc'  => __( 'Enter the tab title here (Better keep it short)', 'avia_framework' ),
  390.                             'id'    => 'title',
  391.                             'type'  => 'input',
  392.                             'std'   => 'Tab Title',
  393.                             'lockable'  => true
  394.                         ),
  395.  
  396.                         array(
  397.                             'name'  => __( 'Tab Icon', 'avia_framework' ),
  398.                             'desc'  => __( 'Should an icon be displayed at the left side of the tab title?', 'avia_framework' ),
  399.                             'id'    => 'icon_select',
  400.                             'type'  => 'select',
  401.                             'std'   => 'no',
  402.                             'lockable'  => true,
  403.                             'subtype'   => array(
  404.                                                 __( 'No Icon', 'avia_framework' )           => 'no',
  405.                                                 __( 'Yes, display Icon', 'avia_framework' ) => 'yes'
  406.                                             )
  407.                         ),
  408.  
  409.                         array(
  410.                             'name'  => __( 'Tab Icon','avia_framework' ),
  411.                             'desc'  => __( 'Select an icon for your tab title below', 'avia_framework' ),
  412.                             'id'    => 'icon',
  413.                             'type'  => 'iconfont',
  414.                             'std'   => '',
  415.                             'lockable'  => true,
  416.                             'locked'    => array( 'icon', 'font' ),
  417.                             'required'  => array( 'icon_select', 'equals', 'yes' )
  418.                         ),
  419.  
  420.                         array(
  421.                             'name'  => __( 'Tab Content', 'avia_framework' ),
  422.                             'desc'  => __( 'Enter some content here', 'avia_framework' ),
  423.                             'id'    => 'content',
  424.                             'type'  => 'tiny_mce',
  425.                             'std'   => __( 'Tab Content goes here', 'avia_framework' ),
  426.                             'lockable'  => true
  427.                         ),
  428.                
  429.                 );
  430.            
  431.             AviaPopupTemplates()->register_dynamic_template( $this->popup_key( 'modal_content_tab' ), $c );
  432.            
  433.         }
  434.        
  435.         /**
  436.          * Return a config array for the nested shortcde
  437.          *
  438.          * @since 4.6.4
  439.          * @param string $nested_shortcode
  440.          * @return array
  441.          */
  442.         protected function get_nested_developer_elements( $nested_shortcode )
  443.         {
  444.             $config = array();
  445.            
  446.             if( 'av_tab' == $nested_shortcode )
  447.             {
  448.                 $config['id_name'] = 'custom_id';
  449.                 $config['id_show'] = 'yes';
  450.                 $config['custom_css_show'] = 'never';
  451.             }
  452.            
  453.             return $config;
  454.         }
  455.  
  456.         /**
  457.          * Editor Sub Element - this function defines the visual appearance of an element that is displayed within a modal window and on click opens its own modal window
  458.          * Works in the same way as Editor Element
  459.          * @param array $params this array holds the default values for $content and $args.
  460.          * @return $params the return array usually holds an innerHtml key that holds item specific markup.
  461.          */
  462.         function editor_sub_element( $params )
  463.         {
  464.             $default = array();
  465.             $locked = array();
  466.             $attr = $params['args'];
  467.             $content = $params['content'];
  468.             Avia_Element_Templates()->set_locked_attributes( $attr, $this, $this->config['shortcode_nested'][0], $default, $locked, $content );
  469.            
  470.             $title_templ = $this->update_option_lockable( 'title', $locked );
  471.             $content_templ = $this->update_option_lockable( 'content', $locked );
  472.            
  473.             extract( av_backend_icon( array( 'args' => $attr ) ) ); // creates $font and $display_char if the icon was passed as param 'icon' and the font as 'font'
  474.  
  475.             $params['innerHtml']  = '';
  476.             $params['innerHtml'] .= "<div class='avia_title_container' data-update_element_template='yes'>";
  477.             $params['innerHtml'] .=     '<span ' . $this->class_by_arguments_lockable( 'icon_select', $attr, $locked ) . '>';
  478.             $params['innerHtml'] .=         '<span ' . $this->class_by_arguments_lockable( 'font', $font, $locked ) . '>';
  479.             $params['innerHtml'] .=             '<span ' . $this->update_option_lockable( array( 'icon', 'icon_fakeArg' ), $locked ) . " class='avia_tab_icon' >{$display_char}</span>";
  480.             $params['innerHtml'] .=         '</span>';
  481.             $params['innerHtml'] .=     '</span>';
  482.             $params['innerHtml'] .=     "<span class='avia_title_container_inner' {$title_templ} >{$attr['title']}</span>";
  483.             $params['innerHtml'] .= '</div>';
  484.  
  485.             $params['innerHtml'] .= "<div class='avia_content_container' {$content_templ}>";
  486.             $params['innerHtml'] .=     stripcslashes( $content );
  487.             $params['innerHtml'] .= '</div>';
  488.  
  489.             return $params;
  490.         }
  491.  
  492.         /**
  493.          * Frontend Shortcode Handler
  494.          *
  495.          * @param array $atts array of attributes
  496.          * @param string $content text within enclosing form of shortcode element
  497.          * @param string $shortcodename the shortcode found, when == callback name
  498.          * @return string $output returns the modified html string
  499.          */
  500.         function shortcode_handler( $atts, $content = '', $shortcodename = '', $meta = '' )
  501.         {
  502.             $default = array(
  503.                         'initial'   => '1',
  504.                         'position'  => 'top_tab',
  505.                         'boxed'     => 'border_tabs'
  506.                     );
  507.            
  508.             $locked = array();
  509.             Avia_Element_Templates()->set_locked_attributes( $atts, $this, $shortcodename, $default, $locked, $content );
  510.             Avia_Element_Templates()->add_template_class( $meta, $atts, $default );
  511.            
  512.             $this->screen_options = AviaHelper::av_mobile_sizes( $atts );
  513.             extract( $this->screen_options ); //return $av_font_classes, $av_title_font_classes and $av_display_classes
  514.  
  515.             $atts = shortcode_atts( $default, $atts, $this->config['shortcode'] );
  516.             extract( $atts );
  517.            
  518.  
  519.             $boxed = $position != 'top_tab' ? $boxed : '';
  520.             $output = '<div ' . $meta['custom_el_id'] . ' class="tabcontainer  ' . $av_display_classes . ' ' . $position . ' ' . $boxed . ' ' . $meta['el_class'] . '" role="tablist">' . "\n";
  521.             $counter = 1;
  522.        
  523.             $tab_sc = ShortcodeHelper::shortcode2array( $content, 1 );
  524.            
  525.             if( ! is_numeric( $initial ) || ( $initial < 1 ) )
  526.             {
  527.                 $initial = 1;
  528.             }
  529.             if( $initial > count( $tab_sc ) )
  530.             {
  531.                 $initial = count( $tab_sc );
  532.             }
  533.  
  534.             avia_sc_tab::$counter = 1;
  535.             avia_sc_tab::$initial = $initial;
  536.  
  537.             $output .= ShortcodeHelper::avia_remove_autop( $content, true );
  538.  
  539.             $output .= "</div>\n";
  540.  
  541.             return $output;
  542.         }
  543.  
  544.         /**
  545.          * Shortcode handler
  546.          *
  547.          * @param array $atts
  548.          * @param string $content
  549.          * @param string $shortcodename
  550.          * @return string
  551.          */
  552.         public function av_tab( $atts, $content = '', $shortcodename = '' )
  553.         {
  554.             /**
  555.              * Fixes a problem when 3-rd party plugins call nested shortcodes without executing main shortcode  (like YOAST in wpseo-filter-shortcodes)
  556.              */
  557.             if( empty( $this->screen_options ) )
  558.             {
  559.                return '';
  560.             }
  561.            
  562.             $default = array(
  563.                         'title'         => '',
  564.                         'icon_select'   => 'no',
  565.                         'icon'          => '',
  566.                         'custom_id'     => '',
  567.                         'font'          => '',
  568.                         'custom_markup' => '',
  569.                         'skip_markup'   => ''           //  'yes' if markup should be skipped. Used e.g. for privacy modal popup throwing errors in check on blog posts
  570.                     );
  571.            
  572.            
  573.             $locked = array();
  574.             Avia_Element_Templates()->set_locked_attributes( $atts, $this, $shortcodename, $default, $locked, $content );
  575.            
  576.             $tab_atts = shortcode_atts( $default, $atts, 'av_tab' );
  577.            
  578.  
  579.             $output = '';
  580.             $titleClass = '';
  581.             $contentClass = '';
  582.             $icon = '';
  583.             $markup_tab = '';
  584.             $markup_title = '';
  585.             $markup_text = '';
  586.            
  587.             $display_char = av_icon( $tab_atts['icon'], $tab_atts['font'] );
  588.  
  589.             $aria_content = 'aria-hidden="true"';
  590.  
  591.             if( is_numeric( avia_sc_tab::$initial ) && avia_sc_tab::$counter == avia_sc_tab::$initial )
  592.             {
  593.                 $titleClass   = 'active_tab';
  594.                 $contentClass = 'active_tab_content';
  595.                 $aria_content = 'aria-hidden="false"';
  596.             }
  597.  
  598.             if( empty( $tab_atts['title'] ) )
  599.             {
  600.                 $tab_atts['title'] = avia_sc_tab::$counter;
  601.             }
  602.  
  603.             if( $tab_atts['icon_select'] == 'yes' )
  604.             {
  605.                 $icon = "<span class='tab_icon' {$display_char}></span>";
  606.             }
  607.  
  608.             $setting_id = Avia_Builder()->get_developer_settings( 'custom_id' );
  609.             if( empty( $tab_atts['custom_id'] ) || in_array( $setting_id, array( 'deactivate' ) ) )
  610.             {
  611.                 $tab_atts['custom_id'] = 'tab-id-' . avia_sc_tab::$tab_id++;
  612.             }
  613.             else
  614.             {
  615.                 $tab_atts['custom_id'] = AviaHelper::save_string( $tab_atts['custom_id'], '-' );
  616.             }
  617.  
  618.             if( 'yes' != $tab_atts['skip_markup'] )
  619.             {
  620.                 $markup_tab = avia_markup_helper( array( 'context' => 'entry', 'echo' => false, 'custom_markup' => $tab_atts['custom_markup'] ) );
  621.                 $markup_title = avia_markup_helper( array( 'context' => 'entry_title', 'echo' => false, 'custom_markup' => $tab_atts['custom_markup'] ) );
  622.                 $markup_text = avia_markup_helper( array( 'context' => 'entry_content', 'echo' => false, 'custom_markup' => $tab_atts['custom_markup'] ) );
  623.             }
  624.            
  625.             $output .= '<section class="av_tab_section" ' . $markup_tab . '>';
  626.             $output .=      '<h2 aria-controls="' . $tab_atts['custom_id'] . '-content" role="tab" tabindex="0" data-fake-id="#' . $tab_atts['custom_id'] . '" class="tab ' . $titleClass . '" ' . $markup_title . '>' . $icon.$tab_atts['title'] . "</h2>\n";
  627.             $output .=      '<div id="' . $tab_atts['custom_id'] . '-content" class="tab_content ' . $contentClass . '" ' . $aria_content . ">\n";
  628.             $output .=          '<div class="tab_inner_content invers-color" ' . $markup_text . ">\n";
  629.             $output .=              ShortcodeHelper::avia_apply_autop( ShortcodeHelper::avia_remove_autop( $content ) ) . "\n";
  630.             $output .=          "</div>\n";
  631.             $output .=      "</div>\n";
  632.             $output .=  "</section>\n";
  633.  
  634.             avia_sc_tab::$counter ++;
  635.  
  636.             return $output;
  637.         }
  638.  
  639.     }
  640. }
  641.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement