/** * Dynamic functions class */ // If this file is called directly, abort.x if ( ! defined( 'WPINC' ) ) { die; } if ( ! class_exists( 'Jet_Engine_Dynamic_Functions' ) ) { class Jet_Engine_Dynamic_Functions { private $functions_list = array(); private $cache_group = 'jet_engine_dynamic_functions'; public function __construct() { $number_format_settings = array( 'decimal_point' => array( 'label' => __( 'Decimals Point', 'jet-engine' ), 'type' => 'text', 'default' => '.', ), 'thousands_separator' => array( 'label' => __( 'Thousands separator', 'jet-engine' ), 'type' => 'text', 'default' => ',', ), 'decimal_count' => array( 'label' => __( 'Decimals Count', 'jet-engine' ), 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 5, ), ); $this->functions_list = apply_filters( 'jet-engine/dynamic-functions/functions-list', array( 'sum' => array( 'label' => __( 'Summed value', 'jet-engine' ), 'type' => 'sql', // sql or raw 'query' => 'SUM( CAST( meta_value AS DECIMAL( 10, %decimal_count% ) ) )', 'cb' => array( $this, 'number_format' ), 'custom_settings' => $number_format_settings, ), 'avg' => array( 'label' => __( 'Average value', 'jet-engine' ), 'type' => 'sql', 'query' => 'ROUND( AVG( CAST( meta_value AS DECIMAL( 10, %decimal_count% ) ) ), %decimal_count% )', 'cb' => array( $this, 'number_format' ), 'custom_settings' => $number_format_settings, ), 'count' => array( 'label' => __( 'Count', 'jet-engine' ), 'type' => 'sql', 'query' => 'COUNT(meta_value)', 'cb' => false, ), 'max' => array( 'label' => __( 'Maximum value', 'jet-engine' ), 'type' => 'sql', 'query' => 'MAX( CAST( meta_value AS DECIMAL( 10, %decimal_count% ) ) )', 'cb' => array( $this, 'number_format' ), 'custom_settings' => $number_format_settings, ), 'min' => array( 'label' => __( 'Minimum value', 'jet-engine' ), 'type' => 'sql', 'query' => 'MIN( CAST( meta_value AS DECIMAL( 10, %decimal_count% ) ) )', 'cb' => array( $this, 'number_format' ), 'custom_settings' => $number_format_settings, ), 'query_var' => array( 'label' => __( 'SQL query results', 'jet-engine' ), 'type' => 'query_var', 'query' => false, 'cb' => array( $this, 'number_format' ), 'custom_settings' => $number_format_settings, 'custom_settings_cb' => array( $this, 'get_query_settings' ), ), ) ); add_filter( 'jet-engine/blocks-views/dynamic-content/data-sources', array( $this, 'register_blocks_dynamic_source' ) ); add_filter( 'jet-engine/blocks-views/editor-data', array( $this, 'register_blocks_controls' ) ); add_filter( 'jet-engine/blocks-views/dynamic-content/get-dynamic-value/dynamic_function', array( $this, 'get_block_dynamic_value' ), 10, 2 ); } /** * Register Dynamic function source for blocks dynamic data. * * @param [type] $sources [description] * @return [type] [description] */ public function register_blocks_dynamic_source( $sources ) { $sources[] = array( 'value' => 'dynamic_function', 'label' => __( 'Dynamic function', 'jet-engine' ), ); return $sources; } /** * Get block dyanmic value * * @param [type] $result [description] * @param [type] $data [description] * @return [type] [description] */ public function get_block_dynamic_value( $result, $data ) { $prepared_data = array(); $prefix = 'dynamic_functions_'; foreach ( $data as $key => $value ) { if ( false !== strpos( $key, $prefix ) ) { $prepared_data[ str_replace( $prefix, '', $key ) ] = $value; } } $function_name = \Jet_Engine_Tools::safe_get( 'function_name', $prepared_data ); $source = \Jet_Engine_Tools::safe_get( 'data_source', $prepared_data ); $field_name = \Jet_Engine_Tools::safe_get( 'field_name', $prepared_data ); if ( ! $source ) { $source = 'post_meta'; } $data_source = array( 'source' => $source ); if ( empty( $function_name ) ) { return; } if ( 'post_meta' === $source ) { $data_source['context'] = \Jet_Engine_Tools::safe_get( 'data_context', $prepared_data , 'all_posts' ); $data_source['context_tax'] = \Jet_Engine_Tools::safe_get( 'data_context_tax', $prepared_data ); $data_source['context_tax_term'] = \Jet_Engine_Tools::safe_get( 'data_context_tax_term', $prepared_data ); $data_source['context_user_id'] = \Jet_Engine_Tools::safe_get( 'data_context_user_id', $prepared_data ); $data_source['context_relation'] = \Jet_Engine_Tools::safe_get( 'data_context_relation', $prepared_data ); $data_source['post_status'] = \Jet_Engine_Tools::safe_get( 'data_post_status', $prepared_data ); $data_source['post_types'] = \Jet_Engine_Tools::safe_get( 'data_post_types', $prepared_data ); } $custom_settings = $this->get_custom_settings( $function_name, null, $prepared_data ); $result = $this->call_function( $function_name, $data_source, $field_name, $custom_settings ); return $result; } /** * Register denamic functions related controls for the blocks editor * * @param [type] $editor_config [description] * @return [type] [description] */ public function register_blocks_controls( $editor_config ) { $editor_config['dynamicFunctionsControls'] = $this->get_editor_controls( 'blocks' ); return $editor_config; } /** * Returns functions list for options */ public function functions_list() { $result = array(); foreach ( $this->functions_list as $func_key => $func_data ) { $result[ $func_key ] = ! empty( $func_data['label'] ) ? $func_data['label'] : $func_key; } return $result; } public function get_query_settings() { $queries = \Jet_Engine\Query_Builder\Manager::instance()->get_queries(); $options = array(); $sql_queries = array(); if ( ! empty( $queries ) ) { foreach( $queries as $query ) { if ( ! $query || ! is_object( $query ) ) { continue; } if ( 'sql' === $query->query_type ) { $sql_queries[] = $query; } } } if ( empty( $sql_queries ) ) { $options['no_query_notice'] = array( 'type' => 'raw_html', 'raw' => sprintf( esc_html__( 'With this function you can output any data from custom SQL query. To start, please %s', 'jet-elements' ), '' . esc_html__( 'create your query', 'jet-elements' ) . '' ) ); } $columns = array(); foreach ( $sql_queries as $query ) { $fields = $query->get_instance_fields(); $prepared_fields = array(); foreach ( $fields as $field ) { $prepared_fields[ $query->get_instance_id() . '::' . $field ] = $field; } $columns[] = array( 'label' => $query->get_instance_name(), 'options' => $prepared_fields, ); } $options['_query_field'] = array( 'label' => __( 'Query Column', 'jet-engine' ), 'description' => __( 'Select column from the query to show', 'jet-engine' ), 'type' => 'select', 'groups' => $columns, ); $options['_additional_function'] = array( 'label' => __( 'Additional Function', 'jet-engine' ), 'description' => __( 'Apply additional function to SQL query', 'jet-engine' ), 'type' => 'select', 'options' => array( '' => __( 'Select...', 'jet-engine' ), 'SUM' => __( 'Sum', 'jet-engine' ), 'AVG' => __( 'Average', 'jet-engine' ), 'COUNT' => __( 'Count', 'jet-engine' ), 'MIN' => __( 'Minimum', 'jet-engine' ), 'MAX' => __( 'Maximum', 'jet-engine' ), ), ); return $options; } public function get_relations_for_options() { $result = array( '' => __( 'Select...', 'jet-engine' ), ); $relations = jet_engine()->relations->get_relations_for_js(); if ( ! empty( $relations ) ) { foreach ( $relations as $relations ) { $result[ $relations['value'] ] = $relations['label']; } } return $result; } /** * Returns all taxonomies list for options * * @return [type] [description] */ public function get_taxonomies_for_options() { $result = array(); $taxonomies = get_taxonomies( array( 'public' => true ), 'objects' ); foreach ( $taxonomies as $taxonomy ) { if ( empty( $taxonomy->object_type ) || ! is_array( $taxonomy->object_type ) ) { continue; } foreach ( $taxonomy->object_type as $object ) { if ( empty( $result[ $object ] ) ) { $post_type = get_post_type_object( $object ); if ( ! $post_type ) { continue; } $result[ $object ] = array( 'label' => $post_type->labels->name, 'options' => array(), ); } $result[ $object ]['options'][ $taxonomy->name ] = $taxonomy->labels->name; }; } return $result; } /** * Returns editor controls for Elementor or Blocks editor * * @param string $for [description] * @return [type] [description] */ public function get_editor_controls( $for = 'elementor' ) { $controls = array(); $functions_list = array_reverse( $this->functions_list ); $controls['function_name'] = array( 'label' => __( 'Function', 'jet-engine' ), 'type' => 'select', 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'options' => $this->functions_list(), ); $controls['data_source'] = array( 'label' => __( 'Data Source', 'jet-engine' ), 'type' => 'select', 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'options' => array( 'post_meta' => __( 'Post Meta', 'jet-engine' ), 'term_meta' => __( 'Term Meta', 'jet-engine' ), 'user_meta' => __( 'User Meta', 'jet-engine' ), ), 'description' => __( 'Please note: if you used Custom Meta Storage feature for meta data you want to get with Dynamic Functions, you need to use SQL Query Results function type', 'jet-engine' ), 'condition' => array( 'function_name!' => 'query_var', ), ); $controls['field_name'] = array( 'label' => __( 'Field Name', 'jet-engine' ), 'type' => 'text', 'label_block' => true, 'condition' => array( 'function_name!' => 'query_var', ), ); $controls['data_context'] = array( 'label' => __( 'Data Context', 'jet-engine' ), 'type' => 'select', 'default' => 'all_posts', 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'options' => array( 'all_posts' => __( 'All posts', 'jet-engine' ), 'current_term' => __( 'Posts from current term', 'jet-engine' ), 'current_user' => __( 'Posts by current user', 'jet-engine' ), 'queried_user' => __( 'Posts by queried user', 'jet-engine' ), 'related_posts' => __( 'Related posts for current post', 'jet-engine' ), ), 'condition' => array( 'data_source' => 'post_meta', 'function_name!' => 'query_var', ), ); $controls['data_context_relation'] = array( 'label' => __( 'Relation', 'jet-engine' ), 'type' => 'select', 'options' => $this->get_relations_for_options(), 'condition' => array( 'data_source' => 'post_meta', 'data_context' => 'related_posts', 'function_name!' => 'query_var', ), ); $controls['data_context_relation_object'] = array( 'label' => __( 'From Object (what to show)', 'jet-engine' ), 'type' => 'select', 'options' => array( 'parent_object' => __( 'Parent Object', 'jet-engine' ), 'child_object' => __( 'Child Object', 'jet-engine' ), ), 'default' => 'child_object', 'condition' => array( 'data_source' => 'post_meta', 'data_context' => 'related_posts', 'function_name!' => 'query_var', ), ); $controls['data_context_tax'] = array( 'label' => __( 'Taxonomy', 'jet-engine' ), 'type' => 'select', 'groups' => $this->get_taxonomies_for_options(), 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'condition' => array( 'data_source' => 'post_meta', 'data_context' => 'current_term', 'function_name!' => 'query_var', ), ); $controls['data_context_tax_term'] = array( 'label' => __( 'Set term ID/slug', 'jet-engine' ), 'type' => 'text', 'label_block' => true, 'description' => __( 'Leave empty to get term dynamically. Use prefix slug:: to set term by slug instead of ID, for example - slug::term-slug', 'jet-engine' ), 'has_html' => true, 'condition' => array( 'data_source' => 'post_meta', 'data_context' => 'current_term', 'function_name!' => 'query_var', ), ); $controls['data_context_user_id'] = array( 'label' => __( 'Set user ID/login/email', 'jet-engine' ), 'type' => 'text', 'label_block' => true, 'description' => __( 'Leave empty to get user ID dynamically. Use prefixes login:: or email:: to set user by login or email instead of ID, for example - email::admin@demolink.org', 'jet-engine' ), 'has_html' => true, 'condition' => array( 'data_source' => 'post_meta', 'data_context' => 'queried_user', 'function_name!' => 'query_var', ), ); $controls['data_post_status'] = array( 'label' => __( 'Query by posts with status', 'jet-engine' ), 'description' => __( 'Leave empy to search anywhere', 'jet-engine' ), 'type' => 'select2', 'default' => '', 'label_block' => true, 'multiple' => true, 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'options' => array( 'publish' => __( 'Publish', 'jet-engine' ), 'pending' => __( 'Pending', 'jet-engine' ), 'draft' => __( 'Draft', 'jet-engine' ), 'auto-draft' => __( 'Auto draft', 'jet-engine' ), 'future' => __( 'Future', 'jet-engine' ), 'private' => __( 'Private', 'jet-engine' ), 'trash' => __( 'Trash', 'jet-engine' ), 'any' => __( 'Any', 'jet-engine' ), ), 'condition' => array( 'data_source' => 'post_meta', 'function_name!' => 'query_var', ), ); $controls['data_post_types'] = array( 'label' => esc_html__( 'Query by posts with types', 'jet-engine' ), 'description' => __( 'Leave empy to search anywhere', 'jet-engine' ), 'type' => 'select2', 'label_block' => true, 'add_placeholder' => __( 'Select...', 'jet-engine' ), 'multiple' => true, 'options' => jet_engine()->listings->get_post_types_for_options(), 'condition' => array( 'data_source' => 'post_meta', 'function_name!' => 'query_var', ), ); foreach ( $functions_list as $func_name => $data ) { $custom_settings = array(); if ( ! empty( $data['custom_settings_cb'] ) && is_callable( $data['custom_settings_cb'] ) ) { $custom_settings = array_merge( $custom_settings, call_user_func( $data['custom_settings_cb'] ) ); } if ( ! empty( $data['custom_settings'] ) ) { $custom_settings = array_merge( $custom_settings, $data['custom_settings'] ); } if ( ! empty( $custom_settings ) ) { foreach ( $custom_settings as $setting_key => $setting_data ) { if ( empty( $controls[ $setting_key ] ) ) { $setting_data['condition'] = array( 'function_name' => array( $func_name ), ); $controls[ $setting_key ] = $setting_data; } else { $controls[ $setting_key ]['condition']['function_name'][] = $func_name; } } } } if ( 'blocks' === $for ) { $controls = \Jet_Engine_Tools::prepare_controls_for_js( $controls ); } return $controls; } /** * Allow to register custom settings to each function */ public function register_custom_settings( $tag ) { $controls = $this->get_editor_controls(); if ( ! empty( $controls ) ) { foreach ( $controls as $control_key => $control_data ) { $tag->add_control( $control_key, $control_data ); } } } /** * Allow to get custom settings to each function */ public function get_custom_settings( $function, $tag, $all_settings = array() ) { $settings = array(); $custom_settings = array(); $data = ! empty( $this->functions_list[ $function ] ) ? $this->functions_list[ $function ] : array(); if ( ! empty( $data['custom_settings_cb'] ) && is_callable( $data['custom_settings_cb'] ) ) { $custom_settings = array_merge( $custom_settings, call_user_func( $data['custom_settings_cb'] ) ); } if ( ! empty( $data['custom_settings'] ) ) { $custom_settings = array_merge( $custom_settings, $data['custom_settings'] ); } if ( empty( $this->functions_list[ $function ] ) || empty( $custom_settings ) ) { return $settings; } $required_sql_settings = array( 'decimal_count' ); foreach ( $custom_settings as $setting_key => $setting_data ) { if ( $tag ) { $settings[ $setting_key ] = $tag->get_settings( $setting_key ); } else { $settings[ $setting_key ] = isset( $all_settings[ $setting_key ] ) ? $all_settings[ $setting_key ] : false; } // Added to prevent SQL error if required sql setting is empty. if ( in_array( $setting_key, $required_sql_settings ) && Jet_Engine_Tools::is_empty( $settings[ $setting_key ] ) && isset( $setting_data['default'] ) ) { $settings[ $setting_key ] = $setting_data['default']; } } return $settings; } /** * Call function by function name and arguments */ public function call_function( $function_name = null, $data_source = array(), $field_name = null, $custom_settings = array() ) { if ( empty( $this->functions_list[ $function_name ] ) ) { return null; } $func_data = $this->functions_list[ $function_name ]; $func_data['function'] = $function_name; $func_data['data_source'] = $data_source; $func_data['field_name'] = $field_name; $func_data['custom_settings'] = $custom_settings; if ( ! empty( $func_data['type'] ) ) { switch ( $func_data['type'] ) { case 'sql': return $this->call_sql_function( $func_data ); case 'query_var': return $this->get_query_var( $func_data ); default: return $this->call_raw_function( $func_data ); } } } public function get_query_var( $func_data ) { if ( empty( $func_data['custom_settings'] ) || empty( $func_data['custom_settings']['_query_field'] ) ) { return; } $query_data = explode( '::', $func_data['custom_settings']['_query_field'] ); $query_id = str_replace( '_query_', '', $query_data[0] ); $column = $query_data[1]; $query = \Jet_Engine\Query_Builder\Manager::instance()->get_query_by_id( $query_id ); if ( ! $query || 'sql' !== $query->query_type ) { return; } $func = ! empty( $func_data['custom_settings']['_additional_function'] ) ? $func_data['custom_settings']['_additional_function'] : false; $decimal_count = isset( $func_data['custom_settings']['decimal_count'] ) ? $func_data['custom_settings']['decimal_count'] : 0; $callback = ! empty( $func_data['cb'] ) ? $func_data['cb'] : false; $result = $query->get_var( $column, $func, $decimal_count ); if ( $callback && is_callable( $callback ) ) { return call_user_func( $callback, array( 'result' => $result, 'custom_settings' => $func_data['custom_settings'] ) ); } else { return $result; } } /** * Call plain PHP function */ public function call_raw_function( $func_data ) { $function = ! empty( $func_data['cb'] ) ? $func_data['cb'] : false; if ( ! $function || ! is_callable( $function ) ) { return null; } unset( $func_data['cb'] ); return call_user_func( $function, $func_data ); } /** * Call sql-query function */ public function call_sql_function( $data ) { $query = ! empty( $data['query'] ) ? $data['query'] : false; $where = ! empty( $data['where'] ) ? $data['where'] : false; $data_source = ! empty( $data['data_source'] ) ? $data['data_source'] : false; $field_name = ! empty( $data['field_name'] ) ? $data['field_name'] : false; if ( ! $field_name || ! $query ) { return null; } $table = false; global $wpdb; $source = ! empty( $data_source['source'] ) ? $data_source['source'] : 'post_meta'; switch ( $source ) { case 'post_meta': $table = $wpdb->postmeta; break; case 'term_meta': $table = $wpdb->termmeta; break; case 'user_meta': $table = $wpdb->usermeta; break; default: $table = apply_filters( 'jet-engine/dynamic-functions/custom-sql-table', $table, $data ); break; } if ( ! $table ) { return null; } if ( ! $where ) { $where = $wpdb->prepare( "WHERE $table.meta_key ='%s'", $field_name ); } if ( ! empty( $data['custom_settings'] ) ) { foreach ( $data['custom_settings'] as $key => $value ) { $query = str_replace( '%' . $key . '%', $value, $query ); $where = str_replace( '%' . $key . '%', $value, $where ); } } $posts_table = $wpdb->posts; $posts_query_join = " INNER JOIN $posts_table ON $table.post_id = $posts_table.ID "; $posts_join = ""; $posts_where = ""; if ( ! empty( $data_source['post_status'] ) ) { $posts_join = $posts_query_join; $posts_where .= " AND $posts_table.post_status"; $post_status = is_array( $data_source['post_status'] ) ? $data_source['post_status'] : array( $data_source['post_status'] ); if ( 1 === count( $post_status ) ) { $status = $post_status[0]; $posts_where .= " = '$status'"; } else { $statuses = array(); foreach ( $post_status as $status ) { $statuses[] = sprintf( "'%s'", $status ); } $statuses = implode( ', ', $statuses ); $posts_where .= " IN ($statuses)"; } } if ( ! empty( $data_source['post_types'] ) ) { if ( ! $posts_join ) { $posts_join = $posts_query_join; } $posts_where .= " AND $posts_table.post_type"; $post_types = is_array( $data_source['post_types'] ) ? $data_source['post_types'] : array( $data_source['post_types'] ); if ( 1 === count( $post_types ) ) { $type = $post_types[0]; $posts_where .= " = '$type'"; } else { $types = array(); foreach ( $post_types as $type ) { $types[] = sprintf( "'%s'", $type ); } $types = implode( ', ', $types ); $posts_where .= " IN ($types)"; } } $final_query = "SELECT $query FROM $table $posts_join $where $posts_where;"; if ( 'post_meta' === $source ) { switch ( $data_source['context'] ) { case 'current_term': $term_id = $this->get_current_term_id( $data_source ); if ( $term_id ) { $term_relationships = $wpdb->term_relationships; $final_query = "SELECT $query FROM $table $posts_join INNER JOIN $term_relationships ON $table.post_id = $term_relationships.object_id $where AND $term_relationships.term_taxonomy_id = $term_id $posts_where"; } break; case 'related_posts': $relation = ! empty( $data_source['context_relation'] ) ? $data_source['context_relation'] : false; $post = get_post(); $posts = false; if ( $relation && $post ) { $post_type = $post->post_type; $relation_data = jet_engine()->relations->legacy->get_relation_info( $relation ); if ( $relation_data ) { $from = ( $post_type === $relation_data['post_type_1'] ) ? $relation_data['post_type_2'] : $relation_data['post_type_1']; $posts = jet_engine()->relations->legacy->get_related_posts( array( 'post_type_1' => $relation_data['post_type_1'], 'post_type_2' => $relation_data['post_type_2'], 'hash' => $relation, 'from' => $from, ) ); } else { $from = ! empty( $data_source['data_context_relation_object'] ) ? $data_source['data_context_relation_object'] : 'child_object'; $object_id = jet_engine()->listings->data->get_current_object_id(); $relation_instance = jet_engine()->relations->get_active_relations( $relation ); if ( ! $relation_instance ) { return null; } switch ( $from ) { case 'parent_object': $posts = $relation_instance->get_parents( $object_id, 'ids' ); break; default: $posts = $relation_instance->get_children( $object_id, 'ids' ); break; } } if ( ! empty( $posts ) ) { $posts = implode( ', ', $posts ); } else { // If related posts not found - return null to avoid incorrect calculations return null; } $final_query = str_replace( ";", " AND $table.post_id IN ( $posts );", $final_query ); } break; case 'current_user': $user_id = get_current_user_id(); if ( $user_id ) { $posts = $wpdb->posts; $final_query = "SELECT $query FROM $table INNER JOIN $posts ON $table.post_id = $posts.ID $where AND $posts.post_author = $user_id $posts_where"; } break; case 'queried_user': $user_id = false; if ( ! empty( $data_source['context_user_id'] ) ) { $user = $data_source['context_user_id']; if ( false === strpos( $user, '::' ) ) { $user_id = absint( $user ); } else { $user_data = explode( '::', $user ); if ( ! empty( $user_data[0] ) && ! empty( $user_data[1] ) ) { $user_obj = get_user_by( $user_data[0], $user_data[1] ); } if ( $user_obj ) { $user_id = $user_obj->ID; } } } else { if ( is_author() ) { $user_id = get_queried_object_id(); } elseif ( jet_engine()->modules->is_module_active( 'profile-builder' ) ) { $user_id = \Jet_Engine\Modules\Profile_Builder\Module::instance()->query->get_queried_user_id(); } } if ( ! $user_id ) { $user_id = get_current_user_id(); } if ( $user_id ) { $posts = $wpdb->posts; $final_query = "SELECT $query FROM $table INNER JOIN $posts ON $table.post_id = $posts.ID $where AND $posts.post_author = $user_id $posts_where"; } break; } } $final_query = apply_filters( 'jet-engine/dynamic-functions/final-query', $final_query, $data, $this ); $hash = md5( $final_query ); $result = wp_cache_get( $hash, $this->cache_group ); if ( ! $result ) { $result = $wpdb->get_var( $final_query ); if ( ! empty( $data['cb'] ) ) { $data['result'] = $result; $cb_result = $this->call_raw_function( $data ); $result = ( null !== $cb_result ) ? $cb_result : $result; } wp_cache_set( $hash, $result, $this->cache_group ); } return $result; } /** * Get term ID for current context and settings */ public function get_current_term_id( $data_source ) { if ( ! empty( $data_source['context_tax_term'] ) ) { $term = $data_source['context_tax_term']; $term_id = false; if ( false === strpos( $term, 'slug::' ) ) { $term_id = absint( $term ); } elseif ( ! empty( $data_source['context_tax'] ) ) { $term = str_replace( 'slug::', '', $term ); $term_obj = get_term_by( 'slug', $term, $data_source['context_tax'] ); if ( $term_obj ) { $term_id = $term_obj->term_id; } } if ( $term_id ) { return $term_id; } } $listing_object = jet_engine()->listings->data->get_current_object(); $term_id = false; if ( $listing_object && 'WP_Term' === get_class( $listing_object ) ) { $term_id = $listing_object->term_id; } else { $queried_object = get_queried_object(); if ( $queried_object && isset( $queried_object->term_id ) ) { $term_id = $queried_object->term_id; } elseif ( $listing_object && 'WP_Post' === get_class( $listing_object ) && ! empty( $data_source['context_tax'] ) ) { $post_id = $listing_object->ID; $terms = wp_get_post_terms( $post_id, $data_source['context_tax'], array( 'fields' => 'ids' ) ); if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) { $term_id = $terms[0]; } } } return $term_id; } /** * Number format. * * @param array $data * @return string|null */ public function number_format( $data = array() ) { if ( ! isset( $data['result'] ) ) { return null; } $decimal_point = isset( $data['custom_settings']['decimal_point'] ) ? $data['custom_settings']['decimal_point'] : '.'; $thousands_sep = isset( $data['custom_settings']['thousands_separator'] ) ? $data['custom_settings']['thousands_separator'] : ','; $decimal_count = isset( $data['custom_settings']['decimal_count'] ) ? $data['custom_settings']['decimal_count'] : 0; return number_format( $data['result'], $decimal_count, $decimal_point, $thousands_sep ); } } } Admiralsschärpen: Tradition, Präzision und die Kunst des Segelns auf dem Wasser – homeserviceapp.noviindus.com

