'tags',
				'singular' => 'tag',
				'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
		$action    = $this->screen->action;
		$post_type = $this->screen->post_type;
		$taxonomy  = $this->screen->taxonomy;
		if ( empty( $taxonomy ) ) {
			$taxonomy = 'post_tag';
		}
		if ( ! taxonomy_exists( $taxonomy ) ) {
			wp_die( __( 'Invalid taxonomy.' ) );
		}
		$tax = get_taxonomy( $taxonomy );
		// @todo Still needed? Maybe just the show_ui part.
		if ( empty( $post_type ) || ! in_array( $post_type, get_post_types( array( 'show_ui' => true ) ) ) ) {
			$post_type = 'post';
		}
	}
	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->manage_terms );
	}
	/**
	 */
	public function prepare_items() {
		$tags_per_page = $this->get_items_per_page( 'edit_' . $this->screen->taxonomy . '_per_page' );
		if ( 'post_tag' === $this->screen->taxonomy ) {
			/**
			 * Filters the number of terms displayed per page for the Tags list table.
			 *
			 * @since 2.8.0
			 *
			 * @param int $tags_per_page Number of tags to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters( 'edit_tags_per_page', $tags_per_page );
			/**
			 * Filters the number of terms displayed per page for the Tags list table.
			 *
			 * @since 2.7.0
			 * @deprecated 2.8.0 Use edit_tags_per_page instead.
			 *
			 * @param int $tags_per_page Number of tags to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters( 'tagsperpage', $tags_per_page );
		} elseif ( 'category' === $this->screen->taxonomy ) {
			/**
			 * Filters the number of terms displayed per page for the Categories list table.
			 *
			 * @since 2.8.0
			 *
			 * @param int $tags_per_page Number of categories to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters( 'edit_categories_per_page', $tags_per_page );
		}
		$search = ! empty( $_REQUEST['s'] ) ? trim( wp_unslash( $_REQUEST['s'] ) ) : '';
		$args = array(
			'search' => $search,
			'page'   => $this->get_pagenum(),
			'number' => $tags_per_page,
		);
		if ( ! empty( $_REQUEST['orderby'] ) ) {
			$args['orderby'] = trim( wp_unslash( $_REQUEST['orderby'] ) );
		}
		if ( ! empty( $_REQUEST['order'] ) ) {
			$args['order'] = trim( wp_unslash( $_REQUEST['order'] ) );
		}
		$this->callback_args = $args;
		$this->set_pagination_args(
			array(
				'total_items' => wp_count_terms( $this->screen->taxonomy, compact( 'search' ) ),
				'per_page'    => $tags_per_page,
			)
		);
	}
	/**
	 * @return bool
	 */
	public function has_items() {
		// todo: populate $this->items in prepare_items()
		return true;
	}
	/**
	 */
	public function no_items() {
		echo get_taxonomy( $this->screen->taxonomy )->labels->not_found;
	}
	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions = array();
		if ( current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->delete_terms ) ) {
			$actions['delete'] = __( 'Delete' );
		}
		return $actions;
	}
	/**
	 * @return string
	 */
	public function current_action() {
		if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['delete_tags'] ) && ( 'delete' === $_REQUEST['action'] || 'delete' === $_REQUEST['action2'] ) ) {
			return 'bulk-delete';
		}
		return parent::current_action();
	}
	/**
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			'cb'          => '',
			'name'        => _x( 'Name', 'term name' ),
			'description' => __( 'Description' ),
			'slug'        => __( 'Slug' ),
		);
		if ( 'link_category' === $this->screen->taxonomy ) {
			$columns['links'] = __( 'Links' );
		} else {
			$columns['posts'] = _x( 'Count', 'Number/count of items' );
		}
		return $columns;
	}
	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'name'        => 'name',
			'description' => 'description',
			'slug'        => 'slug',
			'posts'       => 'count',
			'links'       => 'count',
		);
	}
	/**
	 */
	public function display_rows_or_placeholder() {
		$taxonomy = $this->screen->taxonomy;
		$args = wp_parse_args(
			$this->callback_args,
			array(
				'page'       => 1,
				'number'     => 20,
				'search'     => '',
				'hide_empty' => 0,
			)
		);
		$page = $args['page'];
		// Set variable because $args['number'] can be subsequently overridden.
		$number = $args['number'];
		$args['offset'] = $offset = ( $page - 1 ) * $number;
		// Convert it to table rows.
		$count = 0;
		if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) {
			// We'll need the full set of terms then.
			$args['number'] = $args['offset'] = 0;
		}
		$terms = get_terms( $taxonomy, $args );
		if ( empty( $terms ) || ! is_array( $terms ) ) {
			echo '
| ';
			$this->no_items();
			echo ' | 
';
			return;
		}
		if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) {
			if ( ! empty( $args['search'] ) ) {// Ignore children on searches.
				$children = array();
			} else {
				$children = _get_term_hierarchy( $taxonomy );
			}
			// Some funky recursion to get the job done( Paging & parents mainly ) is contained within, Skip it for non-hierarchical taxonomies for performance sake
			$this->_rows( $taxonomy, $terms, $children, $offset, $number, $count );
		} else {
			foreach ( $terms as $term ) {
				$this->single_row( $term );
			}
		}
	}
	/**
	 * @param string $taxonomy
	 * @param array $terms
	 * @param array $children
	 * @param int   $start
	 * @param int   $per_page
	 * @param int   $count
	 * @param int   $parent
	 * @param int   $level
	 */
	private function _rows( $taxonomy, $terms, &$children, $start, $per_page, &$count, $parent = 0, $level = 0 ) {
		$end = $start + $per_page;
		foreach ( $terms as $key => $term ) {
			if ( $count >= $end ) {
				break;
			}
			if ( $term->parent != $parent && empty( $_REQUEST['s'] ) ) {
				continue;
			}
			// If the page starts in a subtree, print the parents.
			if ( $count == $start && $term->parent > 0 && empty( $_REQUEST['s'] ) ) {
				$my_parents = $parent_ids = array();
				$p          = $term->parent;
				while ( $p ) {
					$my_parent    = get_term( $p, $taxonomy );
					$my_parents[] = $my_parent;
					$p            = $my_parent->parent;
					if ( in_array( $p, $parent_ids ) ) { // Prevent parent loops.
						break;
					}
					$parent_ids[] = $p;
				}
				unset( $parent_ids );
				$num_parents = count( $my_parents );
				while ( $my_parent = array_pop( $my_parents ) ) {
					echo "\t";
					$this->single_row( $my_parent, $level - $num_parents );
					$num_parents--;
				}
			}
			if ( $count >= $start ) {
				echo "\t";
				$this->single_row( $term, $level );
			}
			++$count;
			unset( $terms[ $key ] );
			if ( isset( $children[ $term->term_id ] ) && empty( $_REQUEST['s'] ) ) {
				$this->_rows( $taxonomy, $terms, $children, $start, $per_page, $count, $term->term_id, $level + 1 );
			}
		}
	}
	/**
	 * @global string $taxonomy
	 * @param WP_Term $tag Term object.
	 * @param int $level
	 */
	public function single_row( $tag, $level = 0 ) {
		global $taxonomy;
		$tag = sanitize_term( $tag, $taxonomy );
		$this->level = $level;
		if ( $tag->parent ) {
			$count = count( get_ancestors( $tag->term_id, $taxonomy, 'taxonomy' ) );
			$level = 'level-' . $count;
		} else {
			$level = 'level-0';
		}
		echo '';
		$this->single_row_columns( $tag );
		echo '
';
	}
	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_cb( $tag ) {
		if ( current_user_can( 'delete_term', $tag->term_id ) ) {
			return ''
				. '';
		}
		return ' ';
	}
	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_name( $tag ) {
		$taxonomy = $this->screen->taxonomy;
		$pad = str_repeat( '— ', max( 0, $this->level ) );
		/**
		 * Filters display of the term name in the terms list table.
		 *
		 * The default output may include padding due to the term's
		 * current level in the term hierarchy.
		 *
		 * @since 2.5.0
		 *
		 * @see WP_Terms_List_Table::column_name()
		 *
		 * @param string $pad_tag_name The term name, padded if not top-level.
		 * @param WP_Term $tag         Term object.
		 */
		$name = apply_filters( 'term_name', $pad . ' ' . $tag->name, $tag );
		$qe_data = get_term( $tag->term_id, $taxonomy, OBJECT, 'edit' );
		$uri = wp_doing_ajax() ? wp_get_referer() : $_SERVER['REQUEST_URI'];
		$edit_link = get_edit_term_link( $tag->term_id, $taxonomy, $this->screen->post_type );
		if ( $edit_link ) {
			$edit_link = add_query_arg(
				'wp_http_referer',
				urlencode( wp_unslash( $uri ) ),
				$edit_link
			);
			$name      = sprintf(
				'%s',
				esc_url( $edit_link ),
				/* translators: %s: taxonomy term name */
				esc_attr( sprintf( __( '“%s” (Edit)' ), $tag->name ) ),
				$name
			);
		}
		$out = sprintf(
			'%s
',
			$name
		);
		$out .= '';
		$out .= '
' . $qe_data->name . '
';
		/** This filter is documented in wp-admin/edit-tag-form.php */
		$out .= '
' . apply_filters( 'editable_slug', $qe_data->slug, $qe_data ) . '
';
		$out .= '
' . $qe_data->parent . '