<?php

namespace RemoveUnusedMedia\Table;

use RUM_List_Table;
use RemoveUnusedMedia\Util;

use function get_posts;
use function RemoveUnusedMedia\rum_fs;
use function RemoveUnusedMedia\Util\human_filesize;

require_once 'rum_list_table.php';
require_once 'rum_util.php';

final class How
{
    private static $display = [];

    public static function replace($how)
    {
        if (!self::$display) {
            self::$display = [
                'aioseo_0'            => __('All in One SEO: Open Graph Image', 'remove-unused-media'),
                'aioseo_1'            => __('All in One SEO: Twitter Image', 'remove-unused-media'),
                'aioseo_2'            => __('All in One SEO: Knowledge Graph', 'remove-unused-media'),
                'aioseo_3'            => __('All in One SEO: Open Graph Default', 'remove-unused-media'),
                'aioseo_4'            => __('All in One SEO: Twitter Default', 'remove-unused-media'),
                'cf7'                 => __('Used in Form (CF7)', 'remove-unused-media'),
                'cf7_contact'         => __('Used in contact form (CF7)', 'remove-unused-media'),
                'content'             => __('Used in content', 'remove-unused-media'),
                'favicon'             => __('Favicon', 'remove-unused-media'),
                'featured_image'      => __('Featured image', 'remove-unused-media'),
                'flipbook3d'          => __('Flipbook3D', 'remove-unused-media'),
                'flipbook3d_pdf'      => __('Flipbook3D PDF page', 'remove-unused-media'),
                'flipbook3d_thumb'    => __('Flipbook3D thumbnail', 'remove-unused-media'),
                'gdpr_cookie'         => __('GDPR Cookie Consent', 'remove-unused-media'),
                'gp_pro_retina'       => __('Generate Press Retina Logo', 'remove-unused-media'),
                'gp_pro_site'         => __('Generate Press Website Logo', 'remove-unused-media'),
                'image_widget'        => __('Used as Image Widget', 'remove-unused-media'),
                'kadence'             => __('Kadence Slider', 'remove-unused-media'),
                'kadence_background'  => __('Kadence Slider background', 'remove-unused-media'),
                'kadence_layer'       => __('Kadence Slider layer', 'remove-unused-media'),
                'meta'                => __('Used in meta', 'remove-unused-media'),
                'modula'              => __("Used in modula gallery", 'remove-unused-media'),
                'ninja_forms_0'       => __('Ninja Forms Form', 'remove-unused-media'),
                'ninja_forms_1'       => __('Ninja Forms HTML', 'remove-unused-media'),
                'ninja_forms_2'       => __('Ninja Forms Success Message', 'remove-unused-media'),
                'ninja_forms_3'       => __('Ninja Forms Email', 'remove-unused-media'),
                'options'             => __('Used in options', 'remove-unused-media'),
                'product_description' => __('Product Description', 'remove-unused-media'),
                'product_image'       => __('Product Image', 'remove-unused-media'),
                'product_thumbnail'   => __('Used as Product Thumbnail', 'remove-unused-media'),
                'product_variation'   => __('Product Variation Image', 'remove-unused-media'),
                'rankmath_fb'         => __('Facebook image (RankMath)', 'remove-unused-media'),
                'rankmath_social'     => __('Social Media image or logo (RankMath)', 'remove-unused-media'),
                'rankmath_twitter'    => __('Twitter image (RankMath)', 'remove-unused-media'),
                'revision'            => __('Used in a past version', 'remove-unused-media'),
                'siteorigin'          => __('Siteorigin Pagebuilder background', 'remove-unused-media'),
                'slider_revolution_0' => __('Slider Revolution background', 'remove-unused-media'),
                'slider_revolution_1' => __('Slider Revolution image', 'remove-unused-media'),
                'slider_revolution_2' => __('Slider Revolution poster', 'remove-unused-media'),
                'slider_revolution_3' => __('Slider Revolution video', 'remove-unused-media'),
                'slider_revolution_4' => __('Slider Revolution audio', 'remove-unused-media'),
                'slider_revolution_5' => __('Slider Revolution button', 'remove-unused-media'),
                'tablepress_table'    => __('Used in content (TablePress)', 'remove-unused-media'),
                'themify'             => __('Themify', 'remove-unused-media'),
                'thrive_leads'        => __('Thrive Leads', 'remove-unused-media'),
                'thrive_template'     => __('Used in Thrive Theme Builder Template', 'remove-unused-media'),
                'thrive_testimonial'  => __('Testimonial in Thrive Ovation', 'remove-unused-media'),
                'up_solution'         => __('UpSolution/Impreza', 'remove-unused-media'),
                'wondergrid_image'    => __('Wondergrid Gallery image', 'remove-unused-media'),
                'wondergrid_thumb'    => __('Wondergrid Gallery thumbnail', 'remove-unused-media'),
                'woocommerce_0'       => __('WooCommerce Gallery', 'remove-unused-media'),
                'woocommerce_1'       => __('WooCommerce short description', 'remove-unused-media'),
                'woocommerce_2'       => __('WooCommerce Placeholder', 'remove-unused-media'),
                'woocommerce_3'       => __('WooCommerce Category Image', 'remove-unused-media'),
                'wp_schema_pro'       => __('Used in WP Schema Pro', 'remove-unused-media'),
                'yoast_fb'            => __('Facebook image (Yoast SEO)', 'remove-unused-media'),
                'yoast_social'        => __('Social Media image (Yoast SEO)', 'remove-unused-media'),
                'yoast_twitter'       => __('Twitter image (Yoast SEO)', 'remove-unused-media'),
                'yoast_company'       => __('company logo (Yoast SEO)', 'remove-unused-media'),
            ];
        }
        $how_display = $how;
        if (is_array($how)) {
            $how_display = self::$display[$how[0]] ?? $how[0];
            if (count($how) >= 2 && $how[1]) {
                $how_display .= ' (' . $how[1] . ')';
            }
            if (count($how) >= 3) {
                $how_display .= ': ' . $how[2];
            }
        } elseif (isset(self::$display[$how])) {
            $how_display = self::$display[$how];
        }

        return $how_display;
    }
}

