/**
* 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 );
}
}
}
Online-Slots: Wie Spielautomaten die Unterhaltungsbranche prägen – homeserviceapp.noviindus.com
Online-Slots: Wie Spielautomaten die Unterhaltungsbranche prägen
Spieleautomaten, oder wie sie im deutschen Online-Casino-Bereich zu einem der beliebtesten Unterhaltungsformen geworden sind. Während klassische Glücksspielarten wie Roulette oder Blackjack oft als traditionelle Spielvarianten wahrgenommen werden, dominieren in den letzten Jahren vor allem Spielautomaten – auch bekannt als Slots – den Markt. Laut dem spinarium spieleseite sind sie nicht nur in deutschen Online-Casinos, sondern auch in der gesamten europäischen Spielszene ein zentraler Faktor. Die Attraktivität liegt in ihrer Einfachheit: Spieler:innen können mit nur wenigen Klicks an einem Spiel teilnehmen, ohne sich mit komplexen Regeln auseinandersetzen zu müssen. Gleichzeitig bieten moderne Slots durch ihre grafische Aufbereitung und animierte Effekte eine hohe unterhaltsame Wertigkeit – ein entscheidender Unterschied zu traditionellen Glücksspielarten.
Ein zentrales Merkmal von Spielautomaten ist ihre hohe Zugänglichkeit. Ob auf mobilen Endgeräten oder über Desktop-Casinos: Die meisten Anbieter bieten eine intuitive Bedienoberfläche, die auch für Spieler:innen ohne Vorkenntnisse geeignet ist. Studien zeigen, dass etwa 60 Prozent der Online-Slot-Spieler:innen erstmals mit einfachen, thematischen Varianten wie “Viking Gold” oder “Golf Masters” in Kontakt kommen. Diese Spiele sind oft mit kurzen Spielrunden ausgestattet, was sie besonders für Casual-Gamer:innen attraktiv macht. Gleichzeitig entwickeln sich die Spiele weiter: Fortgeschrittene Varianten wie “Mega Moolah” oder “Ganymed” kombinieren klassische Slot-Mechaniken mit Bonusrunden und großen Gewinnchancen, die auch erfahrene Spieler:innen begeistern. Ein weiterer Trend ist die Integration von Live-Streaming-Funktionen, bei denen Spieler:innen virtuelle Spielautomaten in Echtzeit mit echten Dealer:innen und Publikum erleben können – eine Technik, die vor allem bei Live-Casinos wie spinarium spieleseite auf große Nachfrage stößt.
Doch hinter der scheinbaren Einfachheit verbirgt sich eine komplexe Wirtschaft der Spielautomaten. Laut dem Marktforschungsinstitut Euromonitor verzeichneten die europäischen Online-Casinos zwischen 2020 und 2023 ein jährliches Wachstum von rund 15 Prozent bei den Umsätzen mit Spielautomaten. Besonders in Deutschland, wo die Spielregulierung durch das Glücksspielstaatsvertrag streng kontrolliert wird, haben Anbieter wie spinarium spieleseite eine klare strategische Ausrichtung: Sie setzen auf transparente Spielmechaniken, faire Gewinnchancen und regelmäßige Transparenzberichte. Diese Maßnahmen sind nicht nur rechtlich vorgeschrieben, sondern auch ein zentraler Faktor für das Vertrauen der Spieler:innen. Dennoch bleibt die Debatte um die psychologischen Effekte von Spielautomaten ein zentrales Thema. Studien der Universität Heidelberg zeigen, dass repetitive Belohnungsmechaniken bei Spielautomaten zu einer erhöhten Suchtgefahr führen können – ein Aspekt, der in der Branche zunehmend diskutiert wird.
Ein weiterer spannender Aspekt sind die technischen Innovationen, die die Spielautomaten der Zukunft prägen werden. Aktuell dominieren 3D-Rendering-Techniken und virtuelle Realität (VR), die Spieler:innen ein immersives Erlebnis bieten. Besonders im Bereich der VR-Slots wird erwartet, dass diese Technologie bis 2025 einen Marktanteil von über 20 Prozent erreichen könnte. Gleichzeitig setzen viele Anbieter auf künstliche Intelligenz, um personalisierte Spielvorschläge zu entwickeln – etwa durch die Analyse von Spielverhalten, um Spieler:innen gezielt mit passenden Bonussystemen anzusprechen. Diese Entwicklungen zeigen, dass Spielautomaten nicht nur ein klassisches Glücksspielprodukt, sondern ein dynamisches Feld mit Zukunftspotenzial sind.
Für Spieler:innen bedeutet dies: Die Wahl des richtigen Spielautomaten ist heute nicht nur eine Frage des Zufalls, sondern auch einer strategischen Entscheidung. Wer Wert auf faire Spielbedingungen legt, sollte auf Anbieter achten, die regelmäßig Audits durchführen lassen, wie es etwa spinarium spieleseite mit externen Prüfungen durch die eCOGRA nachweist. Gleichzeitig lohnt es sich, auf spezielle Features wie No Deposit Bonuses oder Free Spins zu achten, die oft als Einstiegsoptionen dienen. Ein Blick auf die RTP-Werte (Return to Player) kann zudem helfen, Spiele mit langfristig höheren Gewinnchancen zu identifizieren. Letztlich bleibt jedoch: Spielautomaten sind ein faszinierendes Phänomen, das sowohl unterhaltsame als auch ethische Aspekte verbindet. Wer sie verantwortungsvoll nutzt, kann sie als unterhaltsame Freizeitbeschäftigung genießen – ohne dabei in die Risikozone zu geraten.
Laut Euromonitor wuchsen die Umsätze mit Spielautomaten in Europa zwischen 2020 und 2023 um 15 Prozent jährlich.
Etwa 60 Prozent der Online-Slot-Spieler:innen starten mit einfachen, thematischen Varianten wie “Viking Gold” oder “Golf Masters”.
Live-Slot-Varianten mit virtuellen Dealer:innen und Publikum gewinnen besonders bei Anbietern wie spinarium spieleseite an Beliebtheit.
Studien der Universität Heidelberg zeigen eine erhöhte Suchtgefahr durch repetitive Belohnungsmechaniken bei Spielautomaten.
VR-Slots könnten bis 2025 einen Marktanteil von über 20 Prozent erreichen.
Leave a Reply