/**
  * Handle ajax term reordering
  *
  * This bit is inspired by the Simple Page Ordering plugin from 10up
  *
  * @since 0.1.0
  */
 public static function ajax_reordering_terms()
 {
     // Bail if required term data is missing
     if (empty($_POST['id']) || empty($_POST['tax']) || !isset($_POST['previd']) && !isset($_POST['nextid'])) {
         die(-1);
     }
     // Attempt to get the taxonomy
     $tax = get_taxonomy($_POST['tax']);
     // Bail if taxonomy does not exist
     if (empty($tax)) {
         die(-1);
     }
     // Bail if current user cannot assign terms
     if (!current_user_can($tax->cap->edit_terms)) {
         die(-1);
     }
     // Bail if term cannot be found
     $term = get_term($_POST['id'], $_POST['tax']);
     if (empty($term)) {
         die(-1);
     }
     // Sanitize positions
     $taxonomy = $_POST['tax'];
     $previd = empty($_POST['previd']) ? false : (int) $_POST['previd'];
     $nextid = empty($_POST['nextid']) ? false : (int) $_POST['nextid'];
     $start = empty($_POST['start']) ? 1 : (int) $_POST['start'];
     $excluded = empty($_POST['excluded']) ? array($term->term_id) : array_filter((array) $_POST['excluded'], 'intval');
     // Define return values
     $new_pos = array();
     $return_data = new stdClass();
     // attempt to get the intended parent...
     $parent_id = $term->parent;
     $next_term_parent = $nextid ? wp_get_term_taxonomy_parent_id($nextid, $taxonomy) : false;
     // If the preceding term is the parent of the next term, move it inside
     if ($previd === $next_term_parent) {
         $parent_id = $next_term_parent;
         // If the next term's parent isn't the same as our parent, we need more info
     } elseif ($next_term_parent !== $parent_id) {
         $prev_term_parent = $previd ? wp_get_term_taxonomy_parent_id($nextid, $taxonomy) : false;
         // If the previous term is not our parent now, set it
         if ($prev_term_parent !== $parent_id) {
             $parent_id = $prev_term_parent !== false ? $prev_term_parent : $next_term_parent;
         }
     }
     // If the next term's parent isn't our parent, set to false
     if ($next_term_parent !== $parent_id) {
         $nextid = false;
     }
     // Get term siblings for relative ordering
     $siblings = get_terms($taxonomy, array('depth' => 1, 'number' => 100, 'parent' => $parent_id, 'orderby' => 'order', 'order' => 'ASC', 'hide_empty' => false, 'exclude' => $excluded));
     // Loop through siblings and update terms
     foreach ($siblings as $sibling) {
         // Skip the actual term if it's in the array
         if ($sibling->term_id === (int) $term->term_id) {
             continue;
         }
         // If this is the term that comes after our repositioned term, set
         // our repositioned term position and increment order
         if ($nextid === (int) $sibling->term_id) {
             self::set_term_order($term->term_id, $taxonomy, $start, true);
             $ancestors = get_ancestors($term->term_id, $taxonomy, 'taxonomy');
             $new_pos[$term->term_id] = array('order' => $start, 'parent' => $parent_id, 'depth' => count($ancestors));
             $start++;
         }
         // If repositioned term has been set and new items are already in
         // the right order, we can stop looping
         if (isset($new_pos[$term->term_id]) && (int) $sibling->order >= $start) {
             $return_data->next = false;
             break;
         }
         // Set order of current sibling and increment the order
         if ($start !== (int) $sibling->order) {
             self::set_term_order($sibling->term_id, $taxonomy, $start, true);
         }
         $new_pos[$sibling->term_id] = $start;
         $start++;
         if (empty($nextid) && $previd === (int) $sibling->term_id) {
             self::set_term_order($term->term_id, $taxonomy, $start, true);
             $ancestors = get_ancestors($term->term_id, $taxonomy, 'taxonomy');
             $new_pos[$term->term_id] = array('order' => $start, 'parent' => $parent_id, 'depth' => count($ancestors));
             $start++;
         }
     }
     // max per request
     if (!isset($return_data->next) && count($siblings) > 1) {
         $return_data->next = array('id' => $term->term_id, 'previd' => $previd, 'nextid' => $nextid, 'start' => $start, 'excluded' => array_merge(array_keys($new_pos), $excluded), 'taxonomy' => $taxonomy);
     } else {
         $return_data->next = false;
     }
     if (empty($return_data->next)) {
         // If the moved term has children, refresh the page for UI reasons
         $children = get_terms($taxonomy, array('number' => 1, 'depth' => 1, 'orderby' => 'order', 'order' => 'ASC', 'parent' => $term->term_id, 'fields' => 'ids', 'hide_empty' => false));
         if (!empty($children)) {
             die('children');
         }
     }
     $return_data->new_pos = $new_pos;
     die(json_encode($return_data));
 }
 /**
  * Translate the value returned by 'option_{taxonomy}_children' and store it in cache
  *
  * @param array       $original_value
  * @param bool|string $current_language
  * @param bool|string $taxonomy
  *
  * @return array
  */
 function option_taxonomy_children($original_value, $current_language = false, $taxonomy = false)
 {
     if (!is_array($original_value) || count($original_value) == 0) {
         return $original_value;
     }
     $current_language = !$current_language ? $this->get_current_language() : $current_language;
     $default_language = $this->get_default_language();
     if ($current_language == $default_language) {
         return $original_value;
     }
     $cache_key_array[] = $current_language;
     $cache_key_array[] = $default_language;
     $cache_key_array[] = $original_value;
     $cache_key = md5(serialize($cache_key_array));
     $cache_group = 'translate_taxonomy_children';
     $cache_found = false;
     $result = wp_cache_get($cache_key, $cache_group, false, $cache_found);
     if ($cache_found) {
         return $result;
     }
     $debug_backtrace = $this->get_backtrace(4, false, false);
     //Find the taxonomy name
     if (!$taxonomy && isset($debug_backtrace[3]) && isset($debug_backtrace[3]['args'])) {
         $option_name = $debug_backtrace[3]['args'][0];
         $taxonomies = explode('_', $option_name);
         $taxonomy = $taxonomies[0];
     }
     $translated_children = array();
     if ($taxonomy && is_array($original_value)) {
         foreach ($original_value as $children_term_ids) {
             foreach ($children_term_ids as $child_term_id) {
                 $translated_child_term_id = icl_object_id($child_term_id, $taxonomy, false, $current_language);
                 if ($translated_child_term_id) {
                     $translated_parent_term_id = wp_get_term_taxonomy_parent_id($translated_child_term_id, $taxonomy);
                     if ($translated_parent_term_id) {
                         if (!isset($translated_children[$translated_parent_term_id])) {
                             $translated_children[$translated_parent_term_id] = array();
                         }
                         $translated_children[$translated_parent_term_id][] = $translated_child_term_id;
                     }
                 }
             }
         }
     }
     wp_cache_set($cache_key, $translated_children, $cache_group);
     return $translated_children;
 }
 /**
  * Adds the hierarchical depth as a variable to all terms.
  * 0 means, that the term has no parent.
  *
  * @param array $tridgroup
  *
  * @return array
  */
 private function add_level_information_to_terms($tridgroup)
 {
     foreach ($tridgroup['elements'] as $lang => &$term) {
         $level = 0;
         $term_id = $term['term_id'];
         while ($term_id = wp_get_term_taxonomy_parent_id($term_id, $this->taxonomy)) {
             $level++;
         }
         $term['level'] = $level;
     }
     return $tridgroup;
 }