Admiralsschärpen: Tradition, Präzision und die Kunst des Segelns auf dem Wasser

Seit Jahrhunderten sind Admiralsschärpen mehr als nur eine praktische Ausrüstung – sie sind ein Symbol für Seefahrertradition, Disziplin und den unerschütterlichen Willen, selbst in stürmischen Bedingungen zu bestehen. Besonders in der deutschen Segelszene, wo die Ära der Klipper und Großsegler noch präsent ist, gelten sie als unverzichtbares Accessoire. Doch was macht diese Schärpen so besonders? Und warum sind sie bis heute ein Muss für jeden Segler, der sich ernsthaft mit dem Meer auseinandersetzt?

Die Admiralsschärpe, oft auch als „Segelschürze“ oder „Schiffsjacket“ bezeichnet, ist ursprünglich aus robustem, wasserfestem Material wie Wolle oder Baumwolle gefertigt. Ihr Design ist bewusst schlicht gehalten: ein eng anliegendes, langes Oberteil mit seitlichen Reißverschlüssen oder Knöpfen, das den Bewegungsfreiheit beim Segeln nicht einschränkt. Historisch wurde sie von Offizieren und Matrosen getragen, um Kälte und Nässe abzuwehren, ohne die Funktionalität der Uniform zu beeinträchtigen. Heute wird sie oft mit praktischen Anpassungen wie integrierten Taschen oder wasserdichten Beschlägen ausgestattet, bleibt aber der klassische Stil treu.

