0, 'address' => 1, 'phone' => 2, 'email' => 3, 'link' => 4, // 'location' => 5, ); /** * TVD_Smart_DB constructor. */ public function __construct() { global $wpdb; $this->wpdb = $wpdb; $this->groups_table_name = $this->wpdb->prefix . 'td_groups'; $this->fields_table_name = $this->wpdb->prefix . 'td_fields'; $this->default_groups = $this->groups(); static::$icons = $this->icons(); } /** * Default icons * * return array */ public function icons() { return array( static::$types['text'] => 'text-new', static::$types['address'] => 'address-new', static::$types['phone'] => 'phone-new', static::$types['email'] => 'envelope-new', static::$types['link'] => 'link-new', // TVD_Smart_DB::$types['location'] => 'map-marker-solid', ); } /** * Default types * * return array */ public static function field_types() { $types = array(); foreach ( static::$types as $key => $type ) { $types[ static::$types[ $key ] ] = array( 'name' => $key, 'icon' => static::field_icon( static::$types[ $key ] ), 'key' => static::$types[ $key ], ); } return $types; } /** * Default fields and data * * return array */ public function groups() { return array( 'Company' => array( array( 'name' => 'Name', 'type' => static::$types['text'], 'identifier' => 'name', ), array( 'name' => 'Address', 'type' => static::$types['address'], 'identifier' => 'addr', ), array( 'name' => 'Phone number', 'type' => static::$types['phone'], 'data' => [ 'text' => 'Call', 'url' => '' ], 'identifier' => 'phone', ), array( 'name' => 'Alternative phone number', 'type' => static::$types['phone'], 'data' => [ 'text' => 'Call', 'url' => '' ], 'identifier' => 'alt_phone', ), array( 'name' => 'Email address', 'type' => static::$types['email'], 'data' => [ 'text' => 'Email', 'url' => '' ], 'identifier' => 'mail', ), // array( // 'name' => 'Map Location', // 'type' => TVD_Smart_DB::$types['location'], // ), ), 'Legal' => array( array( 'name' => 'Privacy policy', 'type' => static::$types['link'], 'data' => array( 'text' => 'Privacy policy', 'url' => '' ), 'identifier' => 'priv', ), array( 'name' => 'Disclaimer', 'type' => static::$types['link'], 'data' => array( 'text' => 'Disclaimer', 'url' => '' ), 'identifier' => 'disc', ), array( 'name' => 'Terms and conditions', 'type' => static::$types['link'], 'data' => array( 'text' => 'Terms and conditions', 'url' => '' ), 'identifier' => 'toc', ), array( 'name' => 'Contact', 'type' => static::$types['link'], 'data' => array( 'text' => 'Contact', 'url' => '' ), 'identifier' => 'contact', ), ), 'Social' => array( array( 'name' => 'Facebook page', 'icon' => 'facebook-brands-new', 'type' => static::$types['link'], 'identifier' => 'fb', ), array( 'name' => 'YouTube', 'icon' => 'youtube-brands-new', 'type' => static::$types['link'], 'identifier' => 'yt', ), array( 'name' => 'LinkedIn', 'icon' => 'linkedin-brands-new', 'type' => static::$types['link'], 'identifier' => 'in', ), array( 'name' => 'Pinterest', 'icon' => 'pinterest-brands-new', 'type' => static::$types['link'], 'identifier' => 'pin', ), array( 'name' => 'Instagram', 'icon' => 'instagram-brands-new', 'type' => static::$types['link'], 'identifier' => 'ig', ), array( 'name' => 'Xing', 'icon' => 'xing-brands-new', 'type' => static::$types['link'], 'identifier' => 'xing', ), array( 'name' => 'X', 'icon' => 'x-brands-new', 'type' => static::$types['link'], 'identifier' => 't', ), array( 'name' => 'TikTok', 'icon' => 'tiktok-brands-new', 'type' => static::$types['link'], 'identifier' => 'tiktok', ), array( 'name' => 'Bluesky', 'icon' => 'bluesky-brands-new', 'type' => static::$types['link'], 'identifier' => 'bluesky', ), ), ); } /** * Insert the default data in the db */ public function insert_default_data() { /** * We can't use the migration queries in the migration file because we have relationships, so we insert the data here */ $result = $this->wpdb->get_row( "SELECT `id` FROM $this->groups_table_name LIMIT 0,1", ARRAY_A ); /* if there's no entries in the table, this is the first ( 1.0.0 ) db update */ if ( empty( $result ) ) { foreach ( $this->default_groups as $group => $fields ) { /** * Insert the group */ $result = $this->wpdb->insert( $this->groups_table_name, array( 'name' => $group, 'is_default' => 1, ), array( '%s', ) ); $id = $this->wpdb->insert_id; if ( $result ) { /** * Insert the fields */ foreach ( $fields as $field ) { $this->wpdb->insert( $this->fields_table_name, array( 'name' => $field['name'], 'type' => $field['type'], 'identifier' => $field['identifier'], 'data' => empty( $field['data'] ) ? null : maybe_serialize( $field['data'] ), 'is_default' => 1, 'group_id' => $id, ), array( '%s', '%d', ) ); } } } } else { /* * there are entries in the table => this is the 1.0.X -> 1.0.(X+1) db upgrade * Insert 'Xing' and 'Twitter' manually, and populate the newly added 'identifier' column for each default field */ $xing_twitter_row = $this->wpdb->get_row( "SELECT * FROM $this->fields_table_name WHERE `identifier`='xing' OR `identifier`='t' LIMIT 0,1", ARRAY_A ); /* only continue if xing and twitter aren't already inserted */ if ( empty( $xing_twitter_row ) ) { $this->insert_xing_and_twitter_default_fields(); $this->add_string_identifier_to_fields(); } $tiktok_row = $this->wpdb->get_row( "SELECT * FROM $this->fields_table_name WHERE `identifier`='tiktok' LIMIT 0,1", ARRAY_A ); /* only continue if tiktok isn't inserted */ if ( empty( $tiktok_row ) ) { $this->add_tiktok_field(); } $bluesky_row = $this->wpdb->get_row( "SELECT * FROM $this->fields_table_name WHERE `identifier`='bluesky' LIMIT 0,1", ARRAY_A ); /* only continue if bluesky isn't inserted */ if ( empty( $bluesky_row ) ) { $this->add_bluesky_field(); } } } public function add_tiktok_field() { $format = array( '%s', '%d', ); $this->wpdb->insert( $this->fields_table_name, array( 'name' => 'TikTok', 'type' => static::$types['link'], 'identifier' => 'tiktok', 'is_default' => 1, 'group_id' => 3, ), $format ); } public function add_bluesky_field() { $format = array( '%s', '%d', ); $this->wpdb->insert( $this->fields_table_name, array( 'name' => 'Bluesky', 'type' => static::$types['link'], 'identifier' => 'bluesky', 'is_default' => 1, 'group_id' => 3, ), $format ); } /** * Insert the xing and twitter social fields and add their IDs to the 'id - string identifier' map */ private function insert_xing_and_twitter_default_fields() { $format = array( '%s', '%d', ); $this->wpdb->insert( $this->fields_table_name, array( 'name' => 'Xing', 'type' => static::$types['link'], 'identifier' => 'xing', 'is_default' => 1, 'group_id' => 3, ), $format ); $this->wpdb->insert( $this->fields_table_name, array( 'name' => 'X', 'type' => static::$types['link'], 'identifier' => 't', 'is_default' => 1, 'group_id' => 3, ), $format ); } /** * Add a string 'identifier' to the proper column for all the default field rows */ private function add_string_identifier_to_fields() { foreach ( $this->type_id_map as $id => $identifier ) { $this->wpdb->update( $this->fields_table_name, array( 'identifier' => $identifier ), array( 'id' => $id ) ); } } /** * Get groups with fields * * @param int $id * @param boolean $with_fields * * @return array|object|null */ public function get_groups( $id = 0, $with_fields = true ) { $args = array(); $query = 'SELECT * FROM ' . $this->groups_table_name; if ( $id ) { $where = ' WHERE id = %d'; $args[] = $id; } else { /** * We need this so WPDB won't complain about not preparing the data correctly */ $where = ' WHERE 1 = %d'; $args[] = 1; } $query .= $where; $results = $this->wpdb->get_results( $this->wpdb->prepare( $query, $args ), ARRAY_A ); /* I did not write this, I only rewrote it a bit, please don't assassinate me */ if ( $results && $with_fields ) { foreach ( $results as $group_index => $group ) { $group_name = $results[ $group_index ]['name']; $group_config = empty( $this->default_groups[ $group_name ] ) ? array() : $this->default_groups[ $group_name ]; $fields = $this->get_fields( $group ); if ( ! empty( $fields ) ) { foreach ( $fields as $index => $field ) { $field['group_name'] = $group['name']; if ( ! empty( $fields[ $index ]['name'] ) ) { $fields[ $index ]['name'] = $this->ensure_lowercase_label( $fields[ $index ]['name'] ); } $fields[ $index ]['formated_data'] = empty( $field['data'] ) ? '' : static::format_field_data( maybe_unserialize( $field['data'] ), $field ); $fields[ $index ]['data'] = empty( $field['data'] ) ? '' : maybe_unserialize( $field['data'] ); $field_config = empty( $field['identifier'] ) ? array() : $this->get_config_for_identifier( $group_config, $field['identifier'] ); if ( empty( $field_config ) || empty( $field_config['icon'] ) ) { $icon = static::field_icon( $field['type'] ); } else { $icon = dashboard_icon( $field_config['icon'], true ); } $fields[ $index ]['icon'] = $icon; $fields[ $index ]['default_field'] = empty( $field_config ) ? 0 : 1; } } $results[ $group_index ]['default_field'] = empty( $group_config ) ? 0 : 1; $results[ $group_index ]['fields'] = $fields; } } return $results; } /** * For the current identifier, search the array of configs and return the right one * * @param $default_group * @param $identifier * * @return array|mixed */ private function get_config_for_identifier( $default_group, $identifier ) { $config = array(); foreach ( $default_group as $index => $field ) { if ( ! empty( $field['identifier'] ) && $field['identifier'] === $identifier ) { $config = $field; break; } } return $config; } /** * Make sure some specific default labels ( that are stored in the DB ) are lowercase * * @param string $label * * @return string */ private function ensure_lowercase_label( $label ) { if ( $label === 'Terms and Conditions' ) { $label = 'Terms and conditions'; } else if ( $label === 'Facebook Page' ) { $label = 'Facebook page'; } return $label; } /** * @param $field_type * * @return mixed */ public static function field_icon( $field_type ) { return dashboard_icon( static::$icons[ $field_type ], true ); } public static function format_field_data( $field_data, $field, $args = array() ) { $data = ''; $unavailable = ''; if ( apply_filters( 'td_smartsite_shortcode_tooltip', false ) ) { $unavailable_name = empty( $field['group_name'] ) ? $field['name'] : '[' . $field['group_name'] . '] ' . $field['name']; $unavailable = '' . '' . '!' . '' . $unavailable_name . ''; if ( empty( $args['hide-tooltip'] ) ) { $unavailable .= '' . '' . __( 'This global variable hasn\'t been set. Define your global variables in the', 'thrive-dash' ) . '
' . '' . ' ' . __( ' Global Fields dashboard', 'thrive-dash' ) . '' . '
' . '
'; } } switch ( (int) $field['type'] ) { // text field case TVD_Smart_DB::$types['text']: $data = empty( $field_data['text'] ) ? $unavailable : $field_data['text']; break; //address field case TVD_Smart_DB::$types['address']: if ( empty( $field_data['address1'] ) ) { $data = $unavailable; } else { $address_fields = [ 'address1', 'address2', 'city', 'state', 'zip', 'country' ]; $field_data = array_replace( array_fill_keys( $address_fields, null ), $field_data ); $data = implode( empty( $args['multiline'] ) ? ', ' : '
', array_filter( $field_data ) ); } break; // phone field case TVD_Smart_DB::$types['phone']: $data = empty( $field_data['phone'] ) ? $unavailable : $field_data['phone']; break; // email field case TVD_Smart_DB::$types['email']: $data = empty( $field_data['email'] ) ? $unavailable : $field_data['email']; break; //link field case TVD_Smart_DB::$types['link']: if ( empty( $field_data['url'] ) ) { $data = $unavailable; } else { if ( empty( $args['prevent-link'] ) ) { $link_attr = TVD_Smart_Shortcodes::tvd_decode_link_attributes( $args ); $field_value = '' . $field_data['text'] . ''; } else { $field_value = $field_data['text']; } $data = $field_value; } break; // location field case TVD_Smart_DB::$types['location']: $url = 'https://maps.google.com/maps?q=' . urlencode( empty( $field_data['location'] ) ? 'New York' : $field_data['location'] ) . '&t=m&z=10&output=embed&iwloc=near'; $data = ''; break; } return $data; } /** * Get fields for group or by ID * * @param array $group * @param int $id * * @return array|object|null */ public function get_fields( $group = array(), $id = 0 ) { if ( $group ) { $where = ' WHERE group_id = %d'; $args[] = $group['id']; } else { /** * We need this so WPDB won't complain about not preparing the data correctly */ $where = ' WHERE 1 = %d'; $args[] = 1; } if ( $id ) { if ( is_numeric( $id ) ) { $where .= ' AND id = %d'; } else { $where .= ' AND identifier = %s'; } $args[] = $id; } $query = $this->wpdb->prepare( 'SELECT * FROM ' . $this->fields_table_name . $where, $args ); if ( ! $id ) { $results = $this->wpdb->get_results( $query, ARRAY_A ); } else { $results = $this->wpdb->get_row( $query, ARRAY_A ); } return $results; } /** * Get fields of a specific type which have some data * * @param array $group_id * @param int $type * * @return array|object|null */ public function get_fields_by_type( $group_id = array(), $type = 0 ) { if ( $type ) { $where = ' WHERE type = %d'; $args[] = $type; } else { return array(); } if ( $group_id ) { $where .= ' AND group_id = %d'; $args[] = $group_id; } else { $where .= ' AND 1 = %d'; $args[] = 1; } $query = $this->wpdb->prepare( 'SELECT * FROM ' . $this->fields_table_name . $where, $args ); return $this->wpdb->get_results( $query, ARRAY_A ); } public static function save_field( $model, $action ) { $rep = array( '%d', '%s', '%s', '%s', '%s', ); global $wpdb; // Add new field if ( $action === 'insert' ) { $model['created_at'] = date( 'Y-m-d h:i:s' ); $result = $wpdb->insert( $wpdb->prefix . 'td_fields', array( 'group_id' => $model['group_id'], 'name' => $model['name'], 'type' => $model['type'], 'data' => maybe_serialize( $model['data'] ), 'created_at' => $model['created_at'], ), $rep ); $model['id'] = (string) $wpdb->insert_id; } else { // Update existing field $model['updated_at'] = date( 'Y-m-d h:i:s' ); $result = $wpdb->update( $wpdb->prefix . 'td_fields', array( 'group_id' => (int) $model['group_id'], 'name' => $model['name'], 'type' => $model['type'], 'data' => maybe_serialize( $model['data'] ), 'updated_at' => $model['updated_at'], ), array( 'id' => $model['id'] ), $rep, array( '%d' ) ); } $model['formated_data'] = static::format_field_data( $model['data'], $model ); $model['icon'] = empty( $model['icon'] ) ? static::field_icon( $model['type'] ) : $model['icon']; return $result ? $model : false; } public static function delete_field( $id ) { global $wpdb; return $wpdb->delete( $wpdb->prefix . 'td_fields', array( 'id' => $id ) ); } public static function insert_group( $model ) { $model['created_at'] = date( 'Y-m-d h:i:s' ); global $wpdb; $result = $wpdb->insert( $wpdb->prefix . 'td_groups', array( 'name' => $model['name'], 'created_at' => $model['created_at'], ), array( '%s', '%s', ) ); $model['id'] = (string) $wpdb->insert_id; return $result ? $model : false; } public static function update_group( $model ) { global $wpdb; $model['updated_at'] = date( 'Y-m-d h:i:s' ); $result = $wpdb->update( $wpdb->prefix . 'td_groups', array( 'name' => $model['name'], 'updated_at' => $model['updated_at'], ), array( 'id' => $model['id'] ), array( '%s', '%s', ), array( '%d' ) ); return $result ? $model : false; } public static function delete_group( $id ) { global $wpdb; $result = $wpdb->delete( $wpdb->prefix . 'td_groups', array( 'id' => $id ) ); if ( $result ) { $wpdb->delete( $wpdb->prefix . 'td_fields', array( 'group_id' => $id ), array( '%d' ) ); } return $result; } /* * we're certain that these IDs have these identifiers because they were there from the start and were inserted in this specific order * the 'identifier' is the same as the one from the groups() function * in theory this should never be modified again, it's used only for backwards compatibility when upgrading the DB from 1.0.0 to 1.0.1 */ public $type_id_map = array( 1 => 'name', 2 => 'addr', 3 => 'phone', 4 => 'alt_phone', 5 => 'mail', 6 => 'priv', 7 => 'disc', 8 => 'toc', 9 => 'contact', 10 => 'fb', 11 => 'yt', 12 => 'in', 13 => 'pin', 14 => 'ig', ); }