/**
  * Implements a multi-dimensional array_intersect_assoc.
  *
  * The standard array_intersect_assoc does the intersection based on string
  * values of the keys.
  * We need to find a way to recursively check multi-dimensional arrays.
  *
  * Note that we are not passing values here but references.
  *
  * @since  1.0.0
  *
  * @param mixed $arr1 First array to intersect.
  * @param mixed $arr2 Second array to intersect.
  * @return array Combined array.
  */
 public static function array_intersect_assoc_deep(&$arr1, &$arr2)
 {
     // If not arrays, at least associate the strings.
     // If 1 argument is an array and the other not throw error.
     if (!is_array($arr1) && !is_array($arr2)) {
         $arr1 = (string) $arr1;
         $arr2 = (string) $arr2;
         return $arr1 == $arr2 ? $arr1 : false;
     } elseif (is_array($arr1) !== is_array($arr2)) {
         MS_Helper_Debug::log('WARNING: MS_Helper_Utility::array_intersect_assoc_deep() - ' . 'Both params need to be of same type (array or string).', true);
         return false;
     }
     $intersections = array_intersect(array_keys($arr1), array_keys($arr2));
     $assoc_array = array();
     // Time to recursively run through the arrays
     foreach ($intersections as $key) {
         $result = MS_Helper_Utility::array_intersect_assoc_deep($arr1[$key], $arr2[$key]);
         if ($result) {
             $assoc_array[$key] = $result;
         }
     }
     return apply_filters('ms_helper_utility_array_intersect_assoc_deep', $assoc_array, $arr1, $arr2);
 }
 /**
  * Display the bulk actions dropdown.
  *
  * @since  1.0.0
  * @access public
  *
  * @param  bool $echo Output or return the HTML code? Default is output.
  */
 public function bulk_actions($echo = true)
 {
     if (!$this->is_search() && !$this->has_items()) {
         return '';
     }
     if (is_null($this->_actions)) {
         $no_new_actions = $this->_actions = $this->get_bulk_actions();
         /**
          * Filter the list table Bulk Actions drop-down.
          *
          * The dynamic portion of the hook name, $this->screen->id, refers
          * to the ID of the current screen, usually a string.
          *
          * This filter can currently only be used to remove bulk actions.
          *
          * @since  1.0.0
          *
          * @param array $actions An array of the available bulk actions.
          */
         $this->_actions = apply_filters("bulk_actions-{$this->screen->id}", $this->_actions);
         $this->_actions = MS_Helper_Utility::array_intersect_assoc_deep($this->_actions, $no_new_actions);
         $two = '';
     } else {
         $two = '2';
     }
     if (empty($this->_actions)) {
         return '';
     }
     if (!$echo) {
         ob_start();
     }
     /**
      * Allow other files to add additional code before the bulk actions.
      *
      * Note that this action is only triggered when bulk actions are
      * actually displayed.
      *
      * @since  1.0.0
      */
     do_action('ms_listtable_before_bulk_actions', $this);
     printf('<select name="action%s">', esc_attr($two));
     printf('<option value="-1" selected="selected">%s</option>', __('Bulk Actions'));
     foreach ($this->_actions as $name => $title) {
         if (is_array($title)) {
             printf('<optgroup label="%s">', esc_attr($name));
             foreach ($title as $value => $label) {
                 printf('<option value="%s">%s</option>', esc_attr($value), esc_attr($label));
             }
             echo '</optgroup>';
         } else {
             printf('<option value="%s">%s</option>', esc_attr($name), esc_attr($title));
         }
     }
     echo '</select>';
     submit_button(__('Apply'), 'action', false, false, array('id' => 'doaction' . esc_attr($two)));
     if (!$echo) {
         return ob_get_clean();
     }
 }