/** * Hooks the WP admin_init action to redirect any requests accessing * content which is not in the current language. * * @return void **/ function bbl_admin_init() { global $pagenow; $taxonomy = isset($_GET['taxonomy']) ? sanitize_text_field($_GET['taxonomy']) : false; $post_type = isset($_GET['post_type']) ? sanitize_text_field($_GET['post_type']) : false; // Deal with the special URL case of the listing screens for vanilla posts if (!$post_type && 'edit.php' == $pagenow) { $post_type = 'post'; } $cur_lang_code = bbl_get_current_lang_code(); if ($taxonomy) { $new_taxonomy = bbl_get_taxonomy_in_lang($taxonomy, $cur_lang_code); if ($taxonomy != $new_taxonomy) { $url = add_query_arg(array('taxonomy' => rawurlencode($new_taxonomy))); wp_safe_redirect($url); exit; } } if ($post_type) { $new_post_type = bbl_get_post_type_in_lang($post_type, $cur_lang_code); if ($post_type != $new_post_type) { $url = add_query_arg(array('post_type' => rawurlencode($new_post_type))); wp_safe_redirect($url); exit; } } }
/** * Get the posts which are the translations for the provided * post ID. N.B. The returned array of post objects (and false * values) will include the post for the post ID passed. * * @param int|WP_Post $post Either a WP Post object, or a post ID * @return array Either an array keyed by the site languages, each key containing false (if no translation) or a WP Post object **/ public function get_post_translations($post) { $post = get_post($post); // @FIXME: Is it worth caching here, or can we just rely on the caching in get_objects_in_term and get_posts? $transid = $this->get_transid($post); if ($translations = wp_cache_get($transid, 'bbl_post_translations')) { return $translations; } # @TODO A transid should never be a wp_error. Check and fix. if (is_wp_error($transid)) { error_log("Error getting transid: " . print_r($transid, true)); } $post_ids = get_objects_in_term($transid, 'post_translation'); // Work out all the translated equivalent post types $post_types = array(); $langs = bbl_get_active_langs(); foreach ($langs as $lang) { $post_types[] = bbl_get_post_type_in_lang($post->post_type, $lang->code); } // Get all the translations in one cached DB query $args = array('bbl_translate' => false, 'include' => $post_ids, 'post_type' => $post_types, 'post_status' => array('publish', 'pending', 'draft', 'future')); $posts = get_posts($args); $translations = array(); foreach ($posts as $post) { $translations[$this->get_post_lang_code($post)] = $post; } wp_cache_add($transid, $translations, 'bbl_post_translations'); return $translations; }
/** * Returns the link to a post type in a particular language. * * @param string $post_type A post type for which you want a translated archive link * @param string $lang_code The code for the language the link is requested in * @return void **/ function bbl_get_post_type_archive_link_in_lang($post_type, $lang_code = null) { if (is_null($lang_code)) { $lang_code = bbl_get_current_lang_code(); } bbl_switch_to_lang($lang_code); $lang_post_type = bbl_get_post_type_in_lang($post_type, $lang_code); $link = get_post_type_archive_link($lang_post_type); bbl_restore_lang(); return apply_filters('bbl_post_type_archive_link_in_lang', $link); }
/** * Add an admin list posts screen link to the parent link provided (by reference). * * @param object $lang A Babble language object for this link * @return void **/ protected function add_admin_list_posts_link($lang) { $classes = array(); $args = array('lang' => $lang->code, 'post_type' => bbl_get_post_type_in_lang($this->screen->post_type, $lang->code)); $href = add_query_arg($args); $href = apply_filters('bbl_switch_admin_list_posts_link', $href, $lang); $title = sprintf(__('Switch to %s', 'babble'), $lang->display_name); $classes[] = "bbl-lang-{$lang->code} bbl-lang-{$lang->url_prefix}"; $classes[] = 'bbl-admin'; $classes[] = 'bbl-admin-edit-post'; $classes[] = 'bbl-admin-post-type'; $classes[] = 'bbl-lang'; if ($lang->code == bbl_get_current_lang_code()) { $classes[] = 'bbl-active'; } $this->links[$lang->code] = array('classes' => $classes, 'href' => $href, 'id' => $lang->url_prefix, 'meta' => array('class' => strtolower(join(' ', array_unique($classes)))), 'title' => $title, 'lang' => $lang); }
/** * Will update term count based on object types of the current * taxonomy. Will only count the post(s) in the default language. * * Private function for the default callback for post_tag and category * taxonomies. * * @param array $terms List of Term taxonomy IDs * @param object $taxonomy Current taxonomy object of terms */ function update_post_term_count($terms, $taxonomy) { global $wpdb; $object_types = (array) $taxonomy->object_type; foreach ($object_types as &$object_type) { list($object_type) = explode(':', $object_type); // Babble specific code, to only count in primary language $object_type = bbl_get_post_type_in_lang($object_type, bbl_get_default_lang_code()); } $object_types = array_unique($object_types); if (false !== ($check_attachments = array_search('attachment', $object_types))) { unset($object_types[$check_attachments]); $check_attachments = true; } if ($object_types) { $object_types = esc_sql(array_filter($object_types, 'post_type_exists')); } foreach ((array) $terms as $term) { $count = 0; // Attachments can be 'inherit' status, we need to base count off the parent's status if so if ($check_attachments) { $count += (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->term_relationships}, {$wpdb->posts} p1 WHERE p1.ID = {$wpdb->term_relationships}.object_id AND ( post_status = 'publish' OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM {$wpdb->posts} WHERE ID = p1.post_parent ) = 'publish' ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term)); } if ($object_types) { $count += (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$wpdb->term_relationships}, {$wpdb->posts} WHERE {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id AND post_status = 'publish' AND post_type IN ('" . implode("', '", $object_types) . "') AND term_taxonomy_id = %d", $term)); } do_action('edit_term_taxonomy', $term, $taxonomy); $wpdb->update($wpdb->term_taxonomy, compact('count'), array('term_taxonomy_id' => $term)); do_action('edited_term_taxonomy', $term, $taxonomy); } }
/** * Takes a set of query vars and amends them to show the content * in the current language. * * @TODO This method is getting really hairy and complex, and could do with refactoring * * @param array $query_vars A set of WordPress query vars (sometimes called query arguments) * @param string|boolean $request If this is called on the parse_request hook, $request contains the root relative URL * @return array $query_vars A set of WordPress query vars **/ protected function translate_query_vars(array $query_vars, $request = false) { // Sequester the original query, in case we need it to get the default content later $query_vars['bbl_original_query'] = $query_vars; // We've done this already (avoid re-translating the vars) if (isset($query_vars['bbl_done_translation']) && $query_vars['bbl_done_translation']) { return $query_vars; } $query_vars['bbl_done_translation'] = true; $lang_url_prefix = isset($query_vars['lang_url_prefix']) ? $query_vars['lang_url_prefix'] : get_query_var('lang_url_prefix'); $lang = isset($query_vars['lang']) ? $query_vars['lang'] : get_query_var('lang'); // Detect language specific homepages if ($request == $lang_url_prefix) { unset($query_vars['error']); // @FIXME: Cater for front pages which don't list the posts if (!isset($query_vars['s']) && 'page' == get_option('show_on_front') && ($page_on_front = get_option('page_on_front'))) { // @TODO: Get translated page ID // @FIXME: This is a rather hacky approach to fixing the is_front_page function for translated front pages $this->translated_front_page_id = $this->get_post_in_lang($page_on_front, bbl_get_current_lang_code())->ID; add_filter('pre_option_page_on_front', array($this, 'filter_pre_option_page_on_front')); $query_vars['page_id'] = $this->get_post_in_lang($page_on_front, bbl_get_current_lang_code())->ID; $query_vars['post_type'] = $this->get_post_type_in_lang('page', bbl_get_current_lang_code()); return $query_vars; } // Trigger the archive listing for the relevant shadow post type // of 'post' for this language. if (bbl_get_default_lang_code() != $lang && empty($query_vars['s'])) { $post_type = isset($query_vars['post_type']) ? $query_vars['post_type'] : 'post'; $query_vars['post_type'] = $this->get_post_type_in_lang($post_type, bbl_get_current_lang_code()); } return $query_vars; } // If we're asking for the default content, it's fine if (bbl_get_default_lang_code() == $lang) { return $query_vars; } // Now swap the query vars so we get the content in the right language post_type // @FIXME: Do I need to change $wp->matched query? I think $wp->matched_rule is fine? // @FIXME: Danger of post type slugs clashing?? if (isset($query_vars['pagename']) && $query_vars['pagename']) { // Substitute post_type for $query_vars['name'] = $query_vars['pagename']; $query_vars[bbl_get_post_type_in_lang('page', $query_vars['lang'])] = $query_vars['pagename']; $query_vars['post_type'] = bbl_get_post_type_in_lang('page', bbl_get_current_lang_code()); // Trigger a listing of translated posts if this is meant to // be the blog page. if ('page' == get_option('show_on_front')) { // Test if the current page is in the same translation group as // the 'page_for_posts. $current_post = get_page_by_path($query_vars['pagename'], null, $query_vars['post_type']); if ($this->get_transid(get_option('page_for_posts')) == $this->get_transid($current_post)) { $query_vars['post_type'] = bbl_get_post_type_in_lang('post', bbl_get_current_lang_code()); unset($query_vars['name']); unset($query_vars[bbl_get_post_type_in_lang('page', $query_vars['lang'])]); } } unset($query_vars['page']); unset($query_vars['pagename']); } elseif (isset($query_vars['year']) && $query_vars['year']) { // @FIXME: This is not a reliable way to detect queries for the 'post' post_type. $query_vars['post_type'] = bbl_get_post_type_in_lang('post', bbl_get_current_lang_code()); } elseif (isset($query_vars['post_type'])) { if (is_array($query_vars['post_type'])) { $new_post_types = array(); foreach ($query_vars['post_type'] as $post_type) { $new_post_types[] = bbl_get_post_type_in_lang($post_type, bbl_get_current_lang_code()); } $query_vars['post_type'] = $new_post_types; } else { $query_vars['post_type'] = bbl_get_post_type_in_lang($query_vars['post_type'], bbl_get_current_lang_code()); } } else { $query_vars['post_type'] = bbl_get_post_type_in_lang('post', bbl_get_current_lang_code()); } return $query_vars; }