final class Table extends RUM_List_Table
{
    private $data_source;
    private $all_data;

    public function __construct($src = 'unused')
    {
        parent::__construct();
        $this->data_source = $src;
    }

    public function get_data_for_html(): array
    {
        $data                = [];
        $data['num_unused']  = Util\num_unused();
        $data['num_used']    = Util\num_used();
        $data['num_ignored'] = Util\num_ignored();
        $data['num_trash']   = count(
            get_posts([
                'numberposts'      => -1,
                'suppress_filters' => true,
                'post_type'        => 'attachment',
                'post_status'      => 'trash',
                'lang'             => '',
            ])
        );
        $data['unused']      = 'unused' == $this->data_source ? 'class="selected"' : '';
        $data['used']        = 'used' == $this->data_source ? 'class="selected"' : '';
        $data['ignored']     = 'ignored' == $this->data_source ? 'class="selected"' : '';
        $data['trash']       = 'trash' == $this->data_source ? 'class="selected"' : '';
        $data['url_warning'] = Util\url_warnings();

        return $data;
    }

    /**
     * Prepares the list of items for displaying.
     */
    public function prepare_items()
    {
        $columns  = $this->get_columns();
        $hidden   = $this->get_hidden_columns();
        $sortable = $this->get_sortable_columns();

        if (rum_fs()->is_free_plan() || rum_fs()->can_use_premium_code()) {
            $wpml_lang = apply_filters('wpml_current_language', null);
            if ($this->data_source == 'used') {
                $this->all_data = Util\get_used();
            } elseif ($this->data_source == 'unused') {
                $this->all_data = Util\get_unused();
            } elseif ($this->data_source == 'ignored') {
                $this->all_data = Util\get_ignored();
            }
            if (!empty($wpml_lang)) {
                if ('all' === $wpml_lang) {
                    if ($this->data_source == 'used') {
                        $del = [];
                        foreach ($this->all_data as $key => $img) {
                            foreach ($this->all_data as $key2 => $img2) {
                                if ($key >= $key2) {
                                    continue;
                                }
                                if ($img['url'] == $img2['url']
                                    && $img['where'] == $img2['where']
                                    && $img['how'] == $img2['how']) {
                                    $del[] = $key2;
                                }
                            }
                        }
                        foreach ($del as $d) {
                            unset($this->all_data[$d]);
                        }
                    }
                } else {
                    $filter         = function ($e) use ($wpml_lang) {
                        $lang = apply_filters(
                            'wpml_element_language_code',
                            null,
                            ['element_id' => $e['ID'], 'element_type' => 'attachment']
                        );

                        return $lang == $wpml_lang;
                    };
                    $this->all_data = array_filter($this->all_data, $filter);
                }
            }
        } else {
            $this->all_data = ['unused' => [], 'used' => [], 'ignored' => []];
        }

        $data = $this->table_data();
        usort($data, [&$this, 'sort_data']);

        $user     = get_current_user_id();
        $per_page = get_user_meta($user, 'rum_per_page', true);
        if (empty($per_page) || $per_page < 1) {
            $per_page = 20;
        }
        $currentPage = $this->get_pagenum();
        $totalItems  = count($data);

        $this->set_pagination_args($totalItems, $per_page);

        $data = array_slice($data, (($currentPage - 1) * $per_page), $per_page);

        $this->_column_headers = [$columns, $hidden, $sortable];
        $this->items           = $data;
    }

