wp/wp-content/plugins/option-tree/includes/ot-functions-admin.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
--- a/wp/wp-content/plugins/option-tree/includes/ot-functions-admin.php	Mon Jun 08 16:11:51 2015 +0000
+++ b/wp/wp-content/plugins/option-tree/includes/ot-functions-admin.php	Tue Jun 09 03:35:32 2015 +0200
@@ -26,7 +26,7 @@
   function ot_register_theme_options_page() {
   
     /* get the settings array */
-    $get_settings = get_option( 'option_tree_settings' );
+    $get_settings = get_option( ot_settings_id() );
     
     /* sections array */
     $sections = isset( $get_settings['sections'] ) ? $get_settings['sections'] : array();
@@ -42,7 +42,7 @@
       
       ot_register_settings( array(
           array(
-            'id'                  => 'option_tree',
+            'id'                  => ot_options_id(),
             'pages'               => array( 
               array(
                 'id'              => 'ot_theme_options',
@@ -56,10 +56,9 @@
                 'updated_message' => apply_filters( 'ot_theme_options_updated_message', __( 'Theme Options updated.', 'option-tree' ) ),
                 'reset_message'   => apply_filters( 'ot_theme_options_reset_message', __( 'Theme Options reset.', 'option-tree' ) ),
                 'button_text'     => apply_filters( 'ot_theme_options_button_text', __( 'Save Changes', 'option-tree' ) ),
-                'screen_icon'     => 'themes',
-                'contextual_help' => $contextual_help,
-                'sections'        => $sections,
-                'settings'        => $settings
+                'contextual_help' => apply_filters( 'ot_theme_options_contextual_help', $contextual_help ),
+                'sections'        => apply_filters( 'ot_theme_options_sections', $sections ),
+                'settings'        => apply_filters( 'ot_theme_options_settings', $settings )
               )
             )
           )
@@ -67,7 +66,7 @@
       );
       
       // Filters the options.php to add the minimum user capabilities.
-      add_filter( 'option_page_capability_option_tree', create_function( '$caps', "return '$caps';" ), 999 );
+      add_filter( 'option_page_capability_' . ot_options_id(), create_function( '$caps', "return '$caps';" ), 999 );
     
     }
   
@@ -88,7 +87,21 @@
 if ( ! function_exists( 'ot_register_settings_page' ) ) {
 
   function ot_register_settings_page() {
+    global $ot_has_custom_theme_options;
+    
+    // Display UI Builder admin notice
+    if ( OT_SHOW_OPTIONS_UI == true && isset( $_REQUEST['page'] ) && $_REQUEST['page'] == 'ot-settings' && ( $ot_has_custom_theme_options == true || has_action( 'admin_init', 'custom_theme_options' ) || has_action( 'init', 'custom_theme_options' ) ) ) {
+      
+      function ot_has_custom_theme_options() {
+    
+        echo '<div class="error"><p>' . __( 'The Theme Options UI Builder is being overridden by a custom file in your theme. Any changes you make via the UI Builder will not be saved.', 'option-tree' ) . '</p></div>';
+        
+      }
+      
+      add_action( 'admin_notices', 'ot_has_custom_theme_options' );
   
+    }
+    
     // Create the filterable pages array
     $ot_register_pages_array =  array( 
       array( 
@@ -97,7 +110,7 @@
         'menu_title'      => __( 'OptionTree', 'option-tree' ),
         'capability'      => 'edit_theme_options',
         'menu_slug'       => 'ot-settings',
-        'icon_url'        => OT_URL . '/assets/images/ot-logo-mini.png',
+        'icon_url'        => null,
         'position'        => 61,
         'hidden_page'     => true
       ),
@@ -114,7 +127,6 @@
         'reset_message'   => __( 'Theme Options reset.', 'option-tree' ),
         'button_text'     => __( 'Save Settings', 'option-tree' ),
         'show_buttons'    => false,
-        'screen_icon'     => 'themes',
         'sections'        => array(
           array(
             'id'          => 'create_setting',
@@ -209,7 +221,6 @@
         'reset_message'   => __( 'Theme Options reset.', 'option-tree' ),
         'button_text'     => __( 'Save Settings', 'option-tree' ),
         'show_buttons'    => false,
-        'screen_icon'     => 'themes',
         'sections'        => array(
           array(
             'id'          => 'creating_options',
@@ -371,7 +382,7 @@
     // Register the pages.
     ot_register_settings( array(
         array(
-          'id'              => 'option_tree_settings',
+          'id'              => ot_settings_id(),
           'pages'           => $ot_register_pages_array
         )
       )
@@ -400,7 +411,7 @@
     if ( apply_filters( 'ot_theme_options_menu_slug', 'ot-theme-options' ) == $page && $updated ) {
       
       /* grab a copy of the theme options */
-      $options = get_option( 'option_tree' );
+      $options = get_option( ot_options_id() );
       
       /* execute the action hook and pass the theme options to it */
       do_action( 'ot_after_theme_options_save', $options );
@@ -466,37 +477,254 @@
       
       $input['background-image'] = ot_validate_setting( $input['background-image'], 'upload', $field_id );
       
+      // Loop over array and check for values
+      foreach( (array) $input as $key => $value ) {
+        if ( ! empty( $value ) ) {
+          $has_value = true;
+        }
+      }
+      
+      // No value; set to empty
+      if ( ! isset( $has_value ) ) {
+        $input = '';
+      }
+    
+    } else if ( 'border' == $type ) {
+      
+      // Loop over array and set errors or unset key from array.
+      foreach( $input as $key => $value ) {
+        
+        // Validate width
+        if ( $key == 'width' && ! empty( $value ) && ! is_numeric( $value ) ) {
+          
+          $input[$key] = '0';
+          
+          add_settings_error( 'option-tree', 'invalid_border_width', sprintf( __( 'The %s input field for %s only allows numeric values.', 'option-tree' ), '<code>width</code>', '<code>' . $field_id . '</code>' ), 'error' );
+          
+        }
+        
+        // Validate color
+        if ( $key == 'color' && ! empty( $value ) ) {
+
+          $input[$key] = ot_validate_setting( $value, 'colorpicker', $field_id );
+          
+        }
+        
+        // Unset keys with empty values.
+        if ( empty( $value ) && strlen( $value ) == 0 ) {
+          unset( $input[$key] );
+        }
+        
+      }
+      
+      if ( empty( $input ) ) {
+        $input = '';
+      }
+      
+    } else if ( 'box-shadow' == $type ) {
+      
+      // Validate inset
+      $input['inset'] = isset( $input['inset'] ) ? 'inset' : '';
+      
+      // Validate offset-x
+      $input['offset-x'] = ot_validate_setting( $input['offset-x'], 'text', $field_id );
+      
+      // Validate offset-y
+      $input['offset-y'] = ot_validate_setting( $input['offset-y'], 'text', $field_id );
+      
+      // Validate blur-radius
+      $input['blur-radius'] = ot_validate_setting( $input['blur-radius'], 'text', $field_id );
+      
+      // Validate spread-radius
+      $input['spread-radius'] = ot_validate_setting( $input['spread-radius'], 'text', $field_id );
+      
+      // Validate color
+      $input['color'] = ot_validate_setting( $input['color'], 'colorpicker', $field_id );
+      
+      // Unset keys with empty values.
+      foreach( $input as $key => $value ) {
+        if ( empty( $value ) && strlen( $value ) == 0 ) {
+          unset( $input[$key] );
+        }
+      }
+      
+      // Set empty array to empty string.
+      if ( empty( $input ) ) {
+        $input = '';
+      }
+      
     } else if ( 'colorpicker' == $type ) {
 
       /* return empty & set error */
-      if ( 0 === preg_match( '/^#([a-f0-9]{6}|[a-f0-9]{3})$/i', $input ) ) {
+      if ( 0 === preg_match( '/^#([a-f0-9]{6}|[a-f0-9]{3})$/i', $input ) && 0 === preg_match( '/^rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9\.]{1,4})\s*\)/i', $input ) ) {
         
         $input = '';
         
-        add_settings_error( 'option-tree', 'invalid_hex', __( 'The Colorpicker only allows valid hexadecimal values.', 'option-tree' ), 'error' );
+        add_settings_error( 'option-tree', 'invalid_hex', sprintf( __( 'The %s Colorpicker only allows valid hexadecimal or rgba values.', 'option-tree' ), '<code>' . $field_id . '</code>' ), 'error' );
       
       }
-    
-    } else if ( in_array( $type, array( 'css', 'text', 'textarea', 'textarea-simple' ) ) ) {
+      
+    } else if ( 'colorpicker-opacity' == $type ) {
+
+      // Not allowed
+      if ( is_array( $input ) ) {
+        $input = '';
+      }
+
+      // Validate color
+      $input = ot_validate_setting( $input, 'colorpicker', $field_id );
+
+    } else if ( in_array( $type, array( 'css', 'javascript', 'text', 'textarea', 'textarea-simple' ) ) ) {
       
       if ( ! current_user_can( 'unfiltered_html' ) && OT_ALLOW_UNFILTERED_HTML == false ) {
       
         $input = wp_kses_post( $input );
         
       }
-            
+    
+    } else if ( 'dimension' == $type ) {
+      
+      // Loop over array and set error keys or unset key from array.
+      foreach( $input as $key => $value ) {
+        if ( ! empty( $value ) && ! is_numeric( $value ) && $key !== 'unit' ) {
+          $errors[] = $key;
+        }
+        if ( empty( $value ) && strlen( $value ) == 0 ) {
+          unset( $input[$key] );
+        }
+      }
+
+      /* return 0 & set error */
+      if ( isset( $errors ) ) {
+        
+        foreach( $errors as $error ) {
+          
+          $input[$error] = '0';
+          
+          add_settings_error( 'option-tree', 'invalid_dimension_' . $error, sprintf( __( 'The %s input field for %s only allows numeric values.', 'option-tree' ), '<code>' . $error . '</code>', '<code>' . $field_id . '</code>' ), 'error' );
+          
+        }
+        
+      }
+      
+      if ( empty( $input ) ) {
+        $input = '';
+      }
+      
+    } else if ( 'google-fonts' == $type ) {
+      
+      unset($input['%key%']);
+      
+      // Loop over array and check for values
+      if ( is_array( $input ) && ! empty( $input ) ) {
+        $input = array_values( $input );
+      }
+
+      // No value; set to empty
+      if ( empty( $input ) ) {
+        $input = '';
+      }
+    
+    } else if ( 'link-color' == $type ) {
+      
+      // Loop over array and check for values
+      if ( is_array( $input ) && ! empty( $input ) ) {
+        foreach( $input as $key => $value ) {
+          if ( ! empty( $value ) ) {
+            $input[$key] = ot_validate_setting( $input[$key], 'colorpicker', $field_id . '-' . $key );
+            $has_value = true;
+          }
+        }
+      }
+      
+      // No value; set to empty
+      if ( ! isset( $has_value ) ) {
+        $input = '';
+      }
+               
     } else if ( 'measurement' == $type ) {
     
       $input[0] = sanitize_text_field( $input[0] );
       
+      // No value; set to empty
+      if ( empty( $input[0] ) && strlen( $input[0] ) == 0 && empty( $input[1] ) ) {
+        $input = '';
+      }
+      
+    } else if ( 'spacing' == $type ) {
+      
+      // Loop over array and set error keys or unset key from array.
+      foreach( $input as $key => $value ) {
+        if ( ! empty( $value ) && ! is_numeric( $value ) && $key !== 'unit' ) {
+          $errors[] = $key;
+        }
+        if ( empty( $value ) && strlen( $value ) == 0 ) {
+          unset( $input[$key] );
+        }
+      }
+
+      /* return 0 & set error */
+      if ( isset( $errors ) ) {
+        
+        foreach( $errors as $error ) {
+          
+          $input[$error] = '0';
+          
+          add_settings_error( 'option-tree', 'invalid_spacing_' . $error, sprintf( __( 'The %s input field for %s only allows numeric values.', 'option-tree' ), '<code>' . $error . '</code>', '<code>' . $field_id . '</code>' ), 'error' );
+          
+        }
+        
+      }
+      
+      if ( empty( $input ) ) {
+        $input = '';
+      }
+      
     } else if ( 'typography' == $type && isset( $input['font-color'] ) ) {
       
       $input['font-color'] = ot_validate_setting( $input['font-color'], 'colorpicker', $field_id );
-    
+      
+      // Loop over array and check for values
+      foreach( $input as $key => $value ) {
+        if ( ! empty( $value ) ) {
+          $has_value = true;
+        }
+      }
+      
+      // No value; set to empty
+      if ( ! isset( $has_value ) ) {
+        $input = '';
+      }
+      
     } else if ( 'upload' == $type ) {
 
-      $input = sanitize_text_field( $input );
-         
+      if( filter_var( $input, FILTER_VALIDATE_INT ) === FALSE ) {
+        $input = esc_url_raw( $input );
+      }
+    
+    } else if ( 'gallery' == $type ) {
+
+      $input = trim( $input );
+           
+    } else if ( 'social-links' == $type ) {
+      
+      // Loop over array and check for values, plus sanitize the text field
+      foreach( (array) $input as $key => $value ) {
+        if ( ! empty( $value ) && is_array( $value ) ) {
+          foreach( (array) $value as $item_key => $item_value ) {
+            if ( ! empty( $item_value ) ) {
+              $has_value = true;
+              $input[$key][$item_key] = sanitize_text_field( $item_value );
+            }
+          }
+        }
+      }
+      
+      // No value; set to empty
+      if ( ! isset( $has_value ) ) {
+        $input = '';
+      }
+    
     }
     
     $input = apply_filters( 'ot_after_validate_setting', $input, $type, $field_id );
@@ -506,7 +734,7 @@
   }
 
 }
-  
+
 /**
  * Setup the default admin styles
  *
@@ -518,9 +746,46 @@
 if ( ! function_exists( 'ot_admin_styles' ) ) {
 
   function ot_admin_styles() {
-  
+    global $wp_styles, $post;
+    
+    /* execute styles before actions */
+    do_action( 'ot_admin_styles_before' );
+    
+    /* load WP colorpicker */
+    wp_enqueue_style( 'wp-color-picker' );
+    
+    /* load admin styles */
     wp_enqueue_style( 'ot-admin-css', OT_URL . 'assets/css/ot-admin.css', false, OT_VERSION );
     
+    /* load the RTL stylesheet */
+    $wp_styles->add_data( 'ot-admin-css','rtl', true );
+    
+    /* Remove styles added by the Easy Digital Downloads plugin */
+    if ( isset( $post->post_type ) && $post->post_type == 'post' )
+      wp_dequeue_style( 'jquery-ui-css' );
+
+    /**
+     * Filter the screen IDs used to dequeue `jquery-ui-css`.
+     *
+     * @since 2.5.0
+     *
+     * @param array $screen_ids An array of screen IDs.
+     */
+    $screen_ids = apply_filters( 'ot_dequeue_jquery_ui_css_screen_ids', array( 
+      'toplevel_page_ot-settings', 
+      'optiontree_page_ot-documentation', 
+      'appearance_page_ot-theme-options' 
+    ) );
+    
+    /* Remove styles added by the WP Review plugin and any custom pages added through filtering */
+    if ( in_array( get_current_screen()->id, $screen_ids ) ) {
+      wp_dequeue_style( 'plugin_name-admin-ui-css' );
+      wp_dequeue_style( 'jquery-ui-css' );
+    }
+    
+    /* execute styles after actions */
+    do_action( 'ot_admin_styles_after' );
+
   }
   
 }
@@ -540,7 +805,10 @@
 if ( ! function_exists( 'ot_admin_scripts' ) ) {
 
   function ot_admin_scripts() {
-
+    
+    /* execute scripts before actions */
+    do_action( 'ot_admin_scripts_before' );
+    
     if ( function_exists( 'wp_enqueue_media' ) ) {
       /* WP 3.5 Media Uploader */
       wp_enqueue_media();
@@ -548,37 +816,63 @@
       /* Legacy Thickbox */
       add_thickbox();
     }
-    
-    /* load the colorpicker */
-    wp_enqueue_script( 'ot-colorpicker-js', OT_URL . 'assets/js/ot-colorpicker.js', array( 'jquery' ), OT_VERSION );
-    
+
     /* load jQuery-ui slider */
     wp_enqueue_script( 'jquery-ui-slider' );
-    
+
+    /* load jQuery-ui datepicker */
+    wp_enqueue_script( 'jquery-ui-datepicker' );
+
+    /* load WP colorpicker */
+    wp_enqueue_script( 'wp-color-picker' );
+
+    /* load Ace Editor for CSS Editing */
+    wp_enqueue_script( 'ace-editor', 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js', null, '1.1.3' );   
+
+    /* load jQuery UI timepicker addon */
+    wp_enqueue_script( 'jquery-ui-timepicker', OT_URL . 'assets/js/vendor/jquery/jquery-ui-timepicker.js', array( 'jquery', 'jquery-ui-slider', 'jquery-ui-datepicker' ), '1.4.3' );
+
+    /* load the post formats */
+    if ( OT_META_BOXES == true && OT_POST_FORMATS == true ) {
+      wp_enqueue_script( 'ot-postformats', OT_URL . 'assets/js/ot-postformats.js', array( 'jquery' ), '1.0.1' );
+    }
+
     /* load all the required scripts */
-    wp_enqueue_script( 'ot-admin-js', OT_URL . 'assets/js/ot-admin.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-ui-sortable', 'media-upload', 'thickbox' ), OT_VERSION );
-    
+    wp_enqueue_script( 'ot-admin-js', OT_URL . 'assets/js/ot-admin.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-ui-sortable', 'jquery-ui-slider', 'wp-color-picker', 'ace-editor', 'jquery-ui-datepicker', 'jquery-ui-timepicker' ), OT_VERSION );
+
     /* create localized JS array */
     $localized_array = array( 
       'ajax'                  => admin_url( 'admin-ajax.php' ),
-      'upload_text'           => __( 'Send to OptionTree', 'option-tree' ),
+      'upload_text'           => apply_filters( 'ot_upload_text', __( 'Send to OptionTree', 'option-tree' ) ),
       'remove_media_text'     => __( 'Remove Media', 'option-tree' ),
       'reset_agree'           => __( 'Are you sure you want to reset back to the defaults?', 'option-tree' ),
       'remove_no'             => __( 'You can\'t remove this! But you can edit the values.', 'option-tree' ),
       'remove_agree'          => __( 'Are you sure you want to remove this?', 'option-tree' ),
       'activate_layout_agree' => __( 'Are you sure you want to activate this layout?', 'option-tree' ),
-      'setting_limit'         => __( 'Sorry, you can\'t have settings three levels deep.', 'option-tree' )
+      'setting_limit'         => __( 'Sorry, you can\'t have settings three levels deep.', 'option-tree' ),
+      'delete'                => __( 'Delete Gallery', 'option-tree' ), 
+      'edit'                  => __( 'Edit Gallery', 'option-tree' ), 
+      'create'                => __( 'Create Gallery', 'option-tree' ), 
+      'confirm'               => __( 'Are you sure you want to delete this Gallery?', 'option-tree' ),
+      'date_current'          => __( 'Today', 'option-tree' ),
+      'date_time_current'     => __( 'Now', 'option-tree' ),
+      'date_close'            => __( 'Close', 'option-tree' ),
+      'replace'               => __( 'Featured Image', 'option-tree' ),
+      'with'                  => __( 'Image', 'option-tree' )
     );
     
     /* localized script attached to 'option_tree' */
     wp_localize_script( 'ot-admin-js', 'option_tree', $localized_array );
+    
+    /* execute scripts after actions */
+    do_action( 'ot_admin_scripts_after' );
 
   }
   
 }
 
 /**
- * Returns the ID of a custom post type by post_name.
+ * Returns the ID of a custom post type by post_title.
  *
  * @uses        get_results()
  *
@@ -590,9 +884,27 @@
 if ( ! function_exists( 'ot_get_media_post_ID' ) ) {
 
   function ot_get_media_post_ID() {
-    global $wpdb;
-    
-    return $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE `post_name` = 'media' AND `post_type` = 'option-tree' AND `post_status` = 'private'" );
+    
+    // Option ID
+    $option_id = 'ot_media_post_ID';
+    
+    // Get the media post ID
+    $post_ID = get_option( $option_id, false );
+    
+    // Add $post_ID to the DB
+    if ( $post_ID === false || empty( $post_ID ) ) {
+      global $wpdb;
+      
+      // Get the media post ID
+      $post_ID = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE `post_title` = 'Media' AND `post_type` = 'option-tree' AND `post_status` = 'private'" );
+      
+      // Add to the DB
+      if ( $post_ID !== null )
+        update_option( $option_id, $post_ID );
+
+    }
+    
+    return $post_ID;
     
   }
 
@@ -612,7 +924,8 @@
   
   function ot_create_media_post() {
     
-    register_post_type( 'option-tree', array(
+    $regsiter_post_type = 'register_' . 'post_type';
+    $regsiter_post_type( 'option-tree', array(
       'labels'              => array( 'name' => __( 'Option Tree', 'option-tree' ) ),
       'public'              => false,
       'show_ui'             => false,
@@ -634,6 +947,7 @@
       /* create post object */
       $_p = array();
       $_p['post_title']     = 'Media';
+      $_p['post_name']      = 'media';
       $_p['post_status']    = 'private';
       $_p['post_type']      = 'option-tree';
       $_p['comment_status'] = 'closed';
@@ -659,15 +973,16 @@
 if ( ! function_exists( 'ot_default_settings' ) ) {
 
   function ot_default_settings() {
-    global $wpdb, $table_prefix;
-    
-    if ( ! get_option( 'option_tree_settings' ) ) {
+    global $wpdb;
+    
+    if ( ! get_option( ot_settings_id() ) ) {
       
       $section_count = 0;
       $settings_count = 0;
       $settings = array();
-      
-      if ( mysql_num_rows( mysql_query( "SHOW TABLES LIKE '{$table_prefix}option_tree'" ) ) == 1 && $old_settings = $wpdb->get_results( "SELECT * FROM {$table_prefix}option_tree ORDER BY item_sort ASC" ) ) {
+      $table_name = $wpdb->prefix . 'option_tree';
+      
+      if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ) == $table_name && $old_settings = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY item_sort ASC" ) ) {
         
         foreach ( $old_settings as $setting ) {
           
@@ -697,7 +1012,7 @@
             
             /* textarea rows */
             $rows = '';
-            if ( in_array( $settings['settings'][$settings_count]['type'], array( 'css', 'textarea' ) ) ) {
+            if ( in_array( $settings['settings'][$settings_count]['type'], array( 'css', 'javascript', 'textarea' ) ) ) {
               if ( (int) $setting->item_options > 0 ) {
                 $rows = (int) $setting->item_options;
               } else {
@@ -771,10 +1086,10 @@
       }
       
       /* update the settings array */
-      update_option( 'option_tree_settings', $settings );
+      update_option( ot_settings_id(), $settings );
       
       /* get option tree array */
-      $options = get_option( 'option_tree' );
+      $options = get_option( ot_options_id() );
       
       /* validate options */
       if ( is_array( $options ) ) {
@@ -795,7 +1110,7 @@
         do_action( 'ot_before_theme_options_save', $options );
         
         /* update the option tree array */
-        update_option( 'option_tree', $options );
+        update_option( ot_options_id(), $options );
         
       }
       
@@ -818,7 +1133,7 @@
   function ot_save_css( $options ) {
     
     /* grab a copy of the settings */
-    $settings = get_option( 'option_tree_settings' );
+    $settings = get_option( ot_settings_id() );
       
     /* has settings */
     if ( isset( $settings['settings'] ) ) {
@@ -953,7 +1268,7 @@
         }
         
         /* update settings */
-        update_option( 'option_tree_settings', $settings );
+        update_option( ot_settings_id(), $settings );
         
         /* set message */
         $message = 'success';
@@ -961,7 +1276,7 @@
       }
       
       /* redirect */
-      wp_redirect( add_query_arg( array( 'action' => 'import-xml', 'message' => $message ), $_POST['_wp_http_referer'] ) );
+      wp_redirect( esc_url_raw( add_query_arg( array( 'action' => 'import-xml', 'message' => $message ), $_POST['_wp_http_referer'] ) ) );
       exit;
       
     }
@@ -977,12 +1292,12 @@
       
       /* is array: save & show success message */
       if ( is_array( $textarea ) ) {
-        update_option( 'option_tree_settings', $textarea );
+        update_option( ot_settings_id(), $textarea );
         $message = 'success';
       }
       
       /* redirect */
-      wp_redirect( add_query_arg( array( 'action' => 'import-settings', 'message' => $message ), $_POST['_wp_http_referer'] ) );
+      wp_redirect( esc_url_raw( add_query_arg( array( 'action' => 'import-settings', 'message' => $message ), $_POST['_wp_http_referer'] ) ) );
       exit;
       
     }
@@ -997,7 +1312,7 @@
       $options = isset( $_POST['import_data'] ) ? unserialize( ot_decode( $_POST['import_data'] ) ) : '';
       
       /* get settings array */
-      $settings = get_option( 'option_tree_settings' );
+      $settings = get_option( ot_settings_id() );
       
       /* has options */
       if ( is_array( $options ) ) {
@@ -1023,14 +1338,14 @@
         do_action( 'ot_before_theme_options_save', $options );
       
         /* update the option tree array */
-        update_option( 'option_tree', $options );
+        update_option( ot_options_id(), $options );
         
         $message = 'success';
         
       }
       
       /* redirect accordingly */
-      wp_redirect( add_query_arg( array( 'action' => 'import-data', 'message' => $message ), $_POST['_wp_http_referer'] ) );
+      wp_redirect( esc_url_raw( add_query_arg( array( 'action' => 'import-data', 'message' => $message ), $_POST['_wp_http_referer'] ) ) );
       exit;
       
     }
@@ -1045,7 +1360,7 @@
       $layouts = isset( $_POST['import_layouts'] ) ? unserialize( ot_decode( $_POST['import_layouts'] ) ) : '';
       
       /* get settings array */
-      $settings = get_option( 'option_tree_settings' );
+      $settings = get_option( ot_settings_id() );
       
       /* has layouts */
       if ( is_array( $layouts ) ) {
@@ -1086,19 +1401,19 @@
           /* execute the action hook and pass the theme options to it */
           do_action( 'ot_before_theme_options_save', $new_options );
         
-          update_option( 'option_tree', $new_options );
+          update_option( ot_options_id(), $new_options );
           
         }
         
         /* update the option tree layouts array */
-        update_option( 'option_tree_layouts', $layouts );
+        update_option( ot_layouts_id(), $layouts );
         
         $message = 'success';
         
       }
         
       /* redirect accordingly */
-      wp_redirect( add_query_arg( array( 'action' => 'import-layouts', 'message' => $message ), $_POST['_wp_http_referer'] ) );
+      wp_redirect( esc_url_raw( add_query_arg( array( 'action' => 'import-layouts', 'message' => $message ), $_POST['_wp_http_referer'] ) ) );
       exit;
       
     }
@@ -1190,7 +1505,7 @@
           
           /* textarea rows */
           $rows = '';
-          if ( in_array( $settings['settings'][$settings_count]['type'], array( 'css', 'textarea' ) ) ) {
+          if ( in_array( $settings['settings'][$settings_count]['type'], array( 'css', 'javascript', 'textarea' ) ) ) {
             if ( (int) $value->item_options > 0 ) {
               $rows = (int) $value->item_options;
             } else {
@@ -1259,7 +1574,16 @@
     $contextual_help      = '';
     $sections             = '';
     $settings             = '';
-    $option_tree_settings = get_option( 'option_tree_settings', array() );
+    $option_tree_settings = get_option( ot_settings_id(), array() );
+    
+    // Domain string helper
+    function ot_I18n_string( $string ) {
+      if ( ! empty( $string ) && isset( $_POST['domain'] ) && ! empty( $_POST['domain'] ) ) {
+        $domain = str_replace( ' ', '-', trim( $_POST['domain'] ) );
+        return "__( '$string', '$domain' )";
+      }
+      return "'$string'";
+    }
     
     header( "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
     header( "Pragma: no-cache ");
@@ -1273,13 +1597,13 @@
       $help = '';
       foreach( $option_tree_settings['contextual_help']['content'] as $value ) {
         $_id = isset( $value['id'] ) ? $value['id'] : '';
-        $_title = isset( $value['title'] ) ? str_replace( "'", "\'", $value['title'] ) : '';
-        $_content = isset( $value['content'] ) ? html_entity_decode(  str_replace( "'", "\'", $value['content'] ) ) : '';
+        $_title = ot_I18n_string( isset( $value['title'] ) ? str_replace( "'", "\'", $value['title'] ) : '' );
+        $_content = ot_I18n_string( isset( $value['content'] ) ? html_entity_decode(  str_replace( "'", "\'", $value['content'] ) ) : '' );
         $help.= "
         array(
           'id'        => '$_id',
-          'title'     => '$_title',
-          'content'   => '$_content'
+          'title'     => $_title,
+          'content'   => $_content
         ),";
       }
       $help = substr_replace( $help, '' , -1 );
@@ -1291,7 +1615,7 @@
     /* build contextual help sidebar */
     if ( isset( $option_tree_settings['contextual_help']['sidebar'] ) ) {
       $contextual_help.= "
-      'sidebar'       => '" . html_entity_decode(  str_replace( "'", "\'", $option_tree_settings['contextual_help']['sidebar'] ) ) . "'";
+      'sidebar'       => " . ot_I18n_string( html_entity_decode(  str_replace( "'", "\'", $option_tree_settings['contextual_help']['sidebar'] ) ) );
     }
     
     /* check that $contexual_help has a value and add to $build_settings */
@@ -1305,11 +1629,11 @@
     if ( isset( $option_tree_settings['sections'] ) ) {
       foreach( $option_tree_settings['sections'] as $value ) {
         $_id = isset( $value['id'] ) ? $value['id'] : '';
-        $_title = isset( $value['title'] ) ? str_replace( "'", "\'", $value['title'] ) : '';
+        $_title = ot_I18n_string( isset( $value['title'] ) ? str_replace( "'", "\'", $value['title'] ) : '' );
         $sections.= "
       array(
         'id'          => '$_id',
-        'title'       => '$_title'
+        'title'       => $_title
       ),";
       }
       $sections = substr_replace( $sections, '' , -1 );
@@ -1326,8 +1650,8 @@
     if ( isset( $option_tree_settings['settings'] ) ) {
       foreach( $option_tree_settings['settings'] as $value ) {
         $_id = isset( $value['id'] ) ? $value['id'] : '';
-        $_label = isset( $value['label'] ) ? str_replace( "'", "\'", $value['label'] ) : '';
-        $_desc = isset( $value['desc'] ) ? str_replace( "'", "\'", $value['desc'] ) : '';
+        $_label = ot_I18n_string( isset( $value['label'] ) ? str_replace( "'", "\'", $value['label'] ) : '' );
+        $_desc = ot_I18n_string( isset( $value['desc'] ) ? str_replace( "'", "\'", $value['desc'] ) : '' );
         $_std = isset( $value['std'] ) ? str_replace( "'", "\'", $value['std'] ) : '';
         $_type = isset( $value['type'] ) ? $value['type'] : '';
         $_section = isset( $value['section'] ) ? $value['section'] : '';
@@ -1336,24 +1660,26 @@
         $_taxonomy = isset( $value['taxonomy'] ) ? $value['taxonomy'] : '';
         $_min_max_step = isset( $value['min_max_step'] ) ? $value['min_max_step'] : '';
         $_class = isset( $value['class'] ) ? $value['class'] : '';
+        $_condition = isset( $value['condition'] ) ? $value['condition'] : '';
+        $_operator = isset( $value['operator'] ) ? $value['operator'] : '';
         
         $choices = '';
         if ( isset( $value['choices'] ) && ! empty( $value['choices'] ) ) {
           foreach( $value['choices'] as $choice ) {
             $_choice_value = isset( $choice['value'] ) ? str_replace( "'", "\'", $choice['value'] ) : '';
-            $_choice_label = isset( $choice['label'] ) ? str_replace( "'", "\'", $choice['label'] ) : '';
+            $_choice_label = ot_I18n_string( isset( $choice['label'] ) ? str_replace( "'", "\'", $choice['label'] ) : '' );
             $_choice_src = isset( $choice['src'] ) ? str_replace( "'", "\'", $choice['src'] ) : '';
             $choices.= "
           array(
             'value'       => '$_choice_value',
-            'label'       => '$_choice_label',
+            'label'       => $_choice_label,
             'src'         => '$_choice_src'
           ),";
           }
           $choices = substr_replace( $choices, '' , -1 );
           $choices = ",
         'choices'     => array( $choices
-        ),";
+        )";
         }
         
         $std = "'$_std'";
@@ -1371,8 +1697,8 @@
         if ( isset( $value['settings'] ) && ! empty( $value['settings'] ) ) {
           foreach( $value['settings'] as $setting ) {
             $_setting_id = isset( $setting['id'] ) ? $setting['id'] : '';
-            $_setting_label = isset( $setting['label'] ) ? str_replace( "'", "\'", $setting['label'] ) : '';
-            $_setting_desc = isset( $setting['desc'] ) ? str_replace( "'", "\'", $setting['desc'] ) : '';
+            $_setting_label = ot_I18n_string( isset( $setting['label'] ) ? str_replace( "'", "\'", $setting['label'] ) : '' );
+            $_setting_desc = ot_I18n_string( isset( $setting['desc'] ) ? str_replace( "'", "\'", $setting['desc'] ) : '' );
             $_setting_std = isset( $setting['std'] ) ? $setting['std'] : '';
             $_setting_type = isset( $setting['type'] ) ? $setting['type'] : '';
             $_setting_rows = isset( $setting['rows'] ) ? $setting['rows'] : '';
@@ -1380,24 +1706,26 @@
             $_setting_taxonomy = isset( $setting['taxonomy'] ) ? $setting['taxonomy'] : '';
             $_setting_min_max_step = isset( $setting['min_max_step'] ) ? $setting['min_max_step'] : '';
             $_setting_class = isset( $setting['class'] ) ? $setting['class'] : '';
+            $_setting_condition = isset( $setting['condition'] ) ? $setting['condition'] : '';
+            $_setting_operator = isset( $setting['operator'] ) ? $setting['operator'] : '';
             
             $setting_choices = '';
             if ( isset( $setting['choices'] ) && ! empty( $setting['choices'] ) ) {
               foreach( $setting['choices'] as $setting_choice ) {
                 $_setting_choice_value = isset( $setting_choice['value'] ) ? $setting_choice['value'] : '';
-                $_setting_choice_label = isset( $setting_choice['label'] ) ? str_replace( "'", "\'", $setting_choice['label'] ) : '';
+                $_setting_choice_label = ot_I18n_string( isset( $setting_choice['label'] ) ? str_replace( "'", "\'", $setting_choice['label'] ) : '' );
                 $_setting_choice_src = isset( $setting_choice['src'] ) ? str_replace( "'", "\'", $setting_choice['src'] ) : '';
                 $setting_choices.= "
               array(
                 'value'       => '$_setting_choice_value',
-                'label'       => '$_setting_choice_label',
+                'label'       => $_setting_choice_label,
                 'src'         => '$_setting_choice_src'
               ),";
               }
               $setting_choices = substr_replace( $setting_choices, '' , -1 );
               $setting_choices = ",
             'choices'     => array( $setting_choices
-            ),";
+            )";
             }
             
             $setting_std = "'$_setting_std'";
@@ -1414,15 +1742,17 @@
             $setting_settings.= "
           array(
             'id'          => '$_setting_id',
-            'label'       => '$_setting_label',
-            'desc'        => '$_setting_desc',
+            'label'       => $_setting_label,
+            'desc'        => $_setting_desc,
             'std'         => $setting_std,
             'type'        => '$_setting_type',
             'rows'        => '$_setting_rows',
             'post_type'   => '$_setting_post_type',
             'taxonomy'    => '$_setting_taxonomy',
             'min_max_step'=> '$_setting_min_max_step',
-            'class'       => '$_setting_class'$setting_choices
+            'class'       => '$_setting_class',
+            'condition'   => '$_setting_condition',
+            'operator'    => '$_setting_operator'$setting_choices
           ),";
           }
           $setting_settings = substr_replace( $setting_settings, '' , -1 );
@@ -1434,8 +1764,8 @@
         $settings.= "
       array(
         'id'          => '$_id',
-        'label'       => '$_label',
-        'desc'        => '$_desc',
+        'label'       => $_label,
+        'desc'        => $_desc,
         'std'         => $std,
         'type'        => '$_type',
         'section'     => '$_section',
@@ -1443,7 +1773,9 @@
         'post_type'   => '$_post_type',
         'taxonomy'    => '$_taxonomy',
         'min_max_step'=> '$_min_max_step',
-        'class'       => '$_class'$choices$setting_settings
+        'class'       => '$_class',
+        'condition'   => '$_condition',
+        'operator'    => '$_operator'$choices$setting_settings
       ),";
       }
       $settings = substr_replace( $settings, '' , -1 );
@@ -1460,16 +1792,21 @@
 /**
  * Initialize the custom theme options.
  */
-add_action( 'admin_init', 'custom_theme_options' );
+add_action( 'init', 'custom_theme_options' );
 
 /**
  * Build the custom settings & update OptionTree.
  */
 function custom_theme_options() {
+  
+  /* OptionTree is not loaded yet, or this is not an admin request */
+  if ( ! function_exists( 'ot_settings_id' ) || ! is_admin() )
+    return false;
+    
   /**
    * Get a copy of the saved settings array. 
    */
-  \$saved_settings = get_option( 'option_tree_settings', array() );
+  \$saved_settings = get_option( ot_settings_id(), array() );
   
   /**
    * Custom settings array that will eventually be 
@@ -1479,13 +1816,17 @@
   );
   
   /* allow settings to be filtered before saving */
-  \$custom_settings = apply_filters( 'option_tree_settings_args', \$custom_settings );
+  \$custom_settings = apply_filters( ot_settings_id() . '_args', \$custom_settings );
   
   /* settings are not the same update the DB */
   if ( \$saved_settings !== \$custom_settings ) {
-    update_option( 'option_tree_settings', \$custom_settings ); 
+    update_option( ot_settings_id(), \$custom_settings ); 
   }
   
+  /* Lets OptionTree know the UI Builder is being overridden */
+  global \$ot_has_custom_theme_options;
+  \$ot_has_custom_theme_options = true;
+  
 }";
 
     echo $content;
@@ -1510,7 +1851,7 @@
     if ( isset( $_POST['option_tree_settings_nonce'] ) && wp_verify_nonce( $_POST['option_tree_settings_nonce'], 'option_tree_settings_form' ) ) {
 
       /* settings value */
-      $settings = isset( $_POST['option_tree_settings'] ) ? $_POST['option_tree_settings'] : '';
+      $settings = isset( $_POST[ot_settings_id()] ) ? $_POST[ot_settings_id()] : '';
       
       /* validate sections */
       if ( isset( $settings['sections'] ) ) {
@@ -1634,8 +1975,8 @@
         /* WPML unregister ID's that have been removed */
         if ( function_exists( 'icl_unregister_string' ) ) {
           
-          $current = get_option( 'option_tree_settings' );
-          $options = get_option( 'option_tree' );
+          $current = get_option( ot_settings_id() );
+          $options = get_option( ot_options_id() );
           
           if ( isset( $current['settings'] ) ) {
             
@@ -1669,6 +2010,18 @@
                     }
                   
                   }
+                
+                } else if ( ! empty( $options[$current_setting['id']] ) && $current_setting['type'] == 'social-icons' ) {
+                  
+                  foreach( $options[$current_setting['id']] as $key => $value ) {
+          
+                    foreach( $value as $ckey => $cvalue ) {
+                      
+                      ot_wpml_unregister_string( $current_setting['id'] . '_' . $ckey . '_' . $key );
+                      
+                    }
+                  
+                  }
                   
                 } else {
                 
@@ -1684,13 +2037,13 @@
           
         }
         
-        update_option( 'option_tree_settings', $settings );
+        update_option( ot_settings_id(), $settings );
         $message = 'success';
         
       }
       
       /* redirect */
-      wp_redirect( add_query_arg( array( 'action' => 'save-settings', 'message' => $message ), $_POST['_wp_http_referer'] ) );
+      wp_redirect( esc_url_raw( add_query_arg( array( 'action' => 'save-settings', 'message' => $message ), $_POST['_wp_http_referer'] ) ) );
       exit;
       
     }
@@ -1833,10 +2186,10 @@
     if ( isset( $_POST['option_tree_modify_layouts_nonce'] ) && wp_verify_nonce( $_POST['option_tree_modify_layouts_nonce'], 'option_tree_modify_layouts_form' ) ) {
       
       /* previous layouts value */
-      $option_tree_layouts = get_option( 'option_tree_layouts' );
+      $option_tree_layouts = get_option( ot_layouts_id() );
       
       /* new layouts value */
-      $layouts = isset( $_POST['option_tree_layouts'] ) ? $_POST['option_tree_layouts'] : '';
+      $layouts = isset( $_POST[ot_layouts_id()] ) ? $_POST[ot_layouts_id()] : '';
       
       /* rebuild layout array */
       $rebuild = array();
@@ -1852,7 +2205,7 @@
         /* add new and overwrite active layout */
         if ( isset( $layouts['_add_new_layout_'] ) && ! empty( $layouts['_add_new_layout_'] ) ) {
           $rebuild['active_layout'] = ot_sanitize_layout_id( $layouts['_add_new_layout_'] );
-          $rebuild[$rebuild['active_layout']] = ot_encode( serialize( get_option( 'option_tree' ) ) );
+          $rebuild[$rebuild['active_layout']] = ot_encode( serialize( get_option( ot_options_id() ) ) );
         }
         
         $first_layout = '';
@@ -1893,12 +2246,12 @@
           /* execute the action hook and pass the theme options to it */
           do_action( 'ot_before_theme_options_save', $rebuild_option_tree );
           
-          update_option( 'option_tree', $rebuild_option_tree );
+          update_option( ot_options_id(), $rebuild_option_tree );
           
         }
         
         /* rebuild the layouts */
-        update_option( 'option_tree_layouts', $rebuild );
+        update_option( ot_layouts_id(), $rebuild );
         
         /* change message */
         $message = 'success';
@@ -1906,7 +2259,7 @@
       } else if ( count( $rebuild ) <= 1 ) {
 
         /* delete layouts option */
-        delete_option( 'option_tree_layouts' );
+        delete_option( ot_layouts_id() );
         
         /* change message */
         $message = 'deleted';
@@ -1915,9 +2268,9 @@
       
       /* redirect */
       if ( isset( $_REQUEST['page'] ) && $_REQUEST['page'] == apply_filters( 'ot_theme_options_menu_slug', 'ot-theme-options' ) ) {
-        $query_args = add_query_arg( array( 'settings-updated' => 'layout' ), remove_query_arg( array( 'action', 'message' ), $_POST['_wp_http_referer'] ) );
+        $query_args = esc_url_raw( add_query_arg( array( 'settings-updated' => 'layout' ), remove_query_arg( array( 'action', 'message' ), $_POST['_wp_http_referer'] ) ) );
       } else {
-        $query_args = add_query_arg( array( 'action' => 'save-layouts', 'message' => $message ), $_POST['_wp_http_referer'] );
+        $query_args = esc_url_raw( add_query_arg( array( 'action' => 'save-layouts', 'message' => $message ), $_POST['_wp_http_referer'] ) );
       }
       wp_redirect( $query_args );
       exit;
@@ -1946,6 +2299,12 @@
     if ( empty( $page ) )
       return false;
     
+    $before = apply_filters( 'ot_before_page_messages', '', $page );
+    
+    if ( $before ) {
+      return $before;
+    }
+    
     $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
     $message = isset( $_REQUEST['message'] ) ? $_REQUEST['message'] : '';
     $updated = isset( $_REQUEST['settings-updated'] ) ? $_REQUEST['settings-updated'] : '';
@@ -2023,7 +2382,7 @@
         
     }
     
-    do_action( 'ot_custom_page_messages' );
+    do_action( 'ot_custom_page_messages', $page );
     
     if ( $updated == 'true' ) {  
        
@@ -2054,37 +2413,51 @@
   function ot_option_types_array() {
   
     return apply_filters( 'ot_option_types_array', array( 
-      'background'                => 'Background',
-      'category-checkbox'         => 'Category Checkbox',
-      'category-select'           => 'Category Select',
-      'checkbox'                  => 'Checkbox',
-      'colorpicker'               => 'Colorpicker',
-      'css'                       => 'CSS',
-      'custom-post-type-checkbox' => 'Custom Post Type Checkbox',
-      'custom-post-type-select'   => 'Custom Post Type Select',
-      'list-item'                 => 'List Item',
-      'measurement'               => 'Measurement',
-      'numeric-slider'            => 'Numeric Slider',
-      'page-checkbox'             => 'Page Checkbox',
-      'page-select'               => 'Page Select',
-      'post-checkbox'             => 'Post Checkbox',
-      'post-select'               => 'Post Select',
-      'radio'                     => 'Radio',
-      'radio-image'               => 'Radio Image',
-      'select'                    => 'Select',
-      'sidebar-select'            => 'Sidebar Select', 
-      'slider'                    => 'Slider',
-      'tag-checkbox'              => 'Tag Checkbox',
-      'tag-select'                => 'Tag Select',
-      'taxonomy-checkbox'         => 'Taxonomy Checkbox',
-      'taxonomy-select'           => 'Taxonomy Select',
-      'text'                      => 'Text',
-      'textarea'                  => 'Textarea',
-      'textarea-simple'           => 'Textarea Simple',
-      'textblock'                 => 'Textblock',
-      'textblock-titled'          => 'Textblock Titled',
-      'typography'                => 'Typography',
-      'upload'                    => 'Upload'
+      'background'                => __('Background', 'option-tree'),
+      'border'                    => __('Border', 'option-tree'),
+      'box-shadow'                => __('Box Shadow', 'option-tree'),
+      'category-checkbox'         => __('Category Checkbox', 'option-tree'),
+      'category-select'           => __('Category Select', 'option-tree'),
+      'checkbox'                  => __('Checkbox', 'option-tree'),
+      'colorpicker'               => __('Colorpicker', 'option-tree'),
+      'colorpicker-opacity'       => __('Colorpicker Opacity', 'option-tree'),
+      'css'                       => __('CSS', 'option-tree'),
+      'custom-post-type-checkbox' => __('Custom Post Type Checkbox', 'option-tree'),
+      'custom-post-type-select'   => __('Custom Post Type Select', 'option-tree'),
+      'date-picker'               => __('Date Picker', 'option-tree'),
+      'date-time-picker'          => __('Date Time Picker', 'option-tree'),
+      'dimension'                 => __('Dimension', 'option-tree'),
+      'gallery'                   => __('Gallery', 'option-tree'),
+      'google-fonts'              => __('Google Fonts', 'option-tree'),
+      'javascript'                => __('JavaScript', 'option-tree'),
+      'link-color'                => __('Link Color', 'option-tree'),
+      'list-item'                 => __('List Item', 'option-tree'),
+      'measurement'               => __('Measurement', 'option-tree'),
+      'numeric-slider'            => __('Numeric Slider', 'option-tree'),
+      'on-off'                    => __('On/Off', 'option-tree'),
+      'page-checkbox'             => __('Page Checkbox', 'option-tree'),
+      'page-select'               => __('Page Select', 'option-tree'),
+      'post-checkbox'             => __('Post Checkbox', 'option-tree'),
+      'post-select'               => __('Post Select', 'option-tree'),
+      'radio'                     => __('Radio', 'option-tree'),
+      'radio-image'               => __('Radio Image', 'option-tree'),
+      'select'                    => __('Select', 'option-tree'),
+      'sidebar-select'            => __('Sidebar Select',  'option-tree'),
+      'slider'                    => __('Slider', 'option-tree'),
+      'social-links'              => __('Social Links', 'option-tree'),
+      'spacing'                   => __('Spacing', 'option-tree'),
+      'tab'                       => __('Tab', 'option-tree'),
+      'tag-checkbox'              => __('Tag Checkbox', 'option-tree'),
+      'tag-select'                => __('Tag Select', 'option-tree'),
+      'taxonomy-checkbox'         => __('Taxonomy Checkbox', 'option-tree'),
+      'taxonomy-select'           => __('Taxonomy Select', 'option-tree'),
+      'text'                      => __('Text', 'option-tree'),
+      'textarea'                  => __('Textarea', 'option-tree'),
+      'textarea-simple'           => __('Textarea Simple', 'option-tree'),
+      'textblock'                 => __('Textblock', 'option-tree'),
+      'textblock-titled'          => __('Textblock Titled', 'option-tree'),
+      'typography'                => __('Typography', 'option-tree'),
+      'upload'                    => __('Upload', 'option-tree')
     ) );
     
   }
@@ -2142,6 +2515,38 @@
 }
 
 /**
+ * Filters the typography font-family to add Google fonts dynamically.
+ *
+ * @param     array     $families An array of all recognized font families.
+ * @param     string    $field_id ID of the feild being filtered.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+function ot_google_font_stack( $families, $field_id ) {
+
+  $ot_google_fonts = get_theme_mod( 'ot_google_fonts', array() );
+  $ot_set_google_fonts = get_theme_mod( 'ot_set_google_fonts', array() );
+
+  if ( ! empty( $ot_set_google_fonts ) ) {
+    foreach( $ot_set_google_fonts as $id => $sets ) {
+      foreach( $sets as $value ) {
+        $family = isset( $value['family'] ) ? $value['family'] : '';
+        if ( $family && isset( $ot_google_fonts[$family] ) ) {
+          $spaces = explode(' ', $ot_google_fonts[$family]['family'] );
+          $font_stack = count( $spaces ) > 1 ? '"' . $ot_google_fonts[$family]['family'] . '"': $ot_google_fonts[$family]['family'];
+          $families[$family] = apply_filters( 'ot_google_font_stack', $font_stack, $family, $field_id );
+        }
+      }
+    }
+  }
+  
+  return $families;
+}
+add_filter( 'ot_recognized_font_families', 'ot_google_font_stack', 1, 2 );
+
+/**
  * Recognized font families
  *
  * Returns an array of all recognized font families.
@@ -2160,8 +2565,8 @@
 if ( ! function_exists( 'ot_recognized_font_families' ) ) {
 
   function ot_recognized_font_families( $field_id = '' ) {
-  
-    return apply_filters( 'ot_recognized_font_families', array(
+    
+    $families = array(
       'arial'     => 'Arial',
       'georgia'   => 'Georgia',
       'helvetica' => 'Helvetica',
@@ -2170,7 +2575,9 @@
       'times'     => '"Times New Roman", sans-serif',
       'trebuchet' => 'Trebuchet',
       'verdana'   => 'Verdana'
-    ), $field_id );
+    );
+    
+    return apply_filters( 'ot_recognized_font_families', $families, $field_id );
     
   }
 
@@ -2205,7 +2612,7 @@
       $range[$k] = $v . $unit;
     }
     
-    return $range;
+    return apply_filters( 'ot_recognized_font_sizes', $range, $field_id );
   }
 
 }
@@ -2335,7 +2742,7 @@
       $range[$k] = $v . $unit;
     }
     
-    return $range;
+    return apply_filters( 'ot_recognized_letter_spacing', $range, $field_id );
   }
 
 }
@@ -2360,7 +2767,7 @@
     $range = ot_range( 
       apply_filters( 'ot_line_height_low_range', 0, $field_id ), 
       apply_filters( 'ot_line_height_high_range', 150, $field_id ), 
-      apply_filters( 'ot_line_height_unit_type', 1, $field_id )
+      apply_filters( 'ot_line_height_range_interval', 1, $field_id )
     );
     
     $unit = apply_filters( 'ot_line_height_unit_type', 'px', $field_id );
@@ -2369,7 +2776,7 @@
       $range[$k] = $v . $unit;
     }
     
-    return $range;
+    return apply_filters( 'ot_recognized_line_heights', $range, $field_id );
   }
 
 }
@@ -2528,6 +2935,214 @@
 }
 
 /**
+ * Border Styles
+ *
+ * Returns an array of all available style types.
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_border_style_types' ) ) {
+
+  function ot_recognized_border_style_types( $field_id = '' ) {
+
+    return apply_filters( 'ot_recognized_border_style_types', array(
+      'hidden' => 'Hidden',
+      'dashed' => 'Dashed',
+      'solid'  => 'Solid',
+      'double' => 'Double',
+      'groove' => 'Groove',
+      'ridge'  => 'Ridge',
+      'inset'  => 'Inset',
+      'outset' => 'Outset',
+    ), $field_id );
+
+  }
+
+}
+
+/**
+ * Border Units
+ *
+ * Returns an array of all available unit types.
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_border_unit_types' ) ) {
+
+  function ot_recognized_border_unit_types( $field_id = '' ) {
+
+    return apply_filters( 'ot_recognized_border_unit_types', array(
+      'px' => 'px',
+      '%'  => '%',
+      'em' => 'em',
+      'pt' => 'pt'
+    ), $field_id );
+
+  }
+
+}
+
+/**
+ * Dimension Units
+ *
+ * Returns an array of all available unit types.
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_dimension_unit_types' ) ) {
+
+  function ot_recognized_dimension_unit_types( $field_id = '' ) {
+
+    return apply_filters( 'ot_recognized_dimension_unit_types', array(
+      'px' => 'px',
+      '%'  => '%',
+      'em' => 'em',
+      'pt' => 'pt'
+    ), $field_id );
+
+  }
+
+}
+
+/**
+ * Spacing Units
+ *
+ * Returns an array of all available unit types.
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_spacing_unit_types' ) ) {
+
+  function ot_recognized_spacing_unit_types( $field_id = '' ) {
+
+    return apply_filters( 'ot_recognized_spacing_unit_types', array(
+      'px' => 'px',
+      '%'  => '%',
+      'em' => 'em',
+      'pt' => 'pt'
+    ), $field_id );
+
+  }
+
+}
+
+/**
+ * Recognized Google font families
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_google_font_families' ) ) {
+
+  function ot_recognized_google_font_families( $field_id ) {
+
+    $families = array();
+    $ot_google_fonts = get_theme_mod( 'ot_google_fonts', array() );
+    
+    // Forces an array rebuild when we sitch themes
+    if ( empty( $ot_google_fonts ) ) {
+      $ot_google_fonts = ot_fetch_google_fonts( true, true );
+    }
+    
+    foreach( (array) $ot_google_fonts as $key => $item ) {
+  
+      if ( isset( $item['family'] ) ) {
+  
+        $families[ $key ] = $item['family'];
+  
+      }
+  
+    }
+  
+    return apply_filters( 'ot_recognized_google_font_families', $families, $field_id );
+  
+  }
+
+}
+
+/**
+ * Recognized Google font variants
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_google_font_variants' ) ) {
+
+  function ot_recognized_google_font_variants( $field_id, $family ) {
+
+    $variants = array();
+    $ot_google_fonts = get_theme_mod( 'ot_google_fonts', array() );
+
+    if ( isset( $ot_google_fonts[ $family ]['variants'] ) ) {
+  
+      $variants = $ot_google_fonts[ $family ]['variants'];
+  
+    }
+  
+    return apply_filters( 'ot_recognized_google_font_variants', $variants, $field_id, $family );
+  
+  }
+
+}
+
+/**
+ * Recognized Google font subsets
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+if ( ! function_exists( 'ot_recognized_google_font_subsets' ) ) {
+
+  function ot_recognized_google_font_subsets( $field_id, $family ) {
+
+    $subsets = array();
+    $ot_google_fonts = get_theme_mod( 'ot_google_fonts', array() );
+  
+    if ( isset( $ot_google_fonts[ $family ]['subsets'] ) ) {
+  
+      $subsets = $ot_google_fonts[ $family ]['subsets'];
+  
+    }
+  
+    return apply_filters( 'ot_recognized_google_font_subsets', $subsets, $field_id, $family );
+  
+  }
+
+}
+
+/**
  * Measurement Units
  *
  * Returns an array of all available unit types.
@@ -2749,6 +3364,53 @@
 }
 
 /**
+ * Default Social Links Settings array.
+ *
+ * Returns an array of the default social links settings.
+ * You can filter this function to change the settings
+ * on a per option basis.
+ *
+ * @uses      apply_filters()
+ *
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+if ( ! function_exists( 'ot_social_links_settings' ) ) {
+
+  function ot_social_links_settings( $id ) {
+    
+    $settings = apply_filters( 'ot_social_links_settings', array(
+      array(
+        'id'        => 'name',
+        'label'     => __( 'Name', 'option-tree' ),
+        'desc'      => __( 'Enter the name of the social website.', 'option-tree' ),
+        'std'       => '',
+        'type'      => 'text',
+        'class'     => 'option-tree-setting-title'
+      ),
+      array(
+        'id'        => 'title',
+        'label'     => 'Title',
+        'desc'      => __( 'Enter the text shown in the title attribute of the link.', 'option-tree' ),
+        'type'      => 'text'
+      ),
+      array(
+        'id'        => 'href',
+        'label'     => 'Link',
+        'desc'      => sprintf( __( 'Enter a link to the profile or page on the social website. Remember to add the %s part to the front of the link.', 'option-tree' ), '<code>http://</code>' ),
+        'type'      => 'text',
+      )
+    ), $id );
+    
+    return $settings;
+  
+  }
+
+}
+
+/**
  * Inserts CSS with field_id markers.
  *
  * Inserts CSS into a dynamic.css file, placing it between
@@ -2761,83 +3423,163 @@
  *
  * @access    public
  * @since     1.1.8
- * @updated   2.0.12
+ * @updated   2.5.3
  */
 if ( ! function_exists( 'ot_insert_css_with_markers' ) ) {
 
   function ot_insert_css_with_markers( $field_id = '', $insertion = '', $meta = false ) {
-    
+
     /* missing $field_id or $insertion exit early */
     if ( '' == $field_id || '' == $insertion )
       return;
 
     /* path to the dynamic.css file */
     $filepath = get_stylesheet_directory() . '/dynamic.css';
-    
+    if ( is_multisite() ) {
+      $multisite_filepath = get_stylesheet_directory() . '/dynamic-' . get_current_blog_id() . '.css';
+      if ( file_exists( $multisite_filepath ) ) {
+        $filepath = $multisite_filepath;
+      }
+    }
+
     /* allow filter on path */
     $filepath = apply_filters( 'css_option_file_path', $filepath, $field_id );
-    
+
     /* grab a copy of the paths array */
     $ot_css_file_paths = get_option( 'ot_css_file_paths', array() );
-    
+    if ( is_multisite() ) {
+      $ot_css_file_paths = get_blog_option( get_current_blog_id(), 'ot_css_file_paths', $ot_css_file_paths );
+    }
+
     /* set the path for this field */
     $ot_css_file_paths[$field_id] = $filepath;
-    
+
     /* update the paths */
-    update_option( 'ot_css_file_paths', $ot_css_file_paths );
-    
+    if ( is_multisite() ) {
+      update_blog_option( get_current_blog_id(), 'ot_css_file_paths', $ot_css_file_paths );
+    } else {
+      update_option( 'ot_css_file_paths', $ot_css_file_paths );
+    }
+
     /* insert CSS into file */
     if ( file_exists( $filepath ) ) {
-      
+
       $insertion   = ot_normalize_css( $insertion );
       $regex       = "/{{([a-zA-Z0-9\_\-\#\|\=]+)}}/";
       $marker      = $field_id;
-      
+
       /* Match custom CSS */
       preg_match_all( $regex, $insertion, $matches );
-      
+
       /* Loop through CSS */
       foreach( $matches[0] as $option ) {
 
         $value        = '';
-        $option_id    = str_replace( array( '{{', '}}' ), '', $option );
-        $option_array = explode( '|', $option_id );
-        
-        /* get the array value */
+        $option_array = explode( '|', str_replace( array( '{{', '}}' ), '', $option ) );
+        $option_id    = isset( $option_array[0] ) ? $option_array[0] : '';
+        $option_key   = isset( $option_array[1] ) ? $option_array[1] : '';
+        $option_type  = ot_get_option_type_by_id( $option_id );
+        $fallback     = '';
+
+        // Get the meta array value
         if ( $meta ) {
           global $post;
-          
-          $value = get_post_meta( $post->ID, $option_array[0], true );
-          
+
+          $value = get_post_meta( $post->ID, $option_id, true );
+
+        // Get the options array value
         } else {
-        
-          $options = get_option( 'option_tree' );
-          
-          if ( isset( $options[$option_array[0]] ) ) {
-            
-            $value = $options[$option_array[0]];
-  
+
+          $options = get_option( ot_options_id() );
+
+          if ( isset( $options[$option_id] ) ) {
+
+            $value = $options[$option_id];
+
           }
-          
+
         }
-        
+
+        // This in an array of values
         if ( is_array( $value ) ) {
-          
-          if ( ! isset( $option_array[1] ) ) {
-          
-            /* Measurement */
-            if ( isset( $value[0] ) && isset( $value[1] ) ) {
-              
-              /* set $value with measurement properties */
-              $value = $value[0].$value[1];
-              
-            /* typography */
-            } else if ( ot_array_keys_exists( $value, array( 'font-color', 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight', 'letter-spacing', 'line-height', 'text-decoration', 'text-transform' ) ) ) {
+
+          if ( empty( $option_key ) ) {
+
+            // Measurement
+            if ( $option_type == 'measurement' ) {
+              $unit = ! empty( $value[1] ) ? $value[1] : 'px';
+			  
+              // Set $value with measurement properties
+              if ( isset( $value[0] ) && strlen( $value[0] ) > 0 )
+                $value = $value[0].$unit;
+
+            // Border
+            } else if ( $option_type == 'border' ) {
+              $border = array();
+
+              $unit = ! empty( $value['unit'] ) ? $value['unit'] : 'px';
+
+              if ( isset( $value['width'] ) && strlen( $value['width'] ) > 0 )
+                $border[] = $value['width'].$unit;
+
+              if ( ! empty( $value['style'] ) )
+                $border[] = $value['style'];
+
+              if ( ! empty( $value['color'] ) )
+                $border[] = $value['color'];
+
+              /* set $value with border properties or empty string */
+              $value = ! empty( $border ) ? implode( ' ', $border ) : '';
+
+            // Box Shadow
+            } else if ( $option_type == 'box-shadow' ) {
+
+              /* set $value with box-shadow properties or empty string */
+              $value = ! empty( $value ) ? implode( ' ', $value ) : '';
+
+            // Dimension
+            } else if ( $option_type == 'dimension' ) {
+              $dimension = array();
+
+              $unit = ! empty( $value['unit'] ) ? $value['unit'] : 'px';
+
+              if ( isset( $value['width'] ) && strlen( $value['width'] ) > 0 )
+                $dimension[] = $value['width'].$unit;
+
+              if ( isset( $value['height'] ) && strlen( $value['height'] ) > 0 )
+                $dimension[] = $value['height'].$unit;
+
+              // Set $value with dimension properties or empty string
+              $value = ! empty( $dimension ) ? implode( ' ', $dimension ) : '';
+
+            // Spacing
+            } else if ( $option_type == 'spacing' ) {
+              $spacing = array();
+
+              $unit = ! empty( $value['unit'] ) ? $value['unit'] : 'px';
+
+              if ( isset( $value['top'] ) && strlen( $value['top'] ) > 0 )
+                $spacing[] = $value['top'].$unit;
+
+              if ( isset( $value['right'] ) && strlen( $value['right'] ) > 0 )
+                $spacing[] = $value['right'].$unit;
+
+              if ( isset( $value['bottom'] ) && strlen( $value['bottom'] ) > 0 )
+                $spacing[] = $value['bottom'].$unit;
+
+              if ( isset( $value['left'] ) && strlen( $value['left'] ) > 0 )
+                $spacing[] = $value['left'].$unit;
+
+              // Set $value with spacing properties or empty string
+              $value = ! empty( $spacing ) ? implode( ' ', $spacing ) : '';
+
+            // Typography
+            } else if ( $option_type == 'typography' ) {
               $font = array();
-              
+
               if ( ! empty( $value['font-color'] ) )
                 $font[] = "color: " . $value['font-color'] . ";";
-              
+
               if ( ! empty( $value['font-family'] ) ) {
                 foreach ( ot_recognized_font_families( $marker ) as $key => $v ) {
                   if ( $key == $value['font-family'] ) {
@@ -2845,102 +3587,205 @@
                   }
                 }
               }
-              
+
               if ( ! empty( $value['font-size'] ) )
                 $font[] = "font-size: " . $value['font-size'] . ";";
-              
+
               if ( ! empty( $value['font-style'] ) )
                 $font[] = "font-style: " . $value['font-style'] . ";";
-              
+
               if ( ! empty( $value['font-variant'] ) )
                 $font[] = "font-variant: " . $value['font-variant'] . ";";
-              
+
               if ( ! empty( $value['font-weight'] ) )
                 $font[] = "font-weight: " . $value['font-weight'] . ";";
-                
+
               if ( ! empty( $value['letter-spacing'] ) )
                 $font[] = "letter-spacing: " . $value['letter-spacing'] . ";";
-              
+
               if ( ! empty( $value['line-height'] ) )
                 $font[] = "line-height: " . $value['line-height'] . ";";
-              
+
               if ( ! empty( $value['text-decoration'] ) )
                 $font[] = "text-decoration: " . $value['text-decoration'] . ";";
-              
+
               if ( ! empty( $value['text-transform'] ) )
                 $font[] = "text-transform: " . $value['text-transform'] . ";";
-              
-              /* set $value with font properties or empty string */
+
+              // Set $value with font properties or empty string
               $value = ! empty( $font ) ? implode( "\n", $font ) : '';
-              
-            /* background */
-            } else if ( ot_array_keys_exists( $value, array( 'background-color', 'background-image', 'background-repeat', 'background-attachment', 'background-position' ) ) ) {
+
+            // Background
+            } else if ( $option_type == 'background' ) {
               $bg = array();
-              
+
               if ( ! empty( $value['background-color'] ) )
                 $bg[] = $value['background-color'];
-                
-              if ( ! empty( $value['background-image'] ) )
+
+              if ( ! empty( $value['background-image'] ) ) {
+
+                // If an attachment ID is stored here fetch its URL and replace the value
+                if ( wp_attachment_is_image( $value['background-image'] ) ) {
+
+                  $attachment_data = wp_get_attachment_image_src( $value['background-image'], 'original' );
+
+                  // Check for attachment data
+                  if ( $attachment_data ) {
+
+                    $value['background-image'] = $attachment_data[0];
+
+                  }
+
+                }
+
                 $bg[] = 'url("' . $value['background-image'] . '")';
-                
+
+              }
+
               if ( ! empty( $value['background-repeat'] ) )
                 $bg[] = $value['background-repeat'];
-                
+
               if ( ! empty( $value['background-attachment'] ) )
                 $bg[] = $value['background-attachment'];
-                
+
               if ( ! empty( $value['background-position'] ) )
                 $bg[] = $value['background-position'];
-              
-              /* set $value with background properties or empty string */
+
+              if ( ! empty( $value['background-size'] ) )
+                $size = $value['background-size'];
+
+              // Set $value with background properties or empty string
               $value = ! empty( $bg ) ? 'background: ' . implode( " ", $bg ) . ';' : '';
+
+              if ( isset( $size ) ) {
+                if ( ! empty( $bg ) ) {
+                  $value.= apply_filters( 'ot_insert_css_with_markers_bg_size_white_space', "\n\x20\x20", $option_id );
+                }
+                $value.= "background-size: $size;";
+              }
+
             }
-          
+
           } else {
-          
-            $value = $value[$option_array[1]];
-            
+
+            $value = $value[$option_key];
+
+          }
+
+        }
+
+        // If an attachment ID is stored here fetch its URL and replace the value
+        if ( $option_type == 'upload' && wp_attachment_is_image( $value ) ) {
+
+          $attachment_data = wp_get_attachment_image_src( $value, 'original' );
+
+          // Check for attachment data
+          if ( $attachment_data ) {
+
+            $value = $attachment_data[0];
+
           }
-         
+
         }
-        
+
+        // Attempt to fallback when `$value` is empty
+        if ( empty( $value ) ) {
+
+          // We're trying to access a single array key
+          if ( ! empty( $option_key ) ) {
+
+            // Link Color `inherit`
+            if ( $option_type == 'link-color' ) {
+              $fallback = 'inherit';
+            }
+
+          } else {
+
+            // Border
+            if ( $option_type == 'border' ) {
+              $fallback = 'inherit';
+            }
+
+            // Box Shadow
+            if ( $option_type == 'box-shadow' ) {
+              $fallback = 'none';
+            }
+
+            // Colorpicker
+            if ( $option_type == 'colorpicker' ) {
+              $fallback = 'inherit';
+            }
+
+            // Colorpicker Opacity
+            if ( $option_type == 'colorpicker-opacity' ) {
+              $fallback = 'inherit';
+            }
+
+          }
+
+          /**
+           * Filter the `dynamic.css` fallback value.
+           *
+           * @since 2.5.3
+           *
+           * @param string $fallback The default CSS fallback value.
+           * @param string $option_id The option ID.
+           * @param string $option_type The option type.
+           * @param string $option_key The option array key.
+           */
+          $fallback = apply_filters( 'ot_insert_css_with_markers_fallback', $fallback, $option_id, $option_type, $option_key );
+
+        }
+
+        // Let's fallback!
+        if ( ! empty( $fallback ) ) {
+          $value = $fallback;
+        }
+
         // Filter the CSS
-         $value = apply_filters( 'ot_insert_css_with_markers_value', $value, $option_id );
-         
-        /* insert CSS, even if the value is empty */
-         $insertion = stripslashes( str_replace( $option, $value, $insertion ) );
-         
+        $value = apply_filters( 'ot_insert_css_with_markers_value', $value, $option_id );
+
+        // Insert CSS, even if the value is empty
+        $insertion = stripslashes( str_replace( $option, $value, $insertion ) );
+
       }
-    
-      /* create array from the lines of code */
+
+      // Can't write to the file so we error out
+      if ( ! is_writable( $filepath ) ) {
+        add_settings_error( 'option-tree', 'dynamic_css', sprintf( __( 'Unable to write to file %s.', 'option-tree' ), '<code>' . $filepath . '</code>' ), 'error' );
+        return false;
+      }
+
+      // Create array from the lines of code
       $markerdata = explode( "\n", implode( '', file( $filepath ) ) );
-      
-      /* can't write to the file return false */
-      if ( ! $f = ot_file_open( $filepath, 'w' ) )
+
+      // Can't write to the file return false
+      if ( ! $f = ot_file_open( $filepath, 'w' ) ) {
         return false;
-      
+      }
+
       $searching = true;
       $foundit = false;
-      
-      /* has array of lines */
+
+      // Has array of lines
       if ( ! empty( $markerdata ) ) {
-        
-        /* foreach line of code */
+
+        // Foreach line of code
         foreach( $markerdata as $n => $markerline ) {
-          
-          /* found begining of marker, set $searching to false  */
+
+          // Found begining of marker, set $searching to false
           if ( $markerline == "/* BEGIN {$marker} */" )
             $searching = false;
-          
-          /* keep rewrite each line of CSS  */
+
+          // Keep searching each line of CSS
           if ( $searching == true ) {
             if ( $n + 1 < count( $markerdata ) )
               ot_file_write( $f, "{$markerline}\n" );
             else
               ot_file_write( $f, "{$markerline}" );
           }
-          
-          /* found end marker write code */
+
+          // Found end marker write code
           if ( $markerline == "/* END {$marker} */" ) {
             ot_file_write( $f, "/* BEGIN {$marker} */\n" );
             ot_file_write( $f, "{$insertion}\n" );
@@ -2948,23 +3793,23 @@
             $searching = true;
             $foundit = true;
           }
-          
+
         }
-        
+
       }
-      
-      /* nothing inserted, write code. DO IT, DO IT! */
+
+      // Nothing inserted, write code. DO IT, DO IT!
       if ( ! $foundit ) {
         ot_file_write( $f, "/* BEGIN {$marker} */\n" );
         ot_file_write( $f, "{$insertion}\n" );
         ot_file_write( $f, "/* END {$marker} */\n" );
       }
-      
-      /* close file */
+
+      // Close file
       ot_file_close( $f );
       return true;
     }
-    
+
     return false;
 
   }
@@ -3122,7 +3967,7 @@
     
     $content = '';
     
-    foreach( $choices as $key => $choice )
+    foreach( (array) $choices as $key => $choice )
       $content.= '<li class="ui-state-default list-choice">' . ot_choices_view( $name, $key, $choice ) . '</li>';
     
     return $content;
@@ -3177,11 +4022,11 @@
     <div class="option-tree-setting is-section">
       <div class="open">' . ( isset( $section['title'] ) ? esc_attr( $section['title'] ) : 'Section ' . ( $key + 1 ) ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button left-item" title="' . __( 'edit', 'option-tree' ) . '">
-          <span class="icon pencil">' . __( 'Edit', 'option-tree' ) . '</span> 
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
       <div class="option-tree-setting-body">
@@ -3229,13 +4074,14 @@
     $child = ( strpos( $name, '][settings]') !== false ) ? true : false;
     $type = isset( $setting['type'] ) ? $setting['type'] : '';
     $std = isset( $setting['std'] ) ? $setting['std'] : '';
+    $operator = isset( $setting['operator'] ) ? esc_attr( $setting['operator'] ) : 'and';
     
     // Serialize the standard value just incase
     if ( is_array( $std ) ) {
       $std = maybe_serialize( $std );
     }
     
-    if ( in_array( $type, array( 'textarea', 'textarea-simple', 'css' ) ) ) {
+    if ( in_array( $type, array( 'css', 'javascript', 'textarea', 'textarea-simple' ) ) ) {
       $std_form_element = '<textarea class="textarea" rows="10" cols="40" name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . '][std]">' . esc_html( $std ) . '</textarea>';
     } else {
       $std_form_element = '<input type="text" name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . '][std]" value="' . esc_attr( $std ) . '" class="widefat option-tree-ui-input" autocomplete="off" />';
@@ -3245,11 +4091,11 @@
     <div class="option-tree-setting">
       <div class="open">' . ( isset( $setting['label'] ) ? esc_attr( $setting['label'] ) : 'Setting ' . ( $key + 1 ) ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
-          <span class="icon pencil">' . __( 'Edit', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
       <div class="option-tree-setting-body">
@@ -3295,7 +4141,7 @@
               <ul class="option-tree-setting-wrap option-tree-sortable" data-name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . ']">
                 ' . ( isset( $setting['choices'] ) ? ot_loop_through_choices( $name . '[' . $key . ']', $setting['choices'] ) : '' ) . '
               </ul>
-              <a href="javascript:void(0);" class="option-tree-choice-add option-tree-ui-button hug-left">' . __( 'Add Choice', 'option-tree' ) . '</a>
+              <a href="javascript:void(0);" class="option-tree-choice-add option-tree-ui-button button hug-left">' . __( 'Add Choice', 'option-tree' ) . '</a>
             </div>
           </div>
         </div>
@@ -3306,7 +4152,7 @@
               <ul class="option-tree-setting-wrap option-tree-sortable" data-name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . ']">
                 ' . ( isset( $setting['settings'] ) ? ot_loop_through_sub_settings( $name . '[' . $key . '][settings]', $setting['settings'] ) : '' ) . '
               </ul>
-              <a href="javascript:void(0);" class="option-tree-list-item-setting-add option-tree-ui-button hug-left">' . __( 'Add Setting', 'option-tree' ) . '</a>
+              <a href="javascript:void(0);" class="option-tree-list-item-setting-add option-tree-ui-button button hug-left">' . __( 'Add Setting', 'option-tree' ) . '</a>
             </div>
           </div>
         </div>
@@ -3358,6 +4204,25 @@
             </div>
           </div>
         </div>
+        <div class="format-settings">
+          <div class="format-setting type-text wide-desc">
+            <div class="description">' . sprintf( __( '<strong>Condition</strong>: Add a comma separated list (no spaces) of conditions in which the field will be visible, leave this setting empty to always show the field. In these examples, <code>value</code> is a placeholder for your condition, which can be in the form of %s.', 'option-tree' ), '<code>field_id:is(value)</code>, <code>field_id:not(value)</code>, <code>field_id:contains(value)</code>, <code>field_id:less_than(value)</code>, <code>field_id:less_than_or_equal_to(value)</code>, <code>field_id:greater_than(value)</code>, or <code>field_id:greater_than_or_equal_to(value)</code>' ) . '</div>
+            <div class="format-setting-inner">
+              <input type="text" name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . '][condition]" value="' . ( isset( $setting['condition'] ) ? esc_attr( $setting['condition'] ) : '' ) . '" class="widefat option-tree-ui-input" autocomplete="off" />
+            </div>
+          </div>
+        </div>
+        <div class="format-settings">
+          <div class="format-setting type-select wide-desc">
+            <div class="description">' . __( '<strong>Operator</strong>: Choose the logical operator to compute the result of the conditions.', 'option-tree' ) . '</div>
+            <div class="format-setting-inner">
+              <select name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . '][operator]" value="' . $operator . '" class="option-tree-ui-select">
+                <option value="and" ' . selected( $operator, 'and', false ) . '>' . __( 'and', 'option-tree' ) . '</option>
+                <option value="or" ' . selected( $operator, 'or', false ) . '>' . __( 'or', 'option-tree' ) . '</option>
+              </select>
+            </div>
+          </div>
+        </div>
       </div>
     </div>
     ' . ( ! $child ? '<input type="hidden" class="hidden-section" name="' . esc_attr( $name ) . '[' . esc_attr( $key ) . '][section]" value="' . ( isset( $setting['section'] ) ? esc_attr( $setting['section'] ) : '' ) . '" />' : '' );
@@ -3389,11 +4254,11 @@
     <div class="option-tree-setting">
       <div class="open">' . ( isset( $choice['label'] ) ? esc_attr( $choice['label'] ) : 'Choice ' . ( $key + 1 ) ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
-          <span class="icon pencil">' . __( 'Edit', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
       <div class="option-tree-setting-body">
@@ -3455,11 +4320,11 @@
     <div class="option-tree-setting">
       <div class="open">' . ( isset( $content['title'] ) ? esc_attr( $content['title'] ) : 'Content ' . ( $key + 1 ) ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
-          <span class="icon pencil">' . __( 'Edit', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
       <div class="option-tree-setting-body">
@@ -3506,22 +4371,22 @@
  * @access    public
  * @since     2.0
  */
-if ( ! function_exists( 'ot_layouts_view' ) ) {
+if ( ! function_exists( 'ot_layout_view' ) ) {
 
   function ot_layout_view( $key, $data = '', $active_layout = '' ) {
-  
+
     return '
     <div class="option-tree-setting">
       <div class="open">' . ( isset( $key ) ? esc_attr( $key ) : __( 'Layout', 'option-tree' ) ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-layout-activate option-tree-ui-button left-item' . ( $active_layout == $key ? ' active' : '' ) . '" title="' . __( 'Activate', 'option-tree' ) . '">
-          <span class="icon check">' . __( 'Activate', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-layout-activate option-tree-ui-button button left-item' . ( $active_layout == $key ? ' active' : '' ) . '" title="' . __( 'Activate', 'option-tree' ) . '">
+          <span class="icon ot-icon-square-o"></span>' . __( 'Activate', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="'. __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="'. __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
-      <input type="hidden" name="option_tree_layouts[' . esc_attr( $key ) . ']" value="' . $data . '" />
+      <input type="hidden" name="' . ot_layouts_id() . '[' . esc_attr( $key ) . ']" value="' . $data . '" />
     </div>';
     
   }
@@ -3583,11 +4448,164 @@
     <div class="option-tree-setting">
       <div class="open">' . ( isset( $list_item['title'] ) ? esc_attr( $list_item['title'] ) : '' ) . '</div>
       <div class="button-section">
-        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
-          <span class="icon pencil">' . __( 'Edit', 'option-tree' ) . '</span>
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
+        </a>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
-        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button red light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
-          <span class="icon trash-can">' . __( 'Delete', 'option-tree' ) . '</span>
+      </div>
+      <div class="option-tree-setting-body">';
+        
+      foreach( $settings as $field ) {
+        
+        // Set field value
+        $field_value = isset( $list_item[$field['id']] ) ? $list_item[$field['id']] : '';
+        
+        /* set default to standard value */
+        if ( isset( $field['std'] ) ) {  
+          $field_value = ot_filter_std_value( $field_value, $field['std'] );
+        }
+        
+        // filter the title label and description
+        if ( $field['id'] == 'title' ) {
+          
+          // filter the label
+          $field['label'] = apply_filters( 'ot_list_item_title_label', $field['label'], $name );
+          
+          // filter the description
+          $field['desc'] = apply_filters( 'ot_list_item_title_desc', $field['desc'], $name );
+        
+        }
+          
+        /* make life easier */
+        $_field_name = $get_option ? $get_option . '[' . $name . ']' : $name;
+             
+        /* build the arguments array */
+        $_args = array(
+          'type'              => $field['type'],
+          'field_id'          => $name . '_' . $field['id'] . '_' . $key,
+          'field_name'        => $_field_name . '[' . $key . '][' . $field['id'] . ']',
+          'field_value'       => $field_value,
+          'field_desc'        => isset( $field['desc'] ) ? $field['desc'] : '',
+          'field_std'         => isset( $field['std'] ) ? $field['std'] : '',
+          'field_rows'        => isset( $field['rows'] ) ? $field['rows'] : 10,
+          'field_post_type'   => isset( $field['post_type'] ) && ! empty( $field['post_type'] ) ? $field['post_type'] : 'post',
+          'field_taxonomy'    => isset( $field['taxonomy'] ) && ! empty( $field['taxonomy'] ) ? $field['taxonomy'] : 'category',
+          'field_min_max_step'=> isset( $field['min_max_step'] ) && ! empty( $field['min_max_step'] ) ? $field['min_max_step'] : '0,100,1',
+          'field_class'       => isset( $field['class'] ) ? $field['class'] : '',
+          'field_condition'   => isset( $field['condition'] ) ? $field['condition'] : '',
+          'field_operator'    => isset( $field['operator'] ) ? $field['operator'] : 'and',
+          'field_choices'     => isset( $field['choices'] ) && ! empty( $field['choices'] ) ? $field['choices'] : array(),
+          'field_settings'    => isset( $field['settings'] ) && ! empty( $field['settings'] ) ? $field['settings'] : array(),
+          'post_id'           => $post_id,
+          'get_option'        => $get_option
+        );
+        
+        $conditions = '';
+        
+        /* setup the conditions */
+        if ( isset( $field['condition'] ) && ! empty( $field['condition'] ) ) {
+          
+          /* doing magic on the conditions so they work in a list item */
+          $conditionals = explode( ',', $field['condition'] );
+          foreach( $conditionals as $condition ) {
+            $parts = explode( ':', $condition );
+            if ( isset( $parts[0] ) ) {
+              $field['condition'] = str_replace( $condition, $name . '_' . $parts[0] . '_' . $key . ':' . $parts[1], $field['condition'] );
+            }
+          }
+
+          $conditions = ' data-condition="' . $field['condition'] . '"';
+          $conditions.= isset( $field['operator'] ) && in_array( $field['operator'], array( 'and', 'AND', 'or', 'OR' ) ) ? ' data-operator="' . $field['operator'] . '"' : '';
+
+        }
+
+        // Build the setting CSS class
+        if ( ! empty( $_args['field_class'] ) ) {
+
+          $classes = explode( ' ', $_args['field_class'] );
+
+          foreach( $classes as $_key => $value ) {
+
+            $classes[$_key] = $value . '-wrap';
+
+          }
+
+          $class = 'format-settings ' . implode( ' ', $classes );
+
+        } else {
+
+          $class = 'format-settings';
+
+        }
+          
+        /* option label */
+        echo '<div id="setting_' . $_args['field_id'] . '" class="' . $class . '"' . $conditions . '>';
+          
+          /* don't show title with textblocks */
+          if ( $_args['type'] != 'textblock' && ! empty( $field['label'] ) ) {
+            echo '<div class="format-setting-label">';
+              echo '<h3 class="label">' . esc_attr( $field['label'] ) . '</h3>';
+            echo '</div>';
+          }
+          
+          /* only allow simple textarea inside a list-item due to known DOM issues with wp_editor() */
+          if ( apply_filters( 'ot_override_forced_textarea_simple', false, $field['id'] ) == false && $_args['type'] == 'textarea' )
+            $_args['type'] = 'textarea-simple';
+            
+          /* option body, list-item is not allowed inside another list-item */
+          if ( $_args['type'] !== 'list-item' && $_args['type'] !== 'slider' ) {
+            echo ot_display_by_type( $_args );
+          }
+        
+        echo '</div>';
+      
+      }
+        
+      echo '</div>';
+    
+    echo '</div>';
+    
+  }
+  
+}
+
+/**
+ * Helper function to display social links.
+ *
+ * This function is used in AJAX to add a new list items
+ * and when they have already been added and saved.
+ *
+ * @param     string    $name The form field name.
+ * @param     int       $key The array key for the current element.
+ * @param     array     An array of values for the current list item.
+ *
+ * @return    void
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+if ( ! function_exists( 'ot_social_links_view' ) ) {
+
+  function ot_social_links_view( $name, $key, $list_item = array(), $post_id = 0, $get_option = '', $settings = array(), $type = '' ) {
+    
+    /* if no settings array load the filterable social links settings */
+    if ( empty( $settings ) ) {
+      
+      $settings = ot_social_links_settings( $name );
+      
+    }
+    
+    echo '
+    <div class="option-tree-setting">
+      <div class="open">' . ( isset( $list_item['name'] ) ? esc_attr( $list_item['name'] ) : '' ) . '</div>
+      <div class="button-section">
+        <a href="javascript:void(0);" class="option-tree-setting-edit option-tree-ui-button button left-item" title="' . __( 'Edit', 'option-tree' ) . '">
+          <span class="icon ot-icon-pencil"></span>' . __( 'Edit', 'option-tree' ) . '
+        </a>
+        <a href="javascript:void(0);" class="option-tree-setting-remove option-tree-ui-button button button-secondary light right-item" title="' . __( 'Delete', 'option-tree' ) . '">
+          <span class="icon ot-icon-trash-o"></span>' . __( 'Delete', 'option-tree' ) . '
         </a>
       </div>
       <div class="option-tree-setting-body">';
@@ -3618,38 +4636,59 @@
           'field_taxonomy'    => isset( $field['taxonomy'] ) && ! empty( $field['taxonomy'] ) ? $field['taxonomy'] : 'category',
           'field_min_max_step'=> isset( $field['min_max_step'] ) && ! empty( $field['min_max_step'] ) ? $field['min_max_step'] : '0,100,1',
           'field_class'       => isset( $field['class'] ) ? $field['class'] : '',
+          'field_condition'   => isset( $field['condition'] ) ? $field['condition'] : '',
+          'field_operator'    => isset( $field['operator'] ) ? $field['operator'] : 'and',
           'field_choices'     => isset( $field['choices'] ) && ! empty( $field['choices'] ) ? $field['choices'] : array(),
           'field_settings'    => isset( $field['settings'] ) && ! empty( $field['settings'] ) ? $field['settings'] : array(),
           'post_id'           => $post_id,
           'get_option'        => $get_option
         );
+        
+        $conditions = '';
+        
+        /* setup the conditions */
+        if ( isset( $field['condition'] ) && ! empty( $field['condition'] ) ) {
+          
+          /* doing magic on the conditions so they work in a list item */
+          $conditionals = explode( ',', $field['condition'] );
+          foreach( $conditionals as $condition ) {
+            $parts = explode( ':', $condition );
+            if ( isset( $parts[0] ) ) {
+              $field['condition'] = str_replace( $condition, $name . '_' . $parts[0] . '_' . $key . ':' . $parts[1], $field['condition'] );
+            }
+          }
+
+          $conditions = ' data-condition="' . $field['condition'] . '"';
+          $conditions.= isset( $field['operator'] ) && in_array( $field['operator'], array( 'and', 'AND', 'or', 'OR' ) ) ? ' data-operator="' . $field['operator'] . '"' : '';
+
+        }
           
         /* option label */
-        echo '<div class="format-settings">';
+        echo '<div id="setting_' . $_args['field_id'] . '" class="format-settings"' . $conditions . '>';
+          
+          /* don't show title with textblocks */
+          if ( $_args['type'] != 'textblock' && ! empty( $field['label'] ) ) {
+            echo '<div class="format-setting-label">';
+              echo '<h3 class="label">' . esc_attr( $field['label'] ) . '</h3>';
+            echo '</div>';
+          }
           
-        /* don't show title with textblocks */
-        if ( $_args['type'] != 'textblock' && ! empty( $field['label'] ) ) {
-          echo '<div class="format-setting-label">';
-            echo '<h3 class="label">' . esc_attr( $field['label'] ) . '</h3>';
-          echo '</div>';
-        }
-        
-        /* only allow simple textarea inside a list-item due to known DOM issues with wp_editor() */
-        if ( $_args['type'] == 'textarea' )
-          $_args['type'] = 'textarea-simple';
+          /* only allow simple textarea inside a list-item due to known DOM issues with wp_editor() */
+          if ( $_args['type'] == 'textarea' )
+            $_args['type'] = 'textarea-simple';
           
-        /* option body, list-item is not allowed inside another list-item */
-        if ( $_args['type'] !== 'list-item' && $_args['type'] !== 'slider' ) {
-          echo ot_display_by_type( $_args );
-        }
+          /* option body, list-item is not allowed inside another list-item */
+          if ( $_args['type'] !== 'list-item' && $_args['type'] !== 'slider' && $_args['type'] !== 'social-links' ) {
+            echo ot_display_by_type( $_args );
+          }
         
         echo '</div>';
       
       }
         
-    echo
-      '</div>
-    </div>';
+      echo '</div>';
+    
+    echo '</div>';
     
   }
   
@@ -3673,7 +4712,7 @@
       wp_nonce_field( 'option_tree_modify_layouts_form', 'option_tree_modify_layouts_nonce' );
         
       /* get the saved layouts */
-      $layouts = get_option( 'option_tree_layouts' );
+      $layouts = get_option( ot_layouts_id() );
       
       /* set active layout */
       $active_layout = isset( $layouts['active_layout'] ) ? $layouts['active_layout'] : '';
@@ -3686,7 +4725,7 @@
         
         echo '<div class="option-tree-active-layout">';
         
-          echo '<select name="option_tree_layouts[active_layout]" class="option-tree-ui-select">';
+          echo '<select name="' . ot_layouts_id() . '[active_layout]" class="option-tree-ui-select">';
       
             foreach( $layouts as $key => $data ) { 
               
@@ -3705,7 +4744,7 @@
           if ( $key == 'active_layout' )
               continue;
               
-          echo '<input type="hidden" name="option_tree_layouts[' . $key . ']" value="' . ( isset( $data ) ? $data : '' ) . '" />';
+          echo '<input type="hidden" name="' . ot_layouts_id() . '[' . $key . ']" value="' . ( isset( $data ) ? $data : '' ) . '" />';
           
         }
        
@@ -3715,9 +4754,9 @@
       echo '<div class="option-tree-save-layout' . ( ! empty( $active_layout ) ? ' active-layout' : '' ) . '">';
         
         /* add new layout */
-        echo '<input type="text" name="option_tree_layouts[_add_new_layout_]" value="" class="widefat option-tree-ui-input" autocomplete="off" />';
+        echo '<input type="text" name="' . ot_layouts_id() . '[_add_new_layout_]" value="" class="widefat option-tree-ui-input" autocomplete="off" />';
         
-        echo '<button type="submit" class="option-tree-ui-button blue save-layout" title="' . __( 'New Layout', 'option-tree' ) . '">' . __( 'New Layout', 'option-tree' ) . '</button>';
+        echo '<button type="submit" class="option-tree-ui-button button button-primary save-layout" title="' . __( 'New Layout', 'option-tree' ) . '">' . __( 'New Layout', 'option-tree' ) . '</button>';
       
       echo '</div>';
       
@@ -4105,6 +5144,178 @@
 }
 
 /**
+ * Helper function to set the Google fonts array.
+ *
+ * @param     string    $id The option ID.
+ * @param     bool      $value The option value
+ * @return    void
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+function ot_set_google_fonts( $id = '', $value = '' ) {
+
+  $ot_set_google_fonts = get_theme_mod( 'ot_set_google_fonts', array() );
+
+  if ( is_array( $value ) && ! empty( $value ) ) {
+    $ot_set_google_fonts[$id] = $value;
+  } else if ( isset( $ot_set_google_fonts[$id] ) ) {
+    unset( $ot_set_google_fonts[$id] );
+  }
+
+  set_theme_mod( 'ot_set_google_fonts', $ot_set_google_fonts );
+
+}
+
+/**
+ * Helper function to remove unused options from the Google fonts array.
+ *
+ * @param     array     $options The array of saved options.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+function ot_update_google_fonts_after_save( $options ) {
+
+  $ot_set_google_fonts = get_theme_mod( 'ot_set_google_fonts', array() );
+
+  foreach( $ot_set_google_fonts as $key => $set ) {
+    if ( ! isset( $options[$key] ) ) {
+      unset( $ot_set_google_fonts[$key] );
+    }
+  }
+  set_theme_mod( 'ot_set_google_fonts', $ot_set_google_fonts );
+
+}
+add_action( 'ot_after_theme_options_save', 'ot_update_google_fonts_after_save', 1 );
+
+/**
+ * Helper function to fetch the Google fonts array.
+ *
+ * @param     bool      $normalize Whether or not to return a normalized array. Default 'true'.
+ * @param     bool      $force_rebuild Whether or not to force the array to be rebuilt. Default 'false'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+function ot_fetch_google_fonts( $normalize = true, $force_rebuild = false ) {
+
+  /* Google Fonts cache key */
+  $ot_google_fonts_cache_key = apply_filters( 'ot_google_fonts_cache_key', 'ot_google_fonts_cache' );
+
+  /* get the fonts from cache */
+  $ot_google_fonts = apply_filters( 'ot_google_fonts_cache', get_transient( $ot_google_fonts_cache_key ) );
+
+  if ( $force_rebuild || ! is_array( $ot_google_fonts ) || empty( $ot_google_fonts ) ) {
+
+    $ot_google_fonts = array();
+
+    /* API url and key */
+    $ot_google_fonts_api_url = apply_filters( 'ot_google_fonts_api_url', 'https://www.googleapis.com/webfonts/v1/webfonts' );
+    $ot_google_fonts_api_key = apply_filters( 'ot_google_fonts_api_key', 'AIzaSyB8G-4UtQr9fhDYTiNrDP40Y5GYQQKrNWI' );
+
+    /* API arguments */
+    $ot_google_fonts_fields = apply_filters( 'ot_google_fonts_fields', array( 'family', 'variants', 'subsets' ) );
+    $ot_google_fonts_sort   = apply_filters( 'ot_google_fonts_sort', 'alpha' );
+
+    /* Initiate API request */
+    $ot_google_fonts_query_args = array(
+      'key'    => $ot_google_fonts_api_key, 
+      'fields' => 'items(' . implode( ',', $ot_google_fonts_fields ) . ')', 
+      'sort'   => $ot_google_fonts_sort
+    );
+
+    /* Build and make the request */
+    $ot_google_fonts_query = esc_url_raw( add_query_arg( $ot_google_fonts_query_args, $ot_google_fonts_api_url ) );
+    $ot_google_fonts_response = wp_safe_remote_get( $ot_google_fonts_query, array( 'sslverify' => false, 'timeout' => 15 ) );
+
+    /* continue if we got a valid response */
+    if ( 200 == wp_remote_retrieve_response_code( $ot_google_fonts_response ) ) {
+
+      if ( $response_body = wp_remote_retrieve_body( $ot_google_fonts_response ) ) {
+
+        /* JSON decode the response body and cache the result */
+        $ot_google_fonts_data = json_decode( trim( $response_body ), true );
+
+        if ( is_array( $ot_google_fonts_data ) && isset( $ot_google_fonts_data['items'] ) ) {
+
+          $ot_google_fonts = $ot_google_fonts_data['items'];
+          
+          // Normalize the array key
+          $ot_google_fonts_tmp = array();
+          foreach( $ot_google_fonts as $key => $value ) {
+            $id = remove_accents( $value['family'] );
+            $id = strtolower( $id );
+            $id = preg_replace( '/[^a-z0-9_\-]/', '', $id );
+            $ot_google_fonts_tmp[$id] = $value;
+          }
+          
+          $ot_google_fonts = $ot_google_fonts_tmp;
+          set_theme_mod( 'ot_google_fonts', $ot_google_fonts );
+          set_transient( $ot_google_fonts_cache_key, $ot_google_fonts, WEEK_IN_SECONDS );
+
+        }
+
+      }
+
+    }
+
+  }
+
+  return $normalize ? ot_normalize_google_fonts( $ot_google_fonts ) : $ot_google_fonts;
+
+}
+
+/**
+ * Helper function to normalize the Google fonts array.
+ *
+ * @param     array     $google_fonts An array of fonts to nrmalize.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.5.0
+ */
+function ot_normalize_google_fonts( $google_fonts ) {
+
+  $ot_normalized_google_fonts = array();
+
+  if ( is_array( $google_fonts ) && ! empty( $google_fonts ) ) {
+
+    foreach( $google_fonts as $google_font ) {
+
+      if( isset( $google_font['family'] ) ) {
+
+        $id = str_replace( ' ', '+', $google_font['family'] );
+
+        $ot_normalized_google_fonts[ $id ] = array(
+          'family' => $google_font['family']
+        );
+
+        if( isset( $google_font['variants'] ) ) {
+
+          $ot_normalized_google_fonts[ $id ]['variants'] = $google_font['variants'];
+
+        }
+
+        if( isset( $google_font['subsets'] ) ) {
+
+          $ot_normalized_google_fonts[ $id ]['subsets'] = $google_font['subsets'];
+
+        }
+
+      }
+
+    }
+
+  }
+
+  return $ot_normalized_google_fonts;
+
+}
+
+/**
  * Helper function to register a WPML string
  *
  * @access    public
@@ -4136,5 +5347,777 @@
   
 }
 
+/**
+ * Maybe migrate Settings
+ *
+ * @return    void
+ *
+ * @access    public
+ * @since     2.3.3
+ */
+if ( ! function_exists( 'ot_maybe_migrate_settings' ) ) {
+
+  function ot_maybe_migrate_settings() {
+    
+    // Filter the ID to migrate from
+    $settings_id = apply_filters( 'ot_migrate_settings_id', '' );
+    
+    // Attempt to migrate Settings 
+    if ( ! empty( $settings_id ) && get_option( ot_settings_id() ) === false && ot_settings_id() !== $settings_id ) {
+      
+      // Old settings
+      $settings = get_option( $settings_id );
+      
+      // Check for array keys
+      if ( isset( $settings['sections'] ) && isset( $settings['settings'] ) ) {
+      
+        update_option( ot_settings_id(), $settings );
+        
+      }
+      
+    }
+
+  }
+  
+}
+
+/**
+ * Maybe migrate Option
+ *
+ * @return    void
+ *
+ * @access    public
+ * @since     2.3.3
+ */
+if ( ! function_exists( 'ot_maybe_migrate_options' ) ) {
+
+  function ot_maybe_migrate_options() {
+    
+    // Filter the ID to migrate from
+    $options_id = apply_filters( 'ot_migrate_options_id', '' );
+    
+    // Attempt to migrate Theme Options
+    if ( ! empty( $options_id ) && get_option( ot_options_id() ) === false && ot_options_id() !== $options_id ) {
+      
+      // Old options
+      $options = get_option( $options_id );
+      
+      // Migrate to new ID
+      update_option( ot_options_id(), $options );
+      
+    }
+
+  }
+  
+}
+
+/**
+ * Maybe migrate Layouts
+ *
+ * @return    void
+ *
+ * @access    public
+ * @since     2.3.3
+ */
+if ( ! function_exists( 'ot_maybe_migrate_layouts' ) ) {
+
+  function ot_maybe_migrate_layouts() {
+    
+    // Filter the ID to migrate from
+    $layouts_id = apply_filters( 'ot_migrate_layouts_id', '' );
+    
+    // Attempt to migrate Layouts
+    if ( ! empty( $layouts_id ) && get_option( ot_layouts_id() ) === false && ot_layouts_id() !== $layouts_id ) {
+      
+      // Old options
+      $layouts = get_option( $layouts_id );
+      
+      // Migrate to new ID
+      update_option( ot_layouts_id(), $layouts );
+      
+    }
+
+  }
+
+}
+
+/**
+ * Returns an array with the post format gallery meta box.
+ *
+ * @param     mixed     $pages Excepts a comma separated string or array of 
+ *                      post_types and is what tells the metabox where to 
+ *                      display. Default 'post'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+function ot_meta_box_post_format_gallery( $pages = 'post' ) {
+
+  if ( ! current_theme_supports( 'post-formats' ) || ! in_array( 'gallery', current( get_theme_support( 'post-formats' ) ) ) )
+    return false;
+    
+  if ( is_string( $pages ) )
+    $pages = explode( ',', $pages );
+  
+  return apply_filters( 'ot_meta_box_post_format_gallery', array(
+    'id'        => 'ot-post-format-gallery',
+    'title'     => __( 'Gallery', 'option-tree' ),
+    'desc'      => '',
+    'pages'     => $pages,
+    'context'   => 'side',
+    'priority'  => 'low',
+    'fields'    => array(
+      array(
+        'id'          => '_format_gallery',
+        'label'       => '',
+        'desc'        => '',
+        'std'         => '',
+        'type'        => 'gallery',
+        'class'       => 'ot-gallery-shortcode'
+      )
+  	)
+  ), $pages );
+
+}
+
+/**
+ * Returns an array with the post format link metabox.
+ *
+ * @param     mixed     $pages Excepts a comma separated string or array of 
+ *                      post_types and is what tells the metabox where to 
+ *                      display. Default 'post'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+function ot_meta_box_post_format_link( $pages = 'post' ) {
+  
+  if ( ! current_theme_supports( 'post-formats' ) || ! in_array( 'link', current( get_theme_support( 'post-formats' ) ) ) )
+    return false;
+    
+  if ( is_string( $pages ) )
+    $pages = explode( ',', $pages );
+  
+  return apply_filters( 'ot_meta_box_post_format_link', array(
+    'id'        => 'ot-post-format-link',
+    'title'     => __( 'Link', 'option-tree' ),
+    'desc'      => '',
+    'pages'     => $pages,
+    'context'   => 'side',
+    'priority'  => 'low',
+    'fields'    => array(
+      array(
+        'id'      => '_format_link_url',
+        'label'   => '',
+        'desc'    => __( 'Link URL', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      ),
+      array(
+        'id'      => '_format_link_title',
+        'label'   => '',
+        'desc'    => __( 'Link Title', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      )
+  	)
+  ), $pages );
+
+}
+
+/**
+ * Returns an array with the post format quote metabox.
+ *
+ * @param     mixed     $pages Excepts a comma separated string or array of 
+ *                      post_types and is what tells the metabox where to 
+ *                      display. Default 'post'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+function ot_meta_box_post_format_quote( $pages = 'post' ) {
+  
+  if ( ! current_theme_supports( 'post-formats' ) || ! in_array( 'quote', current( get_theme_support( 'post-formats' ) ) ) )
+    return false;
+    
+  if ( is_string( $pages ) )
+    $pages = explode( ',', $pages );
+
+  return apply_filters( 'ot_meta_box_post_format_quote', array(
+    'id'        => 'ot-post-format-quote',
+    'title'     => __( 'Quote', 'option-tree' ),
+    'desc'      => '',
+    'pages'     => $pages,
+    'context'   => 'side',
+    'priority'  => 'low',
+    'fields'    => array(
+      array(
+        'id'      => '_format_quote_source_name',
+        'label'   => '',
+        'desc'    => __( 'Source Name (ex. author, singer, actor)', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      ),
+      array(
+        'id'      => '_format_quote_source_url',
+        'label'   => '',
+        'desc'    => __( 'Source URL', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      ),
+      array(
+        'id'      => '_format_quote_source_title',
+        'label'   => '',
+        'desc'    => __( 'Source Title (ex. book, song, movie)', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      ),
+      array(
+        'id'      => '_format_quote_source_date',
+        'label'   => '',
+        'desc'    => __( 'Source Date', 'option-tree' ),
+        'std'     => '',
+        'type'    => 'text'
+      )
+  	)
+  ), $pages );
+
+}
+
+/**
+ * Returns an array with the post format video metabox.
+ *
+ * @param     mixed     $pages Excepts a comma separated string or array of 
+ *                      post_types and is what tells the metabox where to 
+ *                      display. Default 'post'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+function ot_meta_box_post_format_video( $pages = 'post' ) {
+  
+  if ( ! current_theme_supports( 'post-formats' ) || ! in_array( 'video', current( get_theme_support( 'post-formats' ) ) ) )
+    return false;
+    
+  if ( is_string( $pages ) )
+    $pages = explode( ',', $pages );
+  
+  return apply_filters( 'ot_meta_box_post_format_video', array(
+    'id'        => 'ot-post-format-video',
+    'title'     => __( 'Video', 'option-tree' ),
+    'desc'      => '',
+    'pages'     => $pages,
+    'context'   => 'side',
+    'priority'  => 'low',
+    'fields'    => array(
+      array(
+        'id'      => '_format_video_embed',
+        'label'   => '',
+        'desc'    => sprintf( __( 'Embed video from services like Youtube, Vimeo, or Hulu. You can find a list of supported oEmbed sites in the %1$s. Alternatively, you could use the built-in %2$s shortcode.', 'option-tree' ), '<a href="http://codex.wordpress.org/Embeds" target="_blank">' . __( 'Wordpress Codex', 'option-tree' ) .'</a>', '<code>[video]</code>' ),
+        'std'     => '',
+        'type'    => 'textarea'
+      )
+  	)
+  ), $pages );
+
+}
+
+/**
+ * Returns an array with the post format audio metabox.
+ *
+ * @param     mixed     $pages Excepts a comma separated string or array of 
+ *                      post_types and is what tells the metabox where to 
+ *                      display. Default 'post'.
+ * @return    array
+ *
+ * @access    public
+ * @since     2.4.0
+ */
+function ot_meta_box_post_format_audio( $pages = 'post' ) {
+  
+  if ( ! current_theme_supports( 'post-formats' ) || ! in_array( 'audio', current( get_theme_support( 'post-formats' ) ) ) )
+    return false;
+    
+  if ( is_string( $pages ) )
+    $pages = explode( ',', $pages );
+  
+  return apply_filters( 'ot_meta_box_post_format_audio', array(
+    'id'        => 'ot-post-format-audio',
+    'title'     => __( 'Audio', 'option-tree' ),
+    'desc'      => '',
+    'pages'     => $pages,
+    'context'   => 'side',
+    'priority'  => 'low',
+    'fields'    => array(
+      array(
+        'id'      => '_format_audio_embed',
+        'label'   => '',
+        'desc'    => sprintf( __( 'Embed audio from services like SoundCloud and Rdio. You can find a list of supported oEmbed sites in the %1$s. Alternatively, you could use the built-in %2$s shortcode.', 'option-tree' ), '<a href="http://codex.wordpress.org/Embeds" target="_blank">' . __( 'Wordpress Codex', 'option-tree' ) .'</a>', '<code>[audio]</code>' ),
+        'std'     => '',
+        'type'    => 'textarea'
+      )
+  	)
+  ), $pages );
+
+}
+
+/**
+ * Returns the option type by ID.
+ *
+ * @param     string    $option_id The option ID
+ * @return    string    $settings_id The settings array ID
+ * @return    string    The option type.
+ *
+ * @access    public
+ * @since     2.4.2
+ */
+if ( ! function_exists( 'ot_get_option_type_by_id' ) ) {
+
+  function ot_get_option_type_by_id( $option_id, $settings_id = '' ) {
+    
+    if ( empty( $settings_id ) ) {
+    
+      $settings_id = ot_settings_id();
+    
+    }
+      
+    $settings = get_option( $settings_id, array() );
+    
+    if ( isset( $settings['settings'] ) ) {
+    
+      foreach( $settings['settings'] as $value ) {
+      
+        if ( $option_id == $value['id'] && isset( $value['type'] ) ) {
+        
+          return $value['type'];
+          
+        }
+        
+      }
+      
+    }
+    
+    return false;
+  
+  }
+  
+}
+
+/**
+ * Build an array of potential Theme Options that could share terms
+ *
+ * @return    array
+ *
+ * @access    private
+ * @since     2.5.4
+ */
+function _ot_settings_potential_shared_terms() {
+
+  $options      = array();
+  $settings     = get_option( ot_settings_id(), array() );
+  $option_types = array( 
+    'category-checkbox',
+    'category-select',
+    'tag-checkbox',
+    'tag-select',
+    'taxonomy-checkbox',
+    'taxonomy-select'
+  );
+
+  if ( isset( $settings['settings'] ) ) {
+
+    foreach( $settings['settings'] as $value ) {
+
+      if ( isset( $value['type'] ) ) {
+
+        if ( $value['type'] == 'list-item' && isset( $value['settings'] ) ) {
+
+          $saved = ot_get_option( $value['id'] );
+
+          foreach( $value['settings'] as $item ) {
+
+            if ( isset( $value['id'] ) && isset( $item['type'] ) && in_array( $item['type'], $option_types ) ) {
+              $sub_options = array();
+
+              foreach( $saved as $sub_key => $sub_value ) {
+                if ( isset( $sub_value[$item['id']] ) ) {
+                  $sub_options[$sub_key] = $sub_value[$item['id']];
+                }
+              }
+
+              if ( ! empty( $sub_options ) ) {
+                $options[] = array( 
+                  'id'       => $item['id'],
+                  'taxonomy' => $value['taxonomy'],
+                  'parent'   => $value['id'],
+                  'value'    => $sub_options
+                );
+              }
+            }
+
+          }
+
+        }
+
+        if ( in_array( $value['type'], $option_types ) ) {
+          $saved = ot_get_option( $value['id'] );
+          if ( ! empty( $saved ) ) {
+            $options[] = array( 
+              'id'       => $value['id'],
+              'taxonomy' => $value['taxonomy'],
+              'value'    => $saved
+            );
+          }
+        }
+
+      }
+
+    }
+
+  }
+
+  return $options;
+
+}
+
+/**
+ * Build an array of potential Meta Box options that could share terms
+ *
+ * @return    array
+ *
+ * @access    private
+ * @since     2.5.4
+ */
+function _ot_meta_box_potential_shared_terms() {
+  global $ot_meta_boxes;
+
+  $options      = array();
+  $settings     = $ot_meta_boxes;
+  $option_types = array( 
+    'category-checkbox',
+    'category-select',
+    'tag-checkbox',
+    'tag-select',
+    'taxonomy-checkbox',
+    'taxonomy-select'
+  );
+
+  foreach( $settings as $setting ) {
+
+    if ( isset( $setting['fields'] ) ) {
+
+      foreach( $setting['fields'] as $value ) {
+
+        if ( isset( $value['type'] ) ) {
+
+          if ( $value['type'] == 'list-item' && isset( $value['settings'] ) ) {
+
+            $children = array();
+
+            foreach( $value['settings'] as $item ) {
+
+              if ( isset( $value['id'] ) && isset( $item['type'] ) && in_array( $item['type'], $option_types ) ) {
+
+                $children[$value['id']][] = $item['id'];
+
+              }
+
+            }
+            
+            if ( ! empty( $children[$value['id']] ) ) {
+              $options[] = array( 
+                'id'       => $value['id'],
+                'children' => $children[$value['id']],
+                'taxonomy' => $value['taxonomy'],
+              );
+            }
+
+          }
+
+          if ( in_array( $value['type'], $option_types ) ) {
+
+            $options[] = array( 
+              'id'       => $value['id'],
+              'taxonomy' => $value['taxonomy'],
+            );
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+  return $options;
+
+}
+
+/**
+ * Update terms when a term gets split.
+ *
+ * @param     int     $term_id ID of the formerly shared term.
+ * @param     int     $new_term_id ID of the new term created for the $term_taxonomy_id.
+ * @param     int     $term_taxonomy_id ID for the term_taxonomy row affected by the split.
+ * @param     string  $taxonomy Taxonomy for the split term.
+ * @return    void
+ *
+ * @access    public
+ * @since     2.5.4
+ */
+function ot_split_shared_term( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
+
+  // Process the Theme Options
+  $settings    = _ot_settings_potential_shared_terms();
+  $old_options = get_option( ot_options_id(), array() );
+  $new_options = $old_options;
+
+  // Process the saved settings
+  if ( ! empty( $settings ) && ! empty( $old_options ) ) {
+
+    // Loop over the Theme Options
+    foreach( $settings as $option ) {
+
+      if ( ! is_array( $option['taxonomy'] ) ) {
+        $option['taxonomy'] = explode( ',', $option['taxonomy'] );
+      }
+
+      if ( ! in_array( $taxonomy, $option['taxonomy'] ) ) {
+        continue;
+      }
+
+      // The option ID was found
+      if ( array_key_exists( $option['id'], $old_options ) || ( isset( $option['parent'] ) && array_key_exists( $option['parent'], $old_options ) ) ) {
+
+        // This is a list item, we have to go deeper
+        if ( isset( $option['parent'] ) ) {
+
+          // Loop over the array
+          foreach( $option['value'] as $key => $value ) {
+
+            // The value is an array of IDs
+            if ( is_array( $value ) ) {
+
+              // Loop over the sub array
+              foreach( $value as $sub_key => $sub_value ) {
+
+                if ( $sub_value == $term_id ) {
+
+                  unset( $new_options[$option['parent']][$key][$option['id']][$sub_key] );
+                  $new_options[$option['parent']][$key][$option['id']][$new_term_id] = $new_term_id;
+
+                }
+
+              }
+
+            } else if ( $value == $term_id ) {
+
+              unset( $new_options[$option['parent']][$key][$option['id']] );
+              $new_options[$option['parent']][$key][$option['id']] = $new_term_id;
+
+            }
+
+          }
+
+        } else {
+
+          // The value is an array of IDs
+          if ( is_array( $option['value'] ) ) {
+
+            // Loop over the array
+            foreach( $option['value'] as $key => $value ) {
+
+              // It's a single value, just replace it
+              if ( $value == $term_id ) {
+
+                unset( $new_options[$option['id']][$key] );
+                $new_options[$option['id']][$new_term_id] = $new_term_id;
+
+              }
+
+            }
+
+          // It's a single value, just replace it
+          } else if ( $option['value'] == $term_id ) {
+
+            $new_options[$option['id']] = $new_term_id;
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+  // Options need to be updated
+  if ( $old_options !== $new_options ) {
+    update_option( ot_options_id(), $new_options );
+  }
+
+  // Process the Meta Boxes
+  $meta_settings = _ot_meta_box_potential_shared_terms();
+  $option_types  = array( 
+    'category-checkbox',
+    'category-select',
+    'tag-checkbox',
+    'tag-select',
+    'taxonomy-checkbox',
+    'taxonomy-select'
+  );
+
+  if ( ! empty( $meta_settings ) ) {
+    $old_meta = array();
+    
+    foreach( $meta_settings as $option ) {
+
+      if ( ! is_array( $option['taxonomy'] ) ) {
+        $option['taxonomy'] = explode( ',', $option['taxonomy'] );
+      }
+      
+      if ( ! in_array( $taxonomy, $option['taxonomy'] ) ) {
+        continue;
+      }
+
+      if ( isset( $option['children'] ) ) {
+        $post_ids = get_posts( array(
+          'fields'     => 'ids',
+          'meta_key'   => $option['id'],
+        ) );
+
+        if ( $post_ids ) {
+
+          foreach( $post_ids as $post_id ) {
+
+            // Get the meta
+            $old_meta = get_post_meta( $post_id, $option['id'], true );
+            $new_meta = $old_meta;
+
+            // Has a saved value
+            if ( ! empty( $old_meta ) && is_array( $old_meta ) ) {
+
+              // Loop over the array
+              foreach( $old_meta as $key => $value ) {
+
+                foreach( $value as $sub_key => $sub_value ) {
+
+                  if ( in_array( $sub_key, $option['children'] ) ) {
+
+                    // The value is an array of IDs
+                    if ( is_array( $sub_value ) ) {
+
+                      // Loop over the array
+                      foreach( $sub_value as $sub_sub_key => $sub_sub_value ) {
+
+                        // It's a single value, just replace it
+                        if ( $sub_sub_value == $term_id ) {
+
+                          unset( $new_meta[$key][$sub_key][$sub_sub_key] );
+                          $new_meta[$key][$sub_key][$new_term_id] = $new_term_id;
+
+                        }
+
+                      }
+
+                    // It's a single value, just replace it
+                    } else if ( $sub_value == $term_id ) {
+
+                      $new_meta[$key][$sub_key] = $new_term_id;
+
+                    }
+
+                  }
+
+                }
+
+              }
+
+              // Update
+              if ( $old_meta !== $new_meta ) {
+  
+                update_post_meta( $post_id, $option['id'], $new_meta, $old_meta );
+  
+              }
+
+            }
+
+          }
+
+        }
+
+      } else {
+        $post_ids = get_posts( array(
+          'fields'     => 'ids',
+          'meta_query' => array(
+            'key'     => $option['id'],
+            'value'   => $term_id,
+            'compare' => 'IN'
+          ),
+        ) );
+
+        if ( $post_ids ) {
+
+          foreach( $post_ids as $post_id ) {
+
+            // Get the meta
+            $old_meta = get_post_meta( $post_id, $option['id'], true );
+            $new_meta = $old_meta;
+
+            // Has a saved value
+            if ( ! empty( $old_meta ) ) {
+
+              // The value is an array of IDs
+              if ( is_array( $old_meta ) ) {
+
+                // Loop over the array
+                foreach( $old_meta as $key => $value ) {
+
+                  // It's a single value, just replace it
+                  if ( $value == $term_id ) {
+
+                    unset( $new_meta[$key] );
+                    $new_meta[$new_term_id] = $new_term_id;
+
+                  }
+
+                }
+
+              // It's a single value, just replace it
+              } else if ( $old_meta == $term_id ) {
+
+                $new_meta = $new_term_id;
+
+              }
+
+              // Update
+              if ( $old_meta !== $new_meta ) {
+  
+                update_post_meta( $post_id, $option['id'], $new_meta, $old_meta );
+  
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+}
+add_action( 'split_shared_term', 'ot_split_shared_term', 10, 4 );
+
 /* End of file ot-functions-admin.php */
 /* Location: ./includes/ot-functions-admin.php */
\ No newline at end of file