/**
  * Filter an array of Shortcode attributes.
  * 
  * Shortcodes have limited attributes and possibly limited values
  * for some attributes. This method matches each submitted attr
  * to its limited values if available, and apply a filter to the
  * value before returning the array.
  * 
  * @since    1.1.0
  * 
  * @param    string    $shortcode Shortcode's ID
  * @param    array     $atts Attributes to filter
  * @param    array     $defaults Default attributes if needed
  * 
  * @return   array    Filtered Attributes
  */
 public static function filter_shortcode_atts($shortcode, $atts = array(), $defaults = array())
 {
     if (!is_array($atts)) {
         $atts = array($atts);
     }
     if (empty($defaults)) {
         $defaults = WPMOLY_Settings::get_available_shortcodes();
         $defaults = $defaults[$shortcode]['atts'];
     }
     $attributes = array();
     // Loop through the Shortcode's attributes
     foreach ($defaults as $slug => $default) {
         if (isset($atts[$slug])) {
             $attr = $atts[$slug];
             // Attribute is not null
             if (is_null($attr)) {
                 $attributes[$slug] = $default['default'];
             } else {
                 if (!is_null($attr)) {
                     $value = $attr;
                     // Attribute has limited values
                     if (!is_null($default['values'])) {
                         // Value should be boolean
                         if ('boolean' == $default['values'] && in_array(strtolower($attr), array('true', 'false', 'yes', 'no'))) {
                             $value = wpmoly_is_boolean($attr);
                         } else {
                             if (is_array($default['values'])) {
                                 // multiple values
                                 if (false !== strpos($attr, '|')) {
                                     $value = str_replace('actors', 'cast', $attr);
                                     $value = explode('|', $value);
                                     foreach ($value as $i => $v) {
                                         if (!in_array($v, $default['values'])) {
                                             unset($value[$i]);
                                         }
                                     }
                                     array_unique($value);
                                 } else {
                                     if (in_array(strtolower($attr), $default['values'])) {
                                         $value = $attr;
                                     }
                                 }
                             }
                         }
                     }
                     // Attribute has a valid filter
                     if (is_string($value) && function_exists($default['filter']) && is_callable($default['filter'])) {
                         $value = call_user_func($default['filter'], $value);
                     }
                     $attributes[$slug] = $value;
                 }
             }
         } else {
             $attributes[$slug] = $default['default'];
         }
     }
     return $attributes;
 }