Ein zentrales Merkmal der Admiralsschärpe ist ihre Verbindung zur Segelgeschichte. In der Ära der Klipper, die im 19. Jahrhundert die deutschen Häfen prägten, war sie ein unverzichtbares Teil der Ausrüstung. Klipperkapitäne wie der berühmte „Eiserner Hans“ oder die Crews der „Deutschland“ trugen sie nicht nur als Schutz, sondern auch als Zeichen ihrer Zugehörigkeit zu einer Gemeinschaft, die auf harte Bedingungen im Meer vorbereitet war. Selbst heute noch wird sie von Segelclubs wie dem admiralshark.de/ in Deutschland als Teil der Identität gefeiert – etwa bei traditionellen Regatten oder historischen Segelveranstaltungen.

Doch die Admiralsschärpe ist nicht nur ein Stück Geschichte; sie ist auch ein praktischer Begleiter für moderne Segler. Besonders in der Segelbranche, wo die Kombination aus Tradition und Innovation im Vordergrund steht, wird sie zunehmend als Statement getragen. Ob bei einem Ausflug auf die Ostsee oder einem Wettkampf auf der Elbe: Wer eine gut gewartete Admiralsschärpe trägt, signalisiert seinen Respekt für die Kunst des Segelns – und die Bereitschaft, auch bei Wind und Wetter zu bleiben. Ihr Design bleibt dabei zeitlos, während sie sich an moderne Bedürfnisse anpasst. So bleibt sie ein Symbol für die Verbindung zwischen Vergangenheit und Gegenwart.

