array( 'title' => __('Taxonomies', 'tag-groups'), 'slug' => 'tag-groups-settings', 'parent' => 'tag-groups-settings', 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Settings', 'settings_page_home' ), ), 3 => array( 'title' => __('Front End', 'tag-groups'), 'slug' => 'tag-groups-settings-front-end', 'parent' => 'tag-groups-settings', 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Settings', 'settings_page_front_end' ), ), 4 => array( 'title' => __('Back End', 'tag-groups'), 'slug' => 'tag-groups-settings-back-end', 'parent' => 'tag-groups-settings', 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Settings', 'settings_page_back_end' ), ), 9 => array( 'title' => __('First Steps', 'tag-groups'), 'slug' => 'tag-groups-settings-first-steps', 'parent' => null, 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Setup_Wizard', 'settings_page_onboarding' ), ), 10 => array( 'title' => __('Setup Wizard', 'tag-groups'), 'slug' => 'tag-groups-settings-setup-wizard', 'parent' => null, 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Setup_Wizard', 'settings_page_setup_wizard' ), ), 11 => array( 'title' => __('Settings', 'tag-groups'), 'slug' => 'tag-groups-settings-general', 'parent' => 'tag-groups-settings', 'user_can' => 'manage_options', 'function' => array( 'TagGroups_Settings', 'settings_page_general' ), ), ); // hook for premium plugin to modify the menu $tag_groups_admin_structure = apply_filters('tag_groups_admin_structure', $tag_groups_admin_structure); // make sure they all have the right order ksort($tag_groups_admin_structure); // register the menus and pages foreach ($tag_groups_admin_structure as $tag_groups_admin_page) { add_submenu_page(!empty($tag_groups_admin_page['parent']) ? $tag_groups_admin_page['parent'] : '', $tag_groups_admin_page['title'], $tag_groups_admin_page['title'], $tag_groups_admin_page['user_can'], $tag_groups_admin_page['slug'], $tag_groups_admin_page['function']); } // for each registered taxonomy a tag group admin page $tag_group_taxonomies = TagGroups_Options::get_option('tag_group_taxonomy', array( 'post_tag' )); $tag_group_role_edit_groups = 'edit_pages'; if (TagGroups_Utilities::is_premium_plan()) { $tag_group_role_edit_groups = TagGroups_Options::get_option('tag_group_role_edit_groups', 'edit_pages'); } $tag_group_post_types = TagGroups_Taxonomy::post_types_from_taxonomies($tag_group_taxonomies); foreach ($tag_group_post_types as $post_type) { if ('post' == $post_type) { $post_type_query = ''; } else { $post_type_query = '?post_type=' . $post_type; } $submenu_page = add_submenu_page('edit.php' . $post_type_query, __('Tag Group Admin', 'tag-groups'), __('Tag Group Admin', 'tag-groups'), $tag_group_role_edit_groups, 'tag-groups_' . $post_type, array( 'TagGroups_Group_Admin', 'render_group_administration' )); if ( TagGroups_Utilities::is_premium_plan() && class_exists('TagGroups_Premium_Admin') && method_exists('TagGroups_Premium_Admin', 'add_screen_option') ) { add_action("load-$submenu_page", array( 'TagGroups_Premium_Admin', 'add_screen_option' )); } } } /** * Remove one of the Freemius submenus * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function remove_submenus() { if (TagGroups_Utilities::is_free_plan()) { remove_submenu_page('tag-groups-settings', 'tag-groups-settings-contact'); } else { remove_submenu_page('tag-groups-settings', 'tag-groups-settings-wp-support-forum'); } } /** * Create the html to add tags to tag groups on single tag view (after clicking tag for editing) * * @param type $tag */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function render_edit_tag_menu($tag) { global $tag_group_groups ; $screen = get_current_screen(); if ('post' == $screen->post_type) { $url_post_type = ''; } else { $url_post_type = '&post_type=' . $screen->post_type; } $tag_group_admin_url = admin_url('edit.php?page=tag-groups_' . $screen->post_type . $url_post_type); $term_groups = $tag_group_groups->get_all_with_position_as_key(); unset($term_groups[0]); $tg_term = new TagGroups_Term($tag); $view = new TagGroups_View('admin/edit_tag_main'); if (TagGroups_Utilities::is_premium_plan() && class_exists('TagGroups_Premium_View')) { $view = new TagGroups_Premium_View('admin/edit_tag_main'); } $view->set(array( 'term_groups' => $term_groups, 'screen' => $screen, 'tg_term' => $tg_term, 'tag_group_admin_url' => $tag_group_admin_url, )); $view->render(); } /** * Create the html to assign tags to tag groups upon new tag creation (left of the table) * * @param type $tag */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function render_new_tag_menu($tag) { global $tag_group_groups ; $screen = get_current_screen(); $term_groups = $tag_group_groups->get_all_with_position_as_key(); unset($term_groups[0]); $new_tag_initial_groups = array(); if (TagGroups_Utilities::is_premium_plan()) { $new_tag_initial_groups = TagGroups_Options::get_option('tag_group_new_tag_default_groups', array()); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for WPML translation context if (empty($new_tag_initial_groups) && TagGroups_WPML::is_multilingual() && isset($_GET['trid']) && !empty($_GET['taxonomy'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for WPML translation context $trid = (int) $_GET['trid']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for WPML translation context $taxonomy = sanitize_title(wp_unslash($_GET['taxonomy'])); $translations = apply_filters('wpml_get_element_translations', null, $trid, "tax_{$taxonomy}"); $default_lang = apply_filters('wpml_default_language', null); if (!empty($default_lang) && is_array($translations) && isset($translations[$default_lang])) { $original_translation = $translations[$default_lang]; } else { $original_translation = TagGroups_Utilities::get_first_element($translations); } if (!empty($original_translation)) { $tg_original_term = new TagGroups_Term($original_translation->element_id); $new_tag_initial_groups = $tg_original_term->get_groups(); } } $view = new TagGroups_View('admin/new_tag_from_list'); if (TagGroups_Utilities::is_premium_plan() && class_exists('TagGroups_Premium_View')) { $view = new TagGroups_Premium_View('admin/new_tag_from_list'); } $view->set(array( 'term_groups' => $term_groups, 'screen' => $screen, 'new_tag_initial_groups' => $new_tag_initial_groups, )); $view->render(); } /** * adds a custom column to the table of tags/terms * thanks to http://coderrr.com/add-columns-to-a-taxonomy-terms-table/ * * @global object $wp * @param array $columns * @return string */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_taxonomy_columns($columns) { global $wp ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for column sorting $new_order = (isset($_GET['order']) && 'asc' == $_GET['order'] && isset($_GET['orderby']) && 'term_group' == $_GET['orderby'] ? 'desc' : 'asc'); $screen = get_current_screen(); if (!empty($screen)) { $taxonomy = $screen->taxonomy; $link = add_query_arg( array( 'orderby' => 'term_group', 'order' => $new_order, 'taxonomy' => $taxonomy, ), admin_url("edit-tags.php" . $wp->request) ); $link_escaped = esc_url($link); $columns['term_group'] = '' . __('Tag Groups', 'tag-groups') . ''; } else { $columns['term_group'] = ''; } return $columns; } /** * adds data into custom column of the table for each row * thanks to http://coderrr.com/add-columns-to-a-taxonomy-terms-table/ * * @param type $a * @param type $b * @param type $term_id * @return string */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_taxonomy_column_content($content = '', $column_name = '', $term_id = 0) { global $tag_group_groups ; if ('term_group' != $column_name) { return $content; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for taxonomy display if (!empty($_REQUEST['taxonomy'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for taxonomy display $taxonomy = sanitize_title(wp_unslash($_REQUEST['taxonomy'])); } else { return ''; } $term = get_term($term_id, $taxonomy); if (isset($term)) { $term_o = new TagGroups_Term($term); return implode(', ', $tag_group_groups->get_labels_by_position($term_o->get_groups())); } else { return ''; } } /** * Modify the term query so that we can sort by the term meta * * @param [type] $pieces * @param [type] $taxonomies * @param [type] $args * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function sort_taxonomy_columns($pieces, $taxonomies, $args) { global $wpdb ; $screen = get_current_screen(); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (empty($screen) || !in_array($screen->taxonomy, $enabled_taxonomies)) { return $pieces; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only operation for column sorting if (empty($_GET['orderby']) || 'term_group' != $_GET['orderby']) { return $pieces; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only operation for column sorting if (isset($_GET['order']) && strtoupper(sanitize_key(wp_unslash($_GET['order']))) == 'DESC') { $order = "DESC"; } else { $order = 'ASC'; } $pieces['join'] .= ' INNER JOIN ' . $wpdb->termmeta . ' AS tm ON t.term_id = tm.term_id '; $pieces['where'] .= ' AND tm.meta_key = "_cm_term_group_array"'; $pieces['orderby'] = ' ORDER BY tm.meta_value '; $pieces['order'] = $order; return $pieces; } /** * processing actions defined in bulk_admin_footer() * credits http://www.foxrunsoftware.net * * @global int $tg_update_edit_term_group_called * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function do_bulk_action() { global $tg_update_edit_term_group_called ; $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); $screen = get_current_screen(); $taxonomy = $screen->taxonomy; if (is_object($screen) && !in_array($taxonomy, $enabled_taxonomies)) { return; } $show_filter_tags = TagGroups_Options::get_option('tag_group_show_filter_tags', 0); if ($show_filter_tags) { $tag_group_tags_filter = TagGroups_Options::get_option('tag_group_tags_filter', array()); /** * Processing the filter * Values come as POST (via menu, precedence) or GET (via link from group admin) */ // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Filter operation if (isset($_POST['term-filter'])) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Filter operation $term_filter = (int) $_POST['term-filter']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter operation } elseif (isset($_GET['term-filter'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter operation $term_filter = (int) $_GET['term-filter']; // We need to remove the term-filter piece, or it will stay forever // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- URL manipulation $sendback = remove_query_arg(array( 'term-filter' ), wp_unslash($_SERVER['REQUEST_URI'])); } if (isset($term_filter)) { if ('-1' == $term_filter) { unset($tag_group_tags_filter[$taxonomy]); TagGroups_Options::update_option('tag_group_tags_filter', $tag_group_tags_filter); } else { $tag_group_tags_filter[$taxonomy] = $term_filter; TagGroups_Options::update_option('tag_group_tags_filter', $tag_group_tags_filter); /* * Modify the query */ add_action('terms_clauses', array( 'TagGroups_Admin', 'modify_terms_query' ), 10, 3); } if (isset($sendback)) { // remove filter that destroys WPML's "&lang=" remove_all_filters('wp_redirect'); // escaping $sendback wp_redirect(esc_url_raw($sendback)); exit; } } else { /** * If filter is set, make sure to modify the query */ if (isset($tag_group_tags_filter[$taxonomy])) { add_action('terms_clauses', array( 'TagGroups_Admin', 'modify_terms_query' ), 10, 3); } } } $wp_list_table = _get_list_table('WP_Terms_List_Table'); $action = $wp_list_table->current_action(); $allowed_actions = array( 'assign' ); if (!in_array($action, $allowed_actions)) { return; } check_admin_referer('bulk-tags'); if (isset($_REQUEST['delete_tags'])) { $term_ids = array_map('intval', (array) wp_unslash($_REQUEST['delete_tags'])); } if (isset($_REQUEST['term-group-top'])) { $term_group = (int) sanitize_text_field(wp_unslash($_REQUEST['term-group-top'])); } else { return; } $sendback = remove_query_arg(array( 'assigned', 'deleted' ), wp_get_referer()); if (!$sendback) { $sendback = admin_url('edit-tags.php?taxonomy=' . $taxonomy); } if (empty($term_ids)) { $sendback = add_query_arg( array( 'number_assigned' => 0, 'group_id' => $term_group, ), $sendback ); $sendback = remove_query_arg( array( 'action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view' ), $sendback ); // escaping $sendback wp_redirect(esc_url_raw($sendback)); exit; } $pagenum = $wp_list_table->get_pagenum(); $sendback = add_query_arg('paged', $pagenum, $sendback); $tg_update_edit_term_group_called = true; /** * skip update_edit_term_group() */ switch ($action) { case 'assign': $assigned = 0; foreach ($term_ids as $term_id) { $term = new TagGroups_Term($term_id); if (false !== $term) { if (0 == $term_group) { if ($term->get_groups() != array( 0 )) { $term->remove_all_groups()->save(); } } else { if (!in_array($term_group, $term->get_groups())) { $term->add_group($term_group)->save(); } } $assigned++; } } if (0 == $term_group) { $message = _n('The term has been removed from all groups.', sprintf('%d terms have been removed from all groups.', number_format_i18n((int) $assigned)), (int) $assigned, 'tag-groups'); } else { $tg_group = new TagGroups_Group($term_group); $message = _n(sprintf('The term has been assigned to the group %s.', '' . $tg_group->get_label() . ''), sprintf('%d terms have been assigned to the group %s.', number_format_i18n((int) $assigned), '' . $tg_group->get_label() . ''), (int) $assigned, 'tag-groups'); } break; default: // Need to show a message? exit; break; } TagGroups_Admin_Notice::add('success', $message); $sendback = remove_query_arg( array( 'action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view' ), $sendback ); wp_redirect(esc_url_raw($sendback)); exit; } /** * Filter the tags on the tag page * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function do_filter_tags() { $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); $screen = get_current_screen(); $taxonomy = $screen->taxonomy; if (is_object($screen) && !in_array($taxonomy, $enabled_taxonomies)) { return; } $show_filter_tags = TagGroups_Options::get_option('tag_group_show_filter_tags', 0); if (!$show_filter_tags) { return; } $tag_group_tags_filter = TagGroups_Options::get_option('tag_group_tags_filter', array()); /** * Processing the filter * Values come as POST (via menu, precedence) or GET (via link from group admin) */ // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Filter operation if (isset($_POST['term-filter'])) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Filter operation $term_filter = (int) $_POST['term-filter']; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter operation } elseif (isset($_GET['term-filter'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter operation $term_filter = (int) $_GET['term-filter']; } if (isset($term_filter)) { if ('-1' == $term_filter) { unset($tag_group_tags_filter[$taxonomy]); TagGroups_Options::update_option('tag_group_tags_filter', $tag_group_tags_filter); } else { $tag_group_tags_filter[$taxonomy] = $term_filter; TagGroups_Options::update_option('tag_group_tags_filter', $tag_group_tags_filter); /* * Modify the query */ add_action('terms_clauses', array( 'TagGroups_Admin', 'modify_terms_query' ), 10, 3); } if (isset($sendback)) { /** * We need to remove the term-filter piece, or it will stay forever * * Also return to first page, trying to solve error "A variable mismatch has been detected." */ $sendback = remove_query_arg(array( 'term-filter', 'paged' )); /** * let WP use $_SERVER['REQUEST_URI'] and apply whitelisting etc. if desired * * remove filter that destroys WPML's "&lang=" */ remove_all_filters('wp_redirect'); // escaping $sendback wp_redirect(esc_url_raw($sendback)); exit; } } else { /** * If filter is set, make sure to modify the query */ if (isset($tag_group_tags_filter[$taxonomy])) { add_action('terms_clauses', array( 'TagGroups_Admin', 'modify_terms_query' ), 10, 3); } } } /** * modifies Quick Edit link to call JS when clicked * thanks to http://shibashake.com/WordPress-theme/expand-the-WordPress-quick-edit-menu * * @param array $actions * @param object $tag * @return array */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function expand_quick_edit_link($actions, $tag) { $screen = get_current_screen(); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (is_object($screen) && !in_array($screen->taxonomy, $enabled_taxonomies)) { return $actions; } $term_o = new TagGroups_Term($tag); $groups = htmlspecialchars(wp_json_encode($term_o->get_groups())); $nonce = wp_create_nonce('tag-groups-nonce'); $actions['inline hide-if-no-js'] = '"; $actions['inline hide-if-no-js'] .= __('Quick Edit', 'tag-groups'); $actions['inline hide-if-no-js'] .= ''; return $actions; } /** * adds JS function that sets the saved tag group for a given element when it's opened in quick edit * thanks to http://shibashake.com/WordPress-theme/expand-the-WordPress-quick-edit-menu * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function render_quick_edit_javascript() { $screen = get_current_screen(); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (!in_array($screen->taxonomy, $enabled_taxonomies)) { return; } $view = new TagGroups_View('partials/quick_edit_javascript'); if (TagGroups_Utilities::is_premium_plan() && class_exists('TagGroups_Premium_View')) { $view = new TagGroups_Premium_View('partials/quick_edit_javascript'); } $view->render(); } /** * Create the html to assign tags to tag groups directly in tag table ('quick edit') * * @return type */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function quick_edit_tag() { global $tg_quick_edit_tag_called, $tag_group_groups ; if ($tg_quick_edit_tag_called) { return; } $tg_quick_edit_tag_called = true; $screen = get_current_screen(); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (!in_array($screen->taxonomy, $enabled_taxonomies)) { return; } $term_groups = $tag_group_groups->get_all_with_position_as_key(); unset($term_groups[0]); $view = new TagGroups_View('partials/quick_edit_tag'); if (TagGroups_Utilities::is_premium_plan() && class_exists('TagGroups_Premium_View')) { $view = new TagGroups_Premium_View('partials/quick_edit_tag'); } $view->set(array( 'term_groups' => $term_groups, 'screen' => $screen, )); $view->render(); } /** * Adds a bulk action menu to a term list page * credits http://www.foxrunsoftware.net * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function bulk_admin_footer() { global $tag_group_groups ; $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); $screen = get_current_screen(); if (is_object($screen) && !in_array($screen->taxonomy, $enabled_taxonomies)) { return; } $term_groups = $tag_group_groups->get_all_with_position_as_key(); $view = new TagGroups_View('partials/bulk_admin_footer'); $view->set(array( 'term_groups' => $term_groups, )); $view->render(); } /** * Adds a filter menu to a term list page * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function filter_admin_footer() { global $tag_group_groups ; $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); $screen = get_current_screen(); if (is_object($screen) && !in_array($screen->taxonomy, $enabled_taxonomies)) { return; } if (!TagGroups_Options::get_option('tag_group_show_filter_tags', 0)) { return; } $term_groups = $tag_group_groups->get_all_with_position_as_key(true); $tag_group_tags_filter = TagGroups_Options::get_option('tag_group_tags_filter', array()); if (isset($tag_group_tags_filter[$screen->taxonomy])) { $tag_filter = $tag_group_tags_filter[$screen->taxonomy]; if ($tag_filter > 0) { // check if group exists (could be deleted since last time the filter was set) $tg_group = new TagGroups_Group($tag_filter); if (!$tg_group->exists()) { $tag_filter = -1; } } } else { $tag_filter = -1; } $view = new TagGroups_View('partials/filter_admin_footer'); $view->set(array( 'parents' => $tag_group_groups->get_parents(), 'term_groups' => $term_groups, 'tag_filter' => $tag_filter, )); $view->render(); } /** * Adds a button to reset the filter on the tags page, in case JavaScript breaks * * @since 1.25.0 * * @param void * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_admin_footer_text($text) { $screen = get_current_screen(); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (!empty($screen) && 'edit-tags' == $screen->base && TagGroups_Options::get_option('tag_group_show_filter_tags', 0) && in_array($screen->taxonomy, $enabled_taxonomies)) { $view = new TagGroups_View('partials/admin_footer'); $view->set('reset_url', esc_url(add_query_arg('term-filter', -1))); return $view->return_html() . $text; } return $text; } /** * Adds a button to reset the filter on the tags page, in case JavaScript breaks * * @since 1.25.0 * * @param string $text * @return string */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_admin_footer_rating_text($text) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only check for admin page if (empty($_GET['page']) || strpos(sanitize_key(wp_unslash($_GET['page'])), 'tag-groups') !== 0) { return $text; } $view = new TagGroups_View('partials/admin_footer_rating'); $text = $view->return_html() . $text; return $text; } /** * Adds JS to the footer for nicer tooltips in the backend * * @since 1.43.5 * * @param string $text * @return string */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_admin_footer_tooltip_script($text) { $screen = get_current_screen(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Read-only check for admin page if (empty($_GET['page']) || strpos(sanitize_key(wp_unslash($_GET['page'])), 'tag-groups') !== 0) { /* Tooltip doesn't work well in Gutenberg sidebar */ // phpcs:ignore Squiz.PHP.CommentedOutCode.Found // if ( ( empty( $_GET['page'] ) || strpos( $_GET['page'], 'tag-groups' ) !== 0 ) && // ( ! is_object( $screen ) || ! property_exists( $screen, 'base' ) || 'post' != $screen->base ) ) { return $text; } $view = new TagGroups_View('partials/admin_footer_tooltip'); return $text . $view->return_html(); } /** * Adds a pull-down menu to the filters above the posts. * Based on the code by Ohad Raz, http://wordpress.stackexchange.com/q/45436/2487 * License: Creative Commons Share Alike * * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_post_filter() { global $tag_group_groups ; if (!TagGroups_Options::get_option('tag_group_show_filter', 1)) { return; } $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter display $post_type = (isset($_GET['post_type']) ? sanitize_title(wp_unslash($_GET['post_type'])) : 'post'); if (count(array_intersect($enabled_taxonomies, get_object_taxonomies($post_type)))) { $term_groups = $tag_group_groups->get_all_term_group_label(); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter display $current_term_group = (isset($_GET['tg_filter_posts_value']) ? sanitize_text_field(wp_unslash($_GET['tg_filter_posts_value'])) : ''); $view = new TagGroups_View('admin/post_filter'); $view->set(array( 'current_term_group' => $current_term_group, 'parents' => $tag_group_groups->get_parents(), 'term_groups' => $term_groups, )); $view->render(); } } /** * Applies the filter, if used. * Based on the code by Ohad Raz, http://wordpress.stackexchange.com/q/45436/2487 * License: Creative Commons Share Alike * * @global type $pagenow * @param type $query * @return type */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function apply_post_filter($query) { global $pagenow, $tag_group_groups ; if ('edit.php' != $pagenow) { return $query; } $show_filter_posts = TagGroups_Options::get_option('tag_group_show_filter', 0); if (!$show_filter_posts) { return $query; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter application if (isset($_GET['post_type'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter application $post_type = sanitize_title(wp_unslash($_GET['post_type'])); } else { $post_type = 'post'; } /** * Losing here the filter by language from Polylang, but currently no other way to show any posts when combining tax_query and meta_query */ unset($query->query_vars['tax_query']); $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); // note: removed restriction count( $tg_taxonomy ) <= 1 - rather let user figure out if the result works $taxonomy_intersect = array_intersect($enabled_taxonomies, get_object_taxonomies($post_type)); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter application if (count($taxonomy_intersect) && isset($_GET['tg_filter_posts_value']) && '' !== $_GET['tg_filter_posts_value']) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only filter application $group_id = (int) $_GET['tg_filter_posts_value']; if (TagGroups_Utilities::is_premium_plan()) { $group_ids = $tag_group_groups->expand_parents(array( $group_id )); if (count($group_ids) == 0) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Intentional meta_query for post filtering by tag groups $query->query_vars['meta_query'] = array( array( 'key' => '_cm_post_terms_dummy', 'compare' => 'EXISTS', ), ); } elseif (count($group_ids) == 1) { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Intentional meta_query for post filtering by tag groups $query->query_vars['meta_query'] = array( array( 'key' => '_cm_post_terms_' . $group_ids[0], 'compare' => 'EXISTS', ), ); } else { // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Intentional meta_query for post filtering by tag groups $query->query_vars['meta_query'] = array( 'relation' => 'OR', ); foreach ($group_ids as $group_id) { $query->query_vars['meta_query'][] = array( 'key' => '_cm_post_terms_' . $group_id, 'compare' => 'EXISTS', ); } } return $query; } $tg_group = new TagGroups_Group($group_id); $tags = $tg_group->get_group_terms($taxonomy_intersect, true, 'ids'); if (empty($tags)) { /** * We use a workaround to render an empty list */ $query->query_vars['tag__in'] = array( 0 ); } else { $query->query_vars['tag__in'] = $tags; } } return $query; } /** * AJAX handler to get a feed */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function ajax_get_feed() { if (!current_user_can('manage_options')) { wp_die(-1, 403); } check_ajax_referer('tg_get_feed_nonce', 'nonce'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- AJAX handler if (isset($_REQUEST['url'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- AJAX handler $url = esc_url_raw(wp_unslash($_REQUEST['url'])); } else { $url = ''; } if (strpos($url, 'https://chattymango.com/') !== 0) { TagGroups_Error::log('[Tag Groups] Wrong feed URL: ' . $url); TagGroups_Utilities::die(); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- AJAX handler if (isset($_REQUEST['amount'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- AJAX handler $amount = (int) $_REQUEST['amount']; } else { $amount = 5; } $amount = max(1, min(20, $amount)); /** * Assuming that the posts URL is the $url minus the trailing /feed */ $posts_url = preg_replace('/(.+)feed\\/?/i', '$1', $url); $rss = new TagGroups_Feed(); if (defined('WP_DEBUG')) { $rss->set_debug(WP_DEBUG); } $rss->set_url($url)->set_posts_url($posts_url)->set_amount($amount); wp_send_json($rss->get_html()); } /** * Modifies the query to retrieve tags for filtering in the backend. * * @param array $pieces * @param array $taxonomies * @param array $args * @return array */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function modify_terms_query($pieces, $taxonomies, $args) { $taxonomy = TagGroups_Utilities::get_first_element($taxonomies); if (empty($taxonomy) || is_array($taxonomy)) { $taxonomy = 'post_tag'; } $show_filter_tags = TagGroups_Options::get_option('tag_group_show_filter_tags', 0); if (!$show_filter_tags) { return $pieces; } $tag_group_tags_filter = TagGroups_Options::get_option('tag_group_tags_filter', array()); if (isset($tag_group_tags_filter[$taxonomy])) { $group_id = $tag_group_tags_filter[$taxonomy]; if ($group_id > 0) { // check if group exists (could be deleted since last time the filter was set) $tg_group = new TagGroups_Group($group_id); if (!$tg_group->exists()) { $group_id = -1; } } } else { $group_id = -1; } if ($group_id > -1) { $tg_group = new TagGroups_Group($group_id); $mq_sql = $tg_group->terms_clauses(); if (!empty($pieces['join'])) { $pieces['join'] .= $mq_sql['join']; } else { $pieces['join'] = $mq_sql['join']; } if (!empty($pieces['where'])) { $pieces['where'] .= $mq_sql['where']; } else { $pieces['where'] = $mq_sql['where']; } } return $pieces; } /** * Adds Settings link to plugin list * * @param array $links * @return array */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_plugin_settings_link($links) { $settings_link = '' . __('Settings', 'tag-groups') . ''; array_unshift($links, $settings_link); return $links; } /** * Add a warning if the WPML/Polylang language switch is set to "all" * * @param void * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_language_notice() { $screen = get_current_screen(); if (!$screen || 'edit-tags' !== $screen->base && 'term' !== $screen->base) { return; } $enabled_taxonomies = TagGroups_Taxonomy::get_enabled_taxonomies(); if (!in_array($screen->taxonomy, $enabled_taxonomies)) { return; } if ('all' == TagGroups_WPML::get_current_language()) { $view = new TagGroups_View('partials/language_notice'); $view->render(); } } /** * Add inline styling to the tags page * * @param void * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function add_tag_page_styling() { $view = new TagGroups_View('partials/tag_page_inline_style'); $view->render(); } /** * Recommend to run the migration * * @since 1.24.0 * * @param void * @return void */ // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- Legacy method naming public static function recommend_to_run_migration() { /* translators: %s is the href attribute with URL */ TagGroups_Admin_Notice::add('info', sprintf(__('Please click here to run the migration routines to make sure we have migrated all tags.', 'tag-groups'), 'href="' . admin_url('admin.php?page=tag-groups-settings-general&process-tasks=migratetermmeta&task-set-name=Migration') . '"')); } } // class }