    /**
     * An internal method that sets all the necessary pagination arguments.
     *
     * @param int $totalItems
     * @param int $per_page
     */
    private function set_pagination_args(int $totalItems, int $per_page)
    {
        $total_pages = ceil($totalItems / $per_page);
        // Redirect if page number is invalid and headers are not already sent.
        if (!headers_sent() && !wp_doing_ajax() && $total_pages > 0 && $this->get_pagenum() > $total_pages) {
            wp_redirect(add_query_arg('paged', $total_pages));

            exit;
        }

        $this->_pagination_args = [
            'total_items' => $totalItems,
            'total_pages' => $total_pages,
            'per_page'    => $per_page,
        ];
    }

    public function get_table_classes(): array
    {
        return ['widefat', 'wp-list-table', 'fixed', 'striped', 'table-view-list', 'media'];
    }

    /**
     * @param array $item
     *
     * @return string
     */
    public function column_cb(array $item): string
    {
        return "<input type='checkbox' name='media[]' id='cb-select-{$item['ID']}' value='{$item['ID']}' />";
    }

    public function column_title($item)
    {
        $post = get_post($item['ID']);
        list($mime) = explode('/', $post->post_mime_type);

        $title = _draft_or_post_title($post);
        $thumb = wp_get_attachment_image($post->ID, [60, 60], true, ['alt' => '']);

        $link_start = sprintf(
            '<a href="%s" aria-label="%s">',
            get_edit_post_link($post->ID),
            esc_attr(sprintf(__('&#8220;%s&#8221; (Edit)'), $title))
        );
        $link_end   = '</a>';

        $class = $thumb ? ' class="has-media-icon"' : ''; ?>
        <strong<?php
        echo $class; ?>>
            <?php
            echo $link_start;
            if ($thumb) {
                ?>
                <span class="media-icon <?php
                echo sanitize_html_class($mime . '-icon'); ?>">
                    <?php
                    echo $thumb; ?>
                </span>
                <?php
            }
            echo $title . $link_end;
            _media_states($post); ?>
        </strong>
        <p class="filename">
            <span class="screen-reader-text"><?php
                _e('Media URL:'); ?> </span>
            <?php
            echo esc_html(substr(wp_get_attachment_url($post->ID), strlen(get_site_url()))); ?>
        </p>
        <?php
    }

    public function column_date($item)
    {
        $post = get_post($item['ID']);
        if ('0000-00-00 00:00:00' === $post->post_date) {
            $h_time = __('Unpublished');
        } else {
            $time      = get_post_timestamp($post);
            $time_diff = time() - $time;

            if ($time && $time_diff > 0 && $time_diff < DAY_IN_SECONDS) {
                $h_time = sprintf(__('%s ago'), human_time_diff($time));
            } else {
                $h_time = get_the_time(__('Y/m/d'), $post);
            }
        }

        return $h_time;
    }

    public function column_size($item): string
    {
        return human_filesize($item['size_sort']);
    }

    public function column_id($item)
    {
        return $item['ID'];
    }

    public function column_extension($item)
    {
        return wp_check_filetype($item['filename'])['ext'];
    }

    public function column_where($item): string
    {
        $content = '';
        foreach ($item['where'] as $i => $where) {
            if ($i > 1) {
                $content .= "<p class='more-where-{$item['ID']}'>";
            } else {
                $content .= '<p>';
            }
            if (is_numeric($where)) {
                $title = get_the_title($where) ?: __('(no title)', 'remove-unused-media');
                $link  = get_permalink($where);
                $where = "<a href='$link' target='_blank'>$title</a>";
            }
            $content .= $where;
            if (count($item['how'][$i]) > 1) {
                $content .= "<span class='how-{$item['ID']}-$i'>";
                $content .= str_repeat('<br/>&#8203;', count($item['how'][$i]) - 1);
                $content .= '</span>';
            }
            $content .= '</p>';
            if (1 == $i && count($item['where']) > 2) {
                $content .= "<p id='more-where-link-{$item['ID']}'>";
                $content .= "<a onclick='showMoreWhere({$item['ID']})'>+ ";
                $content .= sprintf(
                    _x('%d more...', '"show more"-link in "where" column', 'remove-unused-media'),
                    count($item['where']) - 2
                );
                $content .= '</a></p>';
            }
        }

        return $content;
    }

    public function column_how($item): string
    {
        $content = '';
        foreach ($item['where'] as $j => $where) {
            if ($j > 1) {
                $content .= "<p class='more-how-{$item['ID']}'>";
            } else {
                $content .= '<p>';
            }
            $content .= How::replace($item['how'][$j][0]);
            if (count($item['how'][$j]) > 1) {
                $content .= "<span id='more-how-link-{$item['ID']}-$j' onclick='toggleMoreHow({$item['ID']},$j)'> &#9664;</span>";
                for ($i = 1; $i < count($item['how'][$j]); ++$i) {
                    $how     = How::replace($item['how'][$j][$i]);
                    $content .= "<span class='how-{$item['ID']}-$j'><br/>$how</span>";
                }
            }
            $content .= '</p>';
        }

        return $content;
    }

    public function get_hidden_columns(): array
    {
        return [];
    }

    public function table_data(): array
    {
        if (!rum_fs()->is_free_plan() && !rum_fs()->can_use_premium_code()) {
            return [];
        }
        if ('trash' === $this->data_source) {
            $args  = [
                'numberposts'      => -1,
                'suppress_filters' => true,
                'post_type'        => 'attachment',
                'post_status'      => 'trash',
                'sort_order'       => 'asc',
                'orderby'          => 'ID',
                'lang'             => '',
            ];
            $posts = get_posts($args);
            $data  = [];
            foreach ($posts as $post) {
                $file            = get_attached_file($post->ID);
                $id              = $post->ID;
                $data[$post->ID] = [
                    'ID'        => $id,
                    'filename'  => basename($file),
                    'date_sort' => get_post_time('U', false, $id),
                    'size_sort' => is_file($file) ? filesize($file) : 0,
                ];
            }
        } else {
            $data = $this->all_data;
            foreach ($data as $d1 => $d2) {
                $data[$d1]['date_sort'] = get_post_time('U', false, $d1);
                $file                   = get_attached_file($d1);
                $data[$d1]['size_sort'] = is_file($file) ? filesize($file) : 0;
                $data[$d1]['filename']  = basename($file);
            }
        }
        if (isset($_REQUEST['attachment-filter']) && !empty($_REQUEST['attachment-filter'])) {
            $filter = $_REQUEST['attachment-filter'];
            if (0 === strpos($filter, 'post_mime_type:')) {
                $filter = str_replace('post_mime_type:', '', $filter);
                $check  = function ($item) use ($filter) {
                    return wp_match_mime_types($filter, get_post_mime_type((int)$item['ID']));
                };
            } /* 'Detached' and 'Mine' filters
            elseif ('detached' == $filter) {
                $check = function ($item) {
                    return !get_post_parent((int) $item['ID']);
                };
            } elseif ('mine' == $filter) {
                $filter = get_current_user_id();
                $check = function ($item) use ($filter) {
                    return $filter == get_post_field('post_author', $item['ID']);
                };
            }*/ else {
                $check = function () {
                    return true;
                };
            }

            $data = array_filter($data, $check);
        }
        if (isset($_REQUEST['s']) && !empty($_REQUEST['s'])) {
            $keyword = $_REQUEST['s'];
            $data    = array_filter($data, function ($item) use ($keyword) {
                $match = !(false === strpos($item['filename'], $keyword));

                $title = get_the_title((int)$item['ID']);

                return $match || !(false === strpos($title, $keyword));
            });
        }

        return $data;
    }

    /**
     * Gets a list of sortable columns.
     * The format is:
     * - `'internal-name' => 'orderby'`
     * - `'internal-name' => array( 'orderby', 'asc' )` - The second element sets the initial sorting order.
     * - `'internal-name' => array( 'orderby', true )`  - The second element makes the initial order descending.
     * @return array
     */
    public function get_sortable_columns(): array
    {
        return [
            'id'    => ['ID', false],
            'title' => ['filename', false],
            'date'  => ['date_sort', false],
            'size'  => ['size_sort', false],
        ];
    }

    private function sort_data($a, $b)
    {
        // Set defaults
        $orderby = 'date_sort';
        $order   = 'desc';

        if (!empty($_REQUEST['orderby'])) {
            $orderby = $_REQUEST['orderby'];
        }

        if (!empty($_REQUEST['order'])) {
            $order = $_REQUEST['order'];
        }

        switch ($orderby) {
            case 'filename':
                $result = strcmp($a[$orderby], $b[$orderby]);

                break;

            case 'ID':
            case 'date_sort':
            case 'size_sort':
                $result = $a[$orderby] - $b[$orderby];

                break;

            default:
                $result = strcmp($a[$orderby], $b[$orderby]);
        }

        if ('asc' === $order) {
            return $result;
        }

        return -$result;
    }

    /**
     * Gets the name of the default primary column.
     * @return string name of the default primary column
     */
    public function get_default_primary_column_name(): string
    {
        return 'title';
    }

    /**
     * Gets the name of the primary column.
     * @return string the name of the primary column
     */
    public function get_primary_column_name(): string
    {
        return 'title';
    }

    /**
     * Retrieves the list of bulk actions available for this table.
     * The format is an associative array where each element represents either a top level option value and label, or
     * an array representing an optgroup and its options.
     * For a standard option, the array element key is the field value and the array element value is the field label.
     * For an optgroup, the array element key is the label and the array element value is an associative array of
     * options as above.
     * Example:
     *     [
     *         'edit'         => 'Edit',
     *         'delete'       => 'Delete',
     *         'Change State' => [
     *             'feature' => 'Featured',
     *             'sale'    => 'On Sale',
     *         ]
     *     ]
     * @return array
     * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup.
     * @since 3.1.0
     */
    public function get_bulk_actions(): array
    {
        if ('trash' == $this->data_source) {
            $actions = [
                'untrash' => __('Restore'),
                'delete'  => __('Delete permanently'),
            ];
        } else {
            $actions = [];
            if (MEDIA_TRASH) {
                $actions['delete'] = __('Move to Trash');
            } else {
                $actions['delete'] = __('Delete permanently');
            }
            if ('ignored' == $this->data_source) {
                $actions['unignore'] = __('Unignore', 'remove-unused-media');
            } else {
                $actions['ignore'] = __('Add to ignored', 'remove-unused-media');
            }
        }

        return $actions;
    }

    /**
     * Message to be displayed when there are no items.
     */
    public function no_items()
    {
        if (!get_option('rum_analysis_counter')) {
            if (rum_fs()->is_free_plan() || rum_fs()->can_use_premium_code()) {
                $start_analysis = __('Start First Analysis', 'remove-unused-media');
                echo "<a onclick='triggerAnalysis()'>$start_analysis</a>";
            } else {
                _e('License not activated!', 'remove-unused-media');
            }

            return;
        }
        $wpml_lang = apply_filters('wpml_current_language', null);
        if ('unused' == $this->data_source) {
            if (!empty($wpml_lang) && $wpml_lang != 'all') {
                _e('No unused media files for the current language detected. Awesome!', 'remove-unused-media');
            } else {
                _e('No unused media files detected. Awesome!', 'remove-unused-media');
            }
        } elseif ('used' == $this->data_source) {
            if (!empty($wpml_lang) && $wpml_lang != 'all') {
                _e('No media files for the current language are used.', 'remove-unused-media');
            } else {
                _e('Uh-oh! No used media files detected.', 'remove-unused-media');
            }
        } elseif ('ignored' == $this->data_source) {
            if (!empty($wpml_lang) && $wpml_lang != 'all') {
                _e('You are not ignoring any media files for the current language.', 'remove-unused-media');
            } else {
                _e('You are not ignoring any media files.', 'remove-unused-media');
            }
        } else {
            _e('No items found.');
        }
    }

    /**
     * Gets a list of columns.
     * The format is:
     * - `'internal-name' => 'Title'`
     * @return array
     */
    public function get_columns(): array
    {
        $columns = [
            'cb'        => '<input type="checkbox" />',
            'title'     => _x('File', 'column name'),
            'date'      => _x('Date', 'column name'),
            'size'      => __('File Size', 'remove-unused-media'),
            'id'        => __('ID', 'remove-unused-media'),
            'extension' => __('Filetype', 'remove-unused-media'),
        ];
        if ('used' == $this->data_source) {
            $columns = array_merge($columns, [
                'where' => __('Where?', 'remove-unused-media'),
                'how'   => __('How?', 'remove-unused-media'),
            ]);
        }

        return $columns;
    }

    /**
     * Generates and display row actions links for the list table.
     *
     * @param array  $item        the item being acted upon
     * @param string $column_name current column name
     * @param string $primary     primary column name
     *
     * @return string the row actions HTML, or an empty string
     *                if the current column is not the primary column
     */
    public function handle_row_actions(array $item, string $column_name, string $primary): string
    {
        if ($column_name !== $primary) {
            return '';
        }

        $ID      = $item['ID'];
        $title   = get_the_title($ID);
        $actions = [];

        if ('trash' == $this->data_source) {
            $actions['untrash'] = sprintf(
                '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',
                wp_nonce_url("post.php?action=untrash&amp;post={$item['ID']}", 'untrash-post_' . $item['ID']),
                esc_attr(sprintf(__('Restore &#8220;%s&#8221; from the Trash'), $title)),
                __('Restore')
            );
            $delete_ays         = '';
            $actions['delete']  = sprintf(
                '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>',
                wp_nonce_url("post.php?action=delete&amp;post={$item['ID']}", 'delete-post_' . $item['ID']),
                $delete_ays,
                esc_attr(sprintf(__('Delete &#8220;%s&#8221; permanently'), $title)),
                __('Delete Permanently')
            );

            return $this->row_actions($actions);
        }

        $btn_tmp         = '<a href="%s" aria-label="%s" target="_blank">%s</a>';
        $url             = get_edit_post_link($ID);
        $aria_label      = esc_attr(sprintf(__('Edit &#8220;%s&#8221;'), $title));
        $label           = __('Edit');
        $actions['edit'] = sprintf($btn_tmp, $url, $aria_label, $label);

        if (MEDIA_TRASH) {
            $btn_tmp          = '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>';
            $url              = wp_nonce_url('post.php?action=trash&amp;post=' . $ID, 'trash-post_' . $ID);
            $aria_label       = esc_attr(sprintf(__('Move &#8220;%s&#8221; to the Trash'), $title));
            $label            = _x('Trash', 'verb');
            $actions['trash'] = sprintf($btn_tmp, $url, $aria_label, $label);
        } else {
            $delete_ays        = " onclick='return showNotice.warn();'";
            $btn_tmp           = '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>';
            $url               = wp_nonce_url('post.php?action=delete&amp;post=' . $ID, 'delete-post_' . $ID);
            $aria_label        = esc_attr(sprintf(__('Delete &#8220;%s&#8221; permanently'), $title));
            $label             = __('Delete Permanently');
            $actions['delete'] = sprintf($btn_tmp, $url, $delete_ays, $aria_label, $label);
        }

        $btn_tmp         = '<a href="%s" aria-label="%s" rel="bookmark" target="_blank">%s</a>';
        $url             = get_permalink($ID);
        $aria_label      = esc_attr(sprintf(__('View &#8220;%s&#8221;'), $title));
        $label           = __('View');
        $actions['view'] = sprintf($btn_tmp, $url, $aria_label, $label);

        $btn_tmp = '<a href="%s" aria-label="%s">%s</a>';
        if ('ignored' == $this->data_source) {
            $url                 = add_query_arg(['action' => 'unignore', 'media' => $ID]);
            $url                 = wp_nonce_url($url, 'unignore');
            $aria_label          = esc_attr(sprintf(__('Unignore &#8220;%s&#8221;', 'remove-unused-media'), $title));
            $label               = __('Unignore', 'remove-unused-media');
            $actions['unignore'] = sprintf($btn_tmp, $url, $aria_label, $label);
        } else {
            $url               = add_query_arg(['action' => 'ignore', 'media' => $ID]);
            $url               = wp_nonce_url($url, 'ignore');
            $aria_label        = esc_attr(sprintf(__('Ignore &#8220;%s&#8221;', 'remove-unused-media'), $title));
            $label             = __('Ignore', 'remove-unused-media');
            $actions['ignore'] = sprintf($btn_tmp, $url, $aria_label, $label);
        }

        return $this->row_actions($actions);
    }

    /**
     * Extra controls to be displayed between bulk actions and pagination.
     *
     * @param string $which
     */
    public function extra_tablenav(string $which)
    {
        if ('top' === $which) {
            $views = $this->filter(); ?>
            <label for="attachment-filter" class="screen-reader-text"><?php
                _e('Filter by type'); ?></label>
            <select class="attachment-filters" name="attachment-filter" id="attachment-filter">
                <?php
                if (!empty($views)) {
                    foreach ($views as $view) {
                        echo "\t$view\n";
                    }
                } ?>
            </select>
            <?php
            submit_button(__('Filter'), '', 'filter_action', false, ['id' => 'post-query-submit']);
            if ('trash' == $this->data_source && $this->has_items()) {
                submit_button(__('Empty Trash'), 'apply', 'delete_all', false);
            }
        }
    }

    protected function filter(): array
    {
        $type_links = [];

        $filter = empty($_REQUEST['attachment-filter']) ? '' : $_REQUEST['attachment-filter'];

        $type_links['all'] = sprintf(
            '<option value=""%s>%s</option>',
            selected($filter, true, false),
            __('All media items')
        );
        list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query();

        foreach ($post_mime_types as $mime_type => $label) {
            if (!wp_match_mime_types($mime_type, $avail_post_mime_types)) {
                continue;
            }

            $selected = $filter && 0 === strpos($filter, 'post_mime_type:');
            $selected = $selected && wp_match_mime_types($mime_type, str_replace('post_mime_type:', '', $filter));
            $selected = selected($selected, true, false);

            $type_links[$mime_type] = sprintf(
                '<option value="post_mime_type:%s"%s>%s</option>',
                esc_attr($mime_type),
                $selected,
                $label[0]
            );
        }

        /* 'Detached' and 'Mine' filters
                $detached = (isset($_REQUEST['attachment-filter']) && 'detached' === $_REQUEST['attachment-filter']);
                $type_links['detached'] = '<option value="detached"'.($detached ? ' selected="selected"' : '').'>'.__('Unattached').'</option>';

                $type_links['mine'] = sprintf(
                    '<option value="mine"%s>%s</option>',
                    selected('mine' === $filter, true, false),
                    _x('Mine', 'media items')
                );
        */

        return $type_links;
    }

    /**
     * Displays the search box.
     */
    public function search_box()
    {
        $tab = $_REQUEST['tab'] ?? 'unused';
        echo "<input type='hidden' name='tab' value='$tab' />";

        echo '<input type="hidden" name="page" value="' . $_REQUEST['page'] . '" />';

        if (empty($_REQUEST['s']) && !$this->has_items()) {
            return;
        }

        if (!empty($_REQUEST['orderby'])) {
            echo '<input type="hidden" name="orderby" value="' . esc_attr($_REQUEST['orderby']) . '" />';
        }
        if (!empty($_REQUEST['order'])) {
            echo '<input type="hidden" name="order" value="' . esc_attr($_REQUEST['order']) . '" />';
        }
        if (!empty($_REQUEST['post_mime_type'])) {
            echo '<input type="hidden" name="post_mime_type" value="' . esc_attr($_REQUEST['post_mime_type']) . '" />';
        } ?>
        <p class="search-box">
            <label class="screen-reader-text" for="rum-search-input">
                <?php
                echo _x('Search:', 'Label for search bar', 'remove-unused-media'); ?>
            </label>
            <input type="search" id="rum-search-input" name="s" value="<?php
            _admin_search_query(); ?>"/>
            <?php
            submit_button(
                _x('Search', 'placeholder in searchbar', 'remove-unused-media'), '', '', false,
                ['id' => 'search-submit']
            );
            ?>
        </p>
        <?php
    }

    /**
     * Generates the required HTML for a list of row action links.
     *
     * @param string[] $actions an array of action links
     *
     * @return string the HTML for the row actions
     */
    private function row_actions(array $actions): string
    {
        $action_count = count($actions);
        $mode         = get_user_setting('posts_list_mode', 'list');
        $class        = 'excerpt' === $mode ? 'row-actions visible' : 'row-actions';
        $out          = "<div class='$class'>";
        foreach ($actions as $action => $link) {
            --$action_count;
            $sep = ($action_count > 0) ? ' | ' : '';
            $out .= "<span class='$action'>$link$sep</span>";
        }
        $out .= '</div>';
        $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">';
        $out .= __('Show more details');
        $out .= '</span></button>';

        return $out;
    }
}