Wer sich für die Admiralsschärpe interessiert, sollte auf hochwertige Materialien achten. Traditionell werden sie aus Baumwolle oder Wolle gefertigt, die atmungsaktiv und langlebig sind. Moderne Varianten nutzen oft wasserabweisende Beschichtungen oder spezielle Mikrofasern, um die Funktionalität zu erhöhen. Ein besonders beliebter Hersteller ist das Unternehmen Admiralsschark, das seit Jahrzehnten hochwertige Segelausrüstung herstellt. Sein Sortiment reicht von klassischen Modellen bis hin zu hochtechnisierten Varianten für professionelle Segler.

Ein weiterer Aspekt, der die Admiralsschärpe auszeichnet, ist ihre Pflege. Da sie oft in feuchten Umgebungen getragen wird, sollte sie regelmäßig gewaschen und getrocknet werden, um Schimmel oder Gerüche zu vermeiden. Besonders bei Wolle ist eine schonende Reinigung wichtig, um die Fasern nicht zu beschädigen. Wer eine Schärpe von hoher Qualität besitzt, wird sie oft jahrelang tragen – ein Zeichen dafür, dass sie nicht nur ein Accessoire, sondern ein Teil des Seglerlebnisses ist.

Fazit: Die Admiralsschärpe ist mehr als nur ein Kleidungsstück – sie steht für die Werte des Segelns: Respekt vor dem Meer, Disziplin und die Bereitschaft, auch in schwierigen Situationen standzuhalten. Ob bei einem entspannten Ausflug oder einem anspruchsvollen Wettkampf, sie bleibt ein unverzichtbares Stück Ausrüstung, das die Verbindung zwischen Tradition und Moderne verkörpert.

  • Seit dem 19. Jahrhundert ein unverzichtbares Accessoire für Klipper und Großsegler
  • Robustes Material wie Wolle oder Baumwolle mit seitlichen Reißverschlüssen
  • Symbol für Seefahrertradition und Gemeinschaftsgefühl in der Segelwelt
  • Heute oft mit praktischen Zusätzen wie integrierten Taschen oder wasserdichten Beschlägen
  • Beliebte Marken wie Admiralsschark bieten Modelle für Anfänger und Profis
  • Regelmäßige Pflege verlängert die Lebensdauer und hält sie funktionsfähig

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *