page_number = $page_number;
        $this->total_pages = $total_pages;
        $this->search_terms = $search_terms;
    }
    public function display_intro(Page $page)
    {
        $text = "
The first thing you'll probably want to do is create a new account; note
that the first account you create will by default be marked as the board's
administrator, and any further accounts will be regular users.
Once logged in you can play with the settings, install extra features,
and of course start organising your images :-)
This message will go away once your first image is uploaded~
 
";
        $page->set_title("Welcome to Shimmie ".VERSION);
        $page->set_heading("Welcome to Shimmie");
        $page->add_block(new Block("Nothing here yet!", $text, "main", 0));
    }
    /**
     * #param Image[] $images
     */
    public function display_page(Page $page, array $images)
    {
        $this->display_shortwiki($page);
        $this->display_page_header($page, $images);
        $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms);
        $page->add_block(new Block("Navigation", $nav, "left", 0));
        if (count($images) > 0) {
            $this->display_page_images($page, $images);
        } else {
            $this->display_error(404, "No Images Found", "No images were found to match the search criteria");
        }
    }
    /**
     * #param string[] $parts
     */
    public function display_admin_block(array $parts)
    {
        global $page;
        $page->add_block(new Block("List Controls", join("
", $parts), "left", 50));
    }
    /**
     * #param string[] $search_terms
     */
    protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string
    {
        $prev = $page_number - 1;
        $next = $page_number + 1;
        $u_tags = url_escape(Tag::implode($search_terms));
        $query = empty($u_tags) ? "" : '/'.$u_tags;
        $h_prev = ($page_number <= 1) ? "Prev" : 'Prev';
        $h_index = "Index";
        $h_next = ($page_number >= $total_pages) ? "Next" : 'Next';
        $h_search_string = html_escape(Tag::implode($search_terms));
        $h_search_link = make_link();
        $h_search = "
			
		";
        return $h_prev.' | '.$h_index.' | '.$h_next.'
'.$h_search;
    }
    /**
     * #param Image[] $images
     */
    protected function build_table(array $images, ?string $query): string
    {
        $h_query = html_escape($query);
        $table = "";
        foreach ($images as $image) {
            $table .= $this->build_thumb_html($image);
        }
        $table .= "
";
        return $table;
    }
    protected function display_shortwiki(Page $page)
    {
        global $config;
        if (class_exists('Wiki') && $config->get_bool(WikiConfig::TAG_SHORTWIKIS)) {
            if (count($this->search_terms) == 1) {
                $st = Tag::implode($this->search_terms);
                $wikiPage = Wiki::get_page($st);
                $short_wiki_description = '';
                if ($wikiPage->id != -1) {
                    // only show first line of wiki
                    $short_wiki_description = explode("\n", $wikiPage->body, 2)[0];
                    $tfe = new TextFormattingEvent($short_wiki_description);
                    send_event($tfe);
                    $short_wiki_description = $tfe->formatted;
                }
                $wikiLink = make_link("wiki/$st");
                if (class_exists('TagCategories')) {
                    $this->tagcategories = new TagCategories;
                    $tag_category_dict = $this->tagcategories->getKeyedDict();
                    $st = $this->tagcategories->getTagHtml(html_escape($st), $tag_category_dict);
                }
                $short_wiki_description = ''.$st.' ⓘ
'.$short_wiki_description;
                $page->add_block(new Block(null, $short_wiki_description, "main", 0, "short-wiki-description"));
            }
        }
    }
    /**
     * #param Image[] $images
     */
    protected function display_page_header(Page $page, array $images)
    {
        global $config;
        if (count($this->search_terms) == 0) {
            $page_title = $config->get_string(SetupConfig::TITLE);
        } else {
            $search_string = implode(' ', $this->search_terms);
            $page_title = html_escape($search_string);
            if (count($images) > 0) {
                $page->set_subheading("Page {$this->page_number} / {$this->total_pages}");
            }
        }
        /*
        if ($this->page_number > 1 || count($this->search_terms) > 0) {
            $page_title .= " / $page_number";
        }
        */
        $page->set_title($page_title);
        $page->set_heading($page_title);
    }
    /**
     * #param Image[] $images
     */
    protected function display_page_images(Page $page, array $images)
    {
        if (count($this->search_terms) > 0) {
            if ($this->page_number > 3) {
                // only index the first pages of each term
                $page->add_html_header('');
            }
            $query = url_escape(Tag::caret(Tag::implode($this->search_terms)));
            $page->add_block(new Block("Images", $this->build_table($images, "#search=$query"), "main", 10, "image-list"));
            $this->display_paginator($page, "post/list/$query", null, $this->page_number, $this->total_pages, true);
        } else {
            $page->add_block(new Block("Images", $this->build_table($images, null), "main", 10, "image-list"));
            $this->display_paginator($page, "post/list", null, $this->page_number, $this->total_pages, true);
        }
    }
    public function get_help_html()
    {
        return 'Searching is largely based on tags, with a number of special keywords available that allow searching based on properties of the images.
        
        tagname
        Returns images that are tagged with "tagname".
         
         
        
        tagname othertagname
        Returns images that are tagged with "tagname" and "othertagname".
 
         
        Most tags and keywords can be prefaced with a negative sign (-) to indicate that you want to search for images that do not match something.
        
        -tagname
        Returns images that are not tagged with "tagname".
 
         
        
        -tagname -othertagname
        Returns images that are not tagged with "tagname" and "othertagname". This is different than without the negative sign, as images with "tagname" or "othertagname" can still be returned as long as the other one is not present.
 
         
        
        tagname -othertagname
        Returns images that are tagged with "tagname", but are not tagged with "othertagname".
 
         
        Wildcard searches are possible as well using * for "any one, more, or none" and ? for "any one".
        
        tagn*
        Returns images that are tagged with "tagname", "tagnot", or anything else that starts with "tagn".
 
         
        
        tagn?me
        Returns images that are tagged with "tagname", "tagnome", or anything else that starts with "tagn", has one character, and ends with "me".
 
         
        
        tags=1
        Returns images with exactly 1 tag.
 
         
        
        tags>0
        Returns images with 1 or more tags. 
         
        Can use <, <=, >, >=, or =.
        
        
        Search for images by aspect ratio
        
        
        ratio=4:3
        Returns images with an aspect ratio of 4:3.
 
         
        
        ratio>16:9
        Returns images with an aspect ratio greater than 16:9. 
         
        Can use <, <=, >, >=, or =. The relation is calculated by dividing width by height.
        
        
        Search for images by file size
        
        
        filesize=1
        Returns images exactly 1 byte in size.
 
         
        
        filesize>100mb
        Returns images greater than 100 megabytes in size. 
         
        Can use <, <=, >, >=, or =. Supported suffixes are kb, mb, and gb. Uses multiples of 1024.
        
        
        Search for images by MD5 hash
        
        
        hash=0D3512CAA964B2BA5D7851AF5951F33B
        Returns image with an MD5 hash 0D3512CAA964B2BA5D7851AF5951F33B.
 
         
        
        Search for images by file type
        
        
        filetype=jpg
        Returns images that are of type "jpg".
 
         
        
        Search for images by file name
        
        
        filename=picasso.jpg
        Returns images that are named "picasso.jpg".
 
         
        
        Search for images by source
        
        
        source=http://google.com/
        Returns images with a source of "http://google.com/".
 
         
        
        source=any
        Returns images with a source set.
 
         
        
        source=none
        Returns images without a source set.
 
         
        
        
        Search for images by date posted.
        
        posted>=07-19-2019
        Returns images posted on or after 07-19-2019.
 
         
        Can use <, <=, >, >=, or =. Date format is mm-dd-yyyy. Date posted includes time component, so = will not work unless the time is exact.
        
        
        Search for images by image dimensions
        
        size=640x480
        Returns images exactly 640 pixels wide by 480 pixels high.
 
         
        
        size>1920x1080
        Returns images with a width larger than 1920 and a height larger than 1080.
         
        
        width=1000
        Returns images exactly 1000 pixels wide.
         
        
        height=1000
        Returns images exactly 1000 pixels high.
         
        Can use <, <=, >, >=, or =.
        
        
        
        Sorting search results can be done using the pattern order:field_direction. _direction can be either _asc or _desc, indicating ascending (123) or descending (321) order.
        
        
        order:id_asc
        Returns images sorted by ID, smallest first.
 
         
        
        order:width_desc
        Returns images sorted by width, largest first.
         
        
        These fields are supported:
            
            - id
- width
- height
- filesize
- filename
';
    }
}