<?php /*

 Composr
 Copyright (c) Christopher Graham, 2004-2024

 See docs/LICENSE.md for full licensing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license    http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright  Christopher Graham
 * @package    catalogues
 */

/**
 * Hook class.
 */
class Hook_addon_registry_catalogues
{
    /**
     * Get a list of file permissions to set.
     *
     * @param  boolean $runtime Whether to include wildcards represented runtime-created chmoddable files
     * @return array File permissions to set
     */
    public function get_chmod_array(bool $runtime = false) : array
    {
        $chmod = [];
        if ($runtime) {
            $chmod = array_merge(
                $chmod,
                [
                    'uploads/catalogues/*',
                ]
            );
        }
        $chmod = array_merge(
            $chmod,
            [
                'uploads/catalogues',
            ]
        );
        return $chmod;
    }

    /**
     * Get the version of the software this addon is for (used in generating the TAR filename).
     *
     * @return float Version number
     */
    public function get_version() : float
    {
        return cms_version_number();
    }

    /**
     * Get the minimum required version of the website software needed to use this addon.
     *
     * @return float Minimum required website software version
     */
    public function get_min_cms_version() : float
    {
        return 11.0;
    }

    /**
     * Get the maximum compatible version of the website software to use this addon.
     *
     * @return ?float Maximum compatible website software version (null: no maximum version currently)
     */
    public function get_max_cms_version() : ?float
    {
        return 11.9;
    }

    /**
     * Get the addon category.
     *
     * @return string The category
     */
    public function get_category() : string
    {
        return 'Information Display';
    }

    /**
     * Get the description of the addon.
     *
     * @return string Description of the addon
     */
    public function get_description() : string
    {
        return 'Describe your own custom data record types (by choosing and configuring fields) and populate with records. Supports tree structures, and most standard CMS features (e.g. ratings).';
    }

    /**
     * Get a list of tutorials that apply to this addon.
     *
     * @return array List of tutorials
     */
    public function get_applicable_tutorials() : array
    {
        return [
            'tut_catalogues',
            'tut_information',
            'tut_fields',
        ];
    }

    /**
     * Get a mapping of dependency types.
     *
     * @return array A structure specifying dependency information
     */
    public function get_dependencies() : array
    {
        return [
            'requires' => [],
            'recommends' => [],
            'conflicts_with' => [],
        ];
    }

    /**
     * Explicitly say which icon should be used.
     *
     * @return URLPATH Icon
     */
    public function get_default_icon() : string
    {
        return 'themes/default/images/icons/menu/rich_content/catalogues/catalogues.svg';
    }

    /**
     * Get a list of files that belong to this addon.
     *
     * @return array List of files
     */
    public function get_file_list() : array
    {
        return [
            'cms/pages/modules/cms_catalogues.php',
            'lang/EN/catalogues.ini',
            'site/pages/modules/catalogues.php',
            'sources/blocks/main_catalogues_form.php',
            'sources/blocks/main_cc_embed.php',
            'sources/blocks/main_contact_catalogues.php',
            'sources/catalogues.php',
            'sources/catalogues2.php',
            'sources/hooks/modules/admin_import/catalogues.php',
            'sources/hooks/modules/admin_import_types/catalogues.php',
            'sources/hooks/modules/admin_newsletter/catalogues.php',
            'sources/hooks/modules/admin_setupwizard/catalogues.php',
            'sources/hooks/modules/search/catalogue_categories.php',
            'sources/hooks/modules/search/catalogue_entries.php',
            'sources/hooks/systems/actionlog/catalogues.php',
            'sources/hooks/systems/addon_registry/catalogues.php',
            'sources/hooks/systems/ajax_tree/choose_catalogue_category.php',
            'sources/hooks/systems/ajax_tree/choose_catalogue_entry.php',
            'sources/hooks/systems/attachments/catalogue_entry.php',
            'sources/hooks/systems/block_ui_renderers/catalogues.php',
            'sources/hooks/systems/cleanup/catalogues.php',
            'sources/hooks/systems/commandr_fs/catalogues.php',
            'sources/hooks/systems/config/catalogue_entries_per_page.php',
            'sources/hooks/systems/config/catalogue_subcats_per_page.php',
            'sources/hooks/systems/config/catalogues_subcat_narrowin.php',
            'sources/hooks/systems/config/search_catalogue_categories.php',
            'sources/hooks/systems/config/search_catalogue_entries.php',
            'sources/hooks/systems/content_meta_aware/catalogue.php',
            'sources/hooks/systems/content_meta_aware/catalogue_category.php',
            'sources/hooks/systems/content_meta_aware/catalogue_entry.php',
            'sources/hooks/systems/cron/catalogue_entry_timeouts.php',
            'sources/hooks/systems/cron/catalogue_view_reports.php',
            'sources/hooks/systems/notifications/catalogues.php',
            'sources/hooks/systems/page_groupings/catalogues.php',
            'sources/hooks/systems/points/catalogue_entry__add.php',
            'sources/hooks/systems/privacy/catalogues.php',
            'sources/hooks/systems/reorganise_uploads/catalogues.php',
            'sources/hooks/systems/rss/catalogues.php',
            'sources/hooks/systems/sitemap/catalogue.php',
            'sources/hooks/systems/sitemap/catalogue_category.php',
            'sources/hooks/systems/sitemap/catalogue_entry.php',
            'sources/hooks/systems/snippets/exists_catalogue.php',
            'sources/hooks/systems/symbols/CATALOGUE_ENTRY_ALL_FIELD_VALUES.php',
            'sources/hooks/systems/symbols/CATALOGUE_ENTRY_BACKREFS.php',
            'sources/hooks/systems/symbols/CATALOGUE_ENTRY_FIELD_VALUE.php',
            'sources/hooks/systems/symbols/CATALOGUE_ENTRY_FIELD_VALUE_PLAIN.php',
            'sources/hooks/systems/tasks/catalogues_recache.php',
            'sources/hooks/systems/tasks/export_catalogue.php',
            'sources/hooks/systems/tasks/import_catalogue.php',
            'sources/hooks/systems/trackback/catalogues.php',
            'themes/default/css/catalogues.css',
            'themes/default/images/icons/menu/cms/catalogues/add_one_catalogue.svg',
            'themes/default/images/icons/menu/cms/catalogues/edit_one_catalogue.svg',
            'themes/default/images/icons/menu/cms/catalogues/edit_this_catalogue.svg',
            'themes/default/images/icons/menu/cms/catalogues/index.html',
            'themes/default/images/icons/menu/rich_content/catalogues/catalogues.svg',
            'themes/default/images/icons/menu/rich_content/catalogues/contacts.svg',
            'themes/default/images/icons/menu/rich_content/catalogues/faqs.svg',
            'themes/default/images/icons/menu/rich_content/catalogues/index.html',
            'themes/default/images/icons/menu/rich_content/catalogues/links.svg',
            'themes/default/images/icons/menu/rich_content/catalogues/products.svg',
            'themes/default/images/icons/menu/rich_content/catalogues/projects.svg',
            'themes/default/images/icons_monochrome/menu/cms/catalogues/add_one_catalogue.svg',
            'themes/default/images/icons_monochrome/menu/cms/catalogues/edit_one_catalogue.svg',
            'themes/default/images/icons_monochrome/menu/cms/catalogues/edit_this_catalogue.svg',
            'themes/default/images/icons_monochrome/menu/cms/catalogues/index.html',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/catalogues.svg',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/contacts.svg',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/faqs.svg',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/index.html',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/links.svg',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/products.svg',
            'themes/default/images/icons_monochrome/menu/rich_content/catalogues/projects.svg',
            'themes/default/javascript/catalogues.js',
            'themes/default/templates/CATALOGUE_ADDING_SCREEN.tpl',
            'themes/default/templates/CATALOGUE_CATEGORIES_LIST_LINE.tpl',
            'themes/default/templates/CATALOGUE_CATEGORY_HEADING.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_CATEGORY_EMBED.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_CATEGORY_SCREEN.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_ENTRY_SCREEN.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_FIELDMAP_ENTRY_FIELD.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_FIELDMAP_ENTRY_WRAP.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_GRID_ENTRY_FIELD.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_GRID_ENTRY_WRAP.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TABULAR_ENTRY_FIELD.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TABULAR_ENTRY_WRAP.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TABULAR_HEADCELL.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TABULAR_WRAP.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TITLELIST_ENTRY.tpl',
            'themes/default/templates/CATALOGUE_DEFAULT_TITLELIST_WRAP.tpl',
            'themes/default/templates/CATALOGUE_EDITING_SCREEN.tpl',
            'themes/default/templates/CATALOGUE_ENTRIES_LIST_LINE.tpl',
            'themes/default/templates/CATALOGUE_links_TABULAR_ENTRY_FIELD.tpl',
            'themes/default/templates/CATALOGUE_links_TABULAR_ENTRY_WRAP.tpl',
            'themes/default/templates/CATALOGUE_links_TABULAR_HEADCELL.tpl',
            'themes/default/templates/CATALOGUE_links_TABULAR_WRAP.tpl',
            'themes/default/templates/SEARCH_RESULT_CATALOGUE_ENTRIES.tpl',
            'uploads/catalogues/.htaccess',
            'uploads/catalogues/index.html',
        ];
    }

    /**
     * Get mapping between template names and the method of this class that can render a preview of them.
     *
     * @return array The mapping
     */
    public function tpl_previews() : array
    {
        return [
            'templates/CATALOGUE_ADDING_SCREEN.tpl' => 'administrative__catalogue_adding_screen',
            'templates/CATALOGUE_EDITING_SCREEN.tpl' => 'administrative__catalogue_editing_screen',
            'templates/CATALOGUE_ENTRIES_LIST_LINE.tpl' => 'catalogue_entries_list_line',
            'templates/CATALOGUE_CATEGORIES_LIST_LINE.tpl' => 'catalogue_categories_list_line',
            'templates/SEARCH_RESULT_CATALOGUE_ENTRIES.tpl' => 'search_result_catalogue_entries',

            'templates/CATALOGUE_DEFAULT_CATEGORY_SCREEN.tpl' => 'category_screen',

            'templates/CATALOGUE_DEFAULT_FIELDMAP_ENTRY_WRAP.tpl' => 'fieldmap_category_screen',
            'templates/CATALOGUE_DEFAULT_FIELDMAP_ENTRY_FIELD.tpl' => 'fieldmap_category_screen',
            'templates/CATALOGUE_CATEGORY_HEADING.tpl' => 'fieldmap_category_screen',

            'templates/CATALOGUE_DEFAULT_GRID_ENTRY_WRAP.tpl' => 'grid_category_screen',
            'templates/CATALOGUE_DEFAULT_GRID_ENTRY_FIELD.tpl' => 'grid_category_screen',
            'templates/CATALOGUE_DEFAULT_CATEGORY_EMBED.tpl' => 'grid_category_screen',

            'templates/CATALOGUE_DEFAULT_TABULAR_WRAP.tpl' => 'tabular_category_screen',
            'templates/CATALOGUE_DEFAULT_TABULAR_HEADCELL.tpl' => 'tabular_category_screen',
            'templates/CATALOGUE_DEFAULT_TABULAR_ENTRY_WRAP.tpl' => 'tabular_category_screen',
            'templates/CATALOGUE_DEFAULT_TABULAR_ENTRY_FIELD.tpl' => 'tabular_category_screen',

            'templates/CATALOGUE_links_TABULAR_WRAP.tpl' => 'tabular_category_screen__links',
            'templates/CATALOGUE_links_TABULAR_HEADCELL.tpl' => 'tabular_category_screen__links',
            'templates/CATALOGUE_links_TABULAR_ENTRY_WRAP.tpl' => 'tabular_category_screen__links',
            'templates/CATALOGUE_links_TABULAR_ENTRY_FIELD.tpl' => 'tabular_category_screen__links',

            'templates/CATALOGUE_DEFAULT_TITLELIST_ENTRY.tpl' => 'list_category_screen',
            'templates/CATALOGUE_DEFAULT_TITLELIST_WRAP.tpl' => 'list_category_screen',

            'templates/CATALOGUE_DEFAULT_ENTRY_SCREEN.tpl' => 'entry_screen',
        ];
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__category_screen() : object
    {
        return lorem_globalise(do_lorem_template('CATALOGUE_DEFAULT_CATEGORY_SCREEN', [
            'ID' => placeholder_numeric_id(),
            'ADD_DATE_RAW' => placeholder_date_raw(),
            'TITLE' => lorem_screen_title(),
            '_TITLE' => lorem_phrase(),
            'CATALOGUE_TITLE' => lorem_phrase(),
            'TAGS' => placeholder_tags(),
            'CATALOGUE' => lorem_word_2(),
            'ADD_ENTRY_URL' => placeholder_url(),
            'ADD_CAT_URL' => placeholder_url(),
            'ADD_CAT_TITLE' => do_lang_tempcode('ADD_CATALOGUE_CATEGORY'),
            'EDIT_CAT_URL' => placeholder_url(),
            'EDIT_CATALOGUE_URL' => placeholder_url(),
            'DESCRIPTION' => lorem_sentence(),
            'DISPLAY_TYPE' => 'TITLELIST',
            'CC_SORT' => 'title',
            'CAT_SELECT' => '*',
            'FILTER' => '',
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__grid_category_screen() : object
    {
        $fields = new Tempcode();
        foreach (placeholder_array() as $v) {
            $name = placeholder_random_id();
            $fields->attach(do_lorem_template('CATALOGUE_DEFAULT_GRID_ENTRY_FIELD', [
                'ENTRYID' => placeholder_numeric_id(),
                'CATALOGUE' => lorem_phrase(),
                'TYPE' => lorem_word(),
                'FIELD' => lorem_word(),
                'FIELDID' => $name,
                '_FIELDID' => $name,
                'FIELDTYPE' => lorem_word(),
                'VALUE_PLAIN' => lorem_phrase(),
                'VALUE' => lorem_phrase(),
            ]));
        }

        $entries = do_lorem_template('CATALOGUE_DEFAULT_GRID_ENTRY_WRAP', [
            'ID' => placeholder_numeric_id(),
            'FIELDS' => $fields,
            'FIELDS_GRID' => '',
            'VIEW_URL' => placeholder_url(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => placeholder_image_url(),
            'FIELD_1_PLAIN' => placeholder_image_url(),
            'EDIT_URL' => placeholder_url(),
            'RATING' => new Tempcode(),
            'ALLOW_RATING' => false,
            'CATALOGUE' => lorem_word(),
            'SUBMITTER' => placeholder_numeric_id(),
        ]);

        return lorem_globalise(do_lorem_template('CATALOGUE_DEFAULT_CATEGORY_EMBED', [
            'DISPLAY_TYPE' => 'GRID',
            'ENTRIES' => $entries,
            'ROOT' => placeholder_numeric_id(),
            'BLOCK_PARAMS' => '',
            'SORTING' => '',
            'PAGINATION' => '',

            'START' => '0',
            'MAX' => '10',
            'START_PARAM' => 'x_start',
            'MAX_PARAM' => 'x_max',
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__fieldmap_category_screen() : object
    {
        $fields = new Tempcode();
        foreach (placeholder_array() as $v) {
            $name = placeholder_random_id();
            $fields->attach(do_lorem_template('CATALOGUE_DEFAULT_FIELDMAP_ENTRY_FIELD', [
                'ENTRYID' => placeholder_numeric_id(),
                'CATALOGUE' => lorem_phrase(),
                'TYPE' => lorem_word(),
                'FIELD' => lorem_word(),
                'FIELDID' => $name,
                '_FIELDID' => $name,
                'FIELDTYPE' => lorem_word(),
                'VALUE_PLAIN' => lorem_phrase(),
                'VALUE' => lorem_phrase(),
            ]));
        }

        $entries = do_lorem_template('CATALOGUE_DEFAULT_FIELDMAP_ENTRY_WRAP', [
            'ID' => placeholder_numeric_id(),
            'FIELDS' => $fields,
            'VIEW_URL' => placeholder_url(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => lorem_phrase(),
            'FIELD_1_PLAIN' => lorem_phrase(),
            'EDIT_URL' => placeholder_url(),
            'RATING' => new Tempcode(),
            'ALLOW_RATING' => false,
            'CATALOGUE' => lorem_word(),
            'SUBMITTER' => placeholder_numeric_id(),
            'GIVE_CONTEXT' => false,
        ]);

        $content = new Tempcode();
        foreach (placeholder_array(2) as $v) {
            $content->attach(do_lorem_template('CATALOGUE_CATEGORY_HEADING', [
                'LETTER' => lorem_phrase(),
                'ENTRIES' => $entries,
            ]));
        }

        return lorem_globalise($content, null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__list_category_screen() : object
    {
        $entries = new Tempcode();
        foreach (placeholder_array() as $v) {
            $entries->attach(do_lorem_template('CATALOGUE_DEFAULT_TITLELIST_ENTRY', [
                'VIEW_URL' => placeholder_url(),
                'ID' => placeholder_numeric_id(),
                'FIELD_0' => lorem_phrase(),
                'FIELD_0_PLAIN' => lorem_phrase(),
                'FIELD_1' => lorem_phrase(),
                'FIELD_1_PLAIN' => lorem_phrase(),
                'CATALOGUE' => lorem_word(),
                'SUBMITTER' => placeholder_numeric_id(),
                'EDIT_URL' => placeholder_url(),
                'RATING' => new Tempcode(),
                'ALLOW_RATING' => false,
            ]));
        }

        return lorem_globalise(do_lorem_template('CATALOGUE_DEFAULT_TITLELIST_WRAP', [
            'CATALOGUE' => lorem_word(),
            'CONTENT' => $entries,
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__tabular_category_screen__links() : object
    {
        $head = new Tempcode();
        $entry_fields = new Tempcode();
        foreach (placeholder_array() as $v) {
            $name = placeholder_random_id();
            $head->attach(do_lorem_template('CATALOGUE_links_TABULAR_HEADCELL', [
                'SORT_ASC_SELECTED' => true,
                'SORT_DESC_SELECTED' => false,
                'SORT_URL_ASC' => placeholder_url(),
                'SORT_URL_DESC' => placeholder_url(),
                'CATALOGUE' => lorem_word(),
                'FIELDID' => $name,
                '_FIELDID' => $name,
                'FIELD' => $v,
                'FIELDTYPE' => 'text',
            ]));

            $name = placeholder_random_id();
            $entry_fields->attach(do_lorem_template('CATALOGUE_links_TABULAR_ENTRY_FIELD', [
                'FIELDID' => $name,
                '_FIELDID' => $name,
                'ENTRYID' => placeholder_numeric_id(),
                'VALUE' => lorem_phrase(),
            ]));
        }

        $rows = new Tempcode();
        $rows->attach(do_lorem_template('CATALOGUE_links_TABULAR_ENTRY_WRAP', [
            'ID' => placeholder_numeric_id(),
            'FIELDS_TABULAR' => $entry_fields,
            'VIEW_URL' => placeholder_url(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => lorem_phrase(),
            'FIELD_1_PLAIN' => lorem_phrase(),
            'EDIT_URL' => placeholder_url(),
            'RATING' => new Tempcode(),
            'ALLOW_RATING' => false,
            'CATALOGUE' => lorem_word(),
            'SUBMITTER' => placeholder_numeric_id(),
        ]));

        return lorem_globalise(do_lorem_template('CATALOGUE_links_TABULAR_WRAP', [
            'CATALOGUE' => lorem_word(),
            'HEAD' => $head,
            'CONTENT' => $rows,
            'FIELD_COUNT' => '3',
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__tabular_category_screen() : object
    {
        $head = do_lorem_template('CATALOGUE_DEFAULT_TABULAR_HEADCELL', [
            'SORT_ASC_SELECTED' => true,
            'SORT_DESC_SELECTED' => false,
            'SORT_URL_ASC' => placeholder_url(),
            'SORT_URL_DESC' => placeholder_url(),
            'CATALOGUE' => lorem_word(),
            'FIELDID' => placeholder_numeric_id(),
            '_FIELDID' => placeholder_numeric_id(),
            'FIELD' => lorem_word(),
            'FIELDTYPE' => 'text',
        ]);

        $fields = new Tempcode();
        $fields->attach(do_lorem_template('CATALOGUE_DEFAULT_TABULAR_ENTRY_FIELD', [
            'FIELDID' => placeholder_numeric_id(),
            'ENTRYID' => placeholder_numeric_id(),
            'VALUE' => lorem_phrase(),
        ]));

        $rows = new Tempcode();
        $rows->attach(do_lorem_template('CATALOGUE_DEFAULT_TABULAR_ENTRY_WRAP', [
            'ID' => placeholder_numeric_id(),
            'FIELDS_TABULAR' => $fields,
            'VIEW_URL' => placeholder_url(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => lorem_phrase(),
            'FIELD_1_PLAIN' => lorem_phrase(),
            'EDIT_URL' => placeholder_url(),
            'RATING' => new Tempcode(),
            'ALLOW_RATING' => false,
            'CATALOGUE' => lorem_word(),
            'SUBMITTER' => placeholder_numeric_id(),
        ]));

        return lorem_globalise(do_lorem_template('CATALOGUE_DEFAULT_TABULAR_WRAP', [
            'CATALOGUE' => lorem_word(),
            'HEAD' => $head,
            'CONTENT' => $rows,
            'FIELD_COUNT' => '1',
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__entry_screen() : object
    {
        $fields = new Tempcode();
        foreach (placeholder_array() as $v) {
            $name = placeholder_random_id();
            $fields->attach(do_lorem_template('CATALOGUE_DEFAULT_FIELDMAP_ENTRY_FIELD', [
                'ENTRYID' => placeholder_numeric_id(),
                'CATALOGUE' => lorem_phrase(),
                'TYPE' => lorem_word(),
                'FIELD' => lorem_word(),
                'FIELDID' => $name,
                '_FIELDID' => $name,
                'FIELDTYPE' => lorem_word(),
                'VALUE_PLAIN' => lorem_phrase(),
                'VALUE' => lorem_phrase(),
            ]));
        }

        $entry = do_lorem_template('CATALOGUE_DEFAULT_FIELDMAP_ENTRY_WRAP', [
            'ID' => placeholder_numeric_id(),
            'FIELDS' => $fields,
            'VIEW_URL' => placeholder_url(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => lorem_phrase(),
            'FIELD_1_PLAIN' => lorem_phrase(),
            'EDIT_URL' => placeholder_url(),
            'RATING' => new Tempcode(),
            'ALLOW_RATING' => false,
            'GIVE_CONTEXT' => false,
            'CATALOGUE' => lorem_word(),
            'SUBMITTER' => placeholder_numeric_id(),
        ]);

        return lorem_globalise(do_lorem_template('CATALOGUE_DEFAULT_ENTRY_SCREEN', [
            'TITLE' => lorem_screen_title(),
            'WARNINGS' => '',
            'ID' => placeholder_numeric_id(),
            'ENTRY' => $entry,
            'EDIT_URL' => placeholder_url(),
            'TRACKBACK_DETAILS' => placeholder_trackbacks_wrapper(),
            'RATING_DETAILS' => placeholder_rating('catalogue_entry'),
            'COMMENT_DETAILS' => placeholder_comments(placeholder_comments_form()),
            'ADD_DATE' => placeholder_date(),
            'ADD_DATE_RAW' => placeholder_date_raw(),
            'EDIT_DATE_RAW' => placeholder_date_raw(),
            'VIEWS' => placeholder_number(),
            'TAGS' => placeholder_tags(),
            'SUBMITTER' => placeholder_numeric_id(),
            'FIELD_0' => lorem_phrase(),
            'FIELD_0_PLAIN' => lorem_phrase(),
            'FIELD_1' => lorem_phrase(),
            'FIELD_1_PLAIN' => lorem_phrase(),
            'CATALOGUE' => lorem_word(),
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__administrative__catalogue_adding_screen() : object
    {
        require_javascript('checking');

        return lorem_globalise(do_lorem_template('CATALOGUE_ADDING_SCREEN', [
            'HIDDEN' => '',
            'TITLE' => lorem_screen_title(),
            'TEXT' => lorem_sentence_html(),
            'URL' => placeholder_url(),
            'FIELDS' => placeholder_fields(),
            'FIELDS_NEW' => placeholder_form(),
            'SUBMIT_ICON' => 'admin/add',
            'SUBMIT_NAME' => lorem_word(),
            'PREVIEW' => true,
            'JS_FUNCTION_CALLS' => [],
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__administrative__catalogue_editing_screen() : object
    {
        require_javascript('checking');

        return lorem_globalise(do_lorem_template('CATALOGUE_EDITING_SCREEN', [
            'HIDDEN' => '',
            'TITLE' => lorem_screen_title(),
            'TEXT' => lorem_sentence_html(),
            'URL' => placeholder_url(),
            'FIELDS' => placeholder_fields(),
            'FIELDS_EXISTING' => placeholder_form(),
            'FIELDS_NEW' => placeholder_form(),
            'SUBMIT_ICON' => 'admin/edit_this',
            'SUBMIT_NAME' => lorem_word(),
            'PREVIEW' => true,
            'JS_FUNCTION_CALLS' => [],
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__catalogue_entries_list_line() : object
    {
        return lorem_globalise(do_lorem_template('CATALOGUE_ENTRIES_LIST_LINE', [
            'BREADCRUMBS' => lorem_phrase(),
            'NAME' => lorem_word(),
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__catalogue_categories_list_line() : object
    {
        return lorem_globalise(do_lorem_template('CATALOGUE_CATEGORIES_LIST_LINE', [
            'BREADCRUMBS' => lorem_phrase(),
            '_COUNT' => placeholder_number(),
            'COUNT' => placeholder_number(),
        ]), null, '', true);
    }

    /**
     * Get a preview(s) of a (group of) template(s), as a full standalone piece of HTML in Tempcode format.
     * Uses sources/lorem.php functions to place appropriate stock-text. Should not hard-code things, as the code is intended to be declarative.
     * Assumptions: You can assume all Lang/CSS/JavaScript files in this addon have been pre-required.
     *
     * @return Tempcode Preview
     */
    public function tpl_preview__search_result_catalogue_entries() : object
    {
        return lorem_globalise(do_lorem_template('SEARCH_RESULT_CATALOGUE_ENTRIES', [
            'BUILDUP' => lorem_phrase(),
            'NAME' => lorem_word(),
            'TITLE' => lorem_phrase(),
        ]), null, '', true);
    }

    /**
     * Uninstall default content.
     */
    public function uninstall_test_content()
    {
        require_code('catalogues');
        require_code('catalogues2');
        require_code('fields');

        $to_delete = $GLOBALS['SITE_DB']->query_select('catalogue_efv_short', ['DISTINCT ce_id'], ['cv_value' => lorem_phrase()]);
        foreach ($to_delete as $record) {
            if ($GLOBALS['SITE_DB']->query_select_value_if_there('catalogue_entries', 'id', ['id' => $record['ce_id']]) !== null/*in case of corrupt data*/) {
                actual_delete_catalogue_entry($record['ce_id']);
            }
        }
        $to_delete = $GLOBALS['SITE_DB']->query_select('catalogue_efv_short_trans', ['DISTINCT ce_id'], [$GLOBALS['SITE_DB']->translate_field_ref('cv_value') => lorem_phrase()]);
        foreach ($to_delete as $record) {
            if ($GLOBALS['SITE_DB']->query_select_value_if_there('catalogue_entries', 'id', ['id' => $record['ce_id']]) !== null/*in case of corrupt data*/) {
                actual_delete_catalogue_entry($record['ce_id']);
            }
        }

        $to_delete = $GLOBALS['SITE_DB']->query_select('catalogue_categories', ['id'], [$GLOBALS['SITE_DB']->translate_field_ref('cc_title') => lorem_phrase()]);
        foreach ($to_delete as $record) {
            actual_delete_catalogue_category($record['id']);
        }
    }

    /**
     * Install default content.
     */
    public function install_test_content()
    {
        require_code('catalogues');
        require_code('catalogues2');
        require_code('fields');

        $catalogues = $GLOBALS['SITE_DB']->query_select('catalogues c' . $GLOBALS['SITE_DB']->singular_join('catalogue_fields', 'f', 'f.c_name=c.c_name', 'cf_order', 'MIN', 'JOIN'), ['c.c_name', 'f.cf_order', 'f.cf_type', 'f.id'], [], 'ORDER BY id');
        foreach ($catalogues as $catalogue) {
            if (($catalogue['cf_type'] == 'short_text') || ($catalogue['cf_type'] == 'short_trans')) { // Only if first field is 'short'
                $is_tree = $GLOBALS['SITE_DB']->query_select_value('catalogues', 'c_is_tree', ['c_name' => $catalogue['c_name']]);

                $category_id = actual_add_catalogue_category($catalogue['c_name'], lorem_phrase(), lorem_paragraph(), '', ($is_tree == 1) ? $GLOBALS['SITE_DB']->query_select_value('catalogue_categories', 'MIN(id)', ['c_name' => $catalogue['c_name']]) : null, placeholder_image_url());
                require_code('permissions2');
                set_global_category_access('catalogues_category', $category_id);

                $fields = $GLOBALS['SITE_DB']->query_select('catalogue_fields', ['*'], ['c_name' => $catalogue['c_name']], 'ORDER BY cf_order');
                $map = [];
                foreach ($fields as $field) {
                    switch ($field['cf_type']) {
                        case 'picture':
                            $map[$field['id']] = placeholder_image_url();
                            break;

                        default:
                            $ob = get_fields_hook($field['cf_type']);
                            list(, , $storage_type) = $ob->get_field_value_row_bits($field);

                            switch ($storage_type) {
                                case 'short':
                                case 'short_trans':
                                    $map[$field['id']] = lorem_phrase();
                                    break;
                                case 'long':
                                case 'long_trans':
                                    $map[$field['id']] = lorem_paragraph();
                                    break;
                                case 'float':
                                    $map[$field['id']] = float_to_raw_string(0.9);
                                    break;
                                case 'integer':
                                    $map[$field['id']] = strval(56);
                                    break;
                            }

                            break;
                    }
                }
                actual_add_catalogue_entry($category_id, 1, '', 1, 1, 1, $map);
            }
        }
    }

    /**
     * Find available predefined content, and what is installed.
     *
     * @return array A map of available predefined content codenames, and details (if installed, and title)
     */
    public function enumerate_predefined_content() : array
    {
        require_lang('catalogues');

        return [
            'have_default_catalogues_projects' => [
                'title' => do_lang_tempcode('HAVE_DEFAULT_CATALOGUES_PROJECTS'),
                'description' => do_lang_tempcode('DESCRIPTION_HAVE_DEFAULT_CATALOGUES_PROJECTS'),
                'installed' => $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_name', ['c_name' => 'projects']) !== null,
            ],
            'have_default_catalogues_faqs' => [
                'title' => do_lang_tempcode('HAVE_DEFAULT_CATALOGUES_FAQS'),
                'description' => do_lang_tempcode('DESCRIPTION_HAVE_DEFAULT_CATALOGUES_FAQS'),
                'installed' => $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_name', ['c_name' => 'faqs']) !== null,
            ],
            'have_default_catalogues_links' => [
                'title' => do_lang_tempcode('HAVE_DEFAULT_CATALOGUES_LINKS'),
                'description' => do_lang_tempcode('DESCRIPTION_HAVE_DEFAULT_CATALOGUES_LINKS'),
                'installed' => $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_name', ['c_name' => 'links']) !== null,
            ],
            'have_default_catalogues_contacts' => [
                'title' => do_lang_tempcode('HAVE_DEFAULT_CATALOGUES_CONTACTS'),
                'description' => do_lang_tempcode('DESCRIPTION_HAVE_DEFAULT_CATALOGUES_CONTACTS'),
                'installed' => $GLOBALS['SITE_DB']->query_select_value_if_there('catalogues', 'c_name', ['c_name' => 'contacts']) !== null,
            ],
        ];
    }

    /**
     * Install predefined content.
     *
     * @param  ?array $content A list of predefined content labels to install (null: all)
     */
    public function install_predefined_content(?array $content = null)
    {
        if ((($content === null) || (in_array('have_default_catalogues_projects', $content))) && (!has_predefined_content('catalogues', 'have_default_catalogues_projects'))) {
            require_lang('catalogues');
            require_code('catalogues'); // Needed for the constants
            require_code('permissions2');
            require_code('catalogues2');
            require_code('lang3');
            actual_add_catalogue('projects', lang_code_to_default_content('c_title', 'DEFAULT_CATALOGUE_PROJECTS_TITLE', false, 2), '', C_DT_FIELDMAPS, 0, '', 30);
            $fields = [
                ['NAME', 'DESCRIPTION_NAME', 'short_trans', 1, 1, '', 0],
                ['MAINTAINER', 'DESCRIPTION_MAINTAINER', 'member', 0, 1, '!', 1],
                ['DESCRIPTION', 'DESCRIPTION_DESCRIPTION', 'long_trans', 0, 1, '', 0],
                ['PROJECT_PROGRESS', 'DESCRIPTION_PROJECT_PROGRESS', 'integer', 0, 1, '0', 0],
            ];
            foreach ($fields as $i => $field) {
                actual_add_catalogue_field(
                    'projects', // $c_name
                    lang_code_to_default_content('cf_name', $field[0], false, 2), // $name
                    lang_code_to_default_content('cf_description', $field[1], false, 3), // $description
                    $field[2], // $type
                    $i, // $order
                    $field[3], // $defines_order
                    1, // $visible
                    $field[6], // $sensitive
                    $field[5], // $default
                    $field[4], // $required
                    1, // $is_sortable
                    1, // $include_in_main_search
                    0 // $allow_template_search
                );
            }
            $cat_id = actual_add_catalogue_category('projects', lang_code_to_default_content('cc_title', 'DEFAULT_CATALOGUE_PROJECTS_TITLE', false, 2), lang_code_to_default_content('cc_description', 'DEFAULT_CATALOGUE_PROJECTS_DESCRIPTION', true, 3), '', null, '');
            set_global_category_access('catalogues_catalogue', 'projects');
            set_global_category_access('catalogues_category', $cat_id);
        }

        if ((($content === null) || (in_array('have_default_catalogues_faqs', $content))) && (!has_predefined_content('catalogues', 'have_default_catalogues_faqs'))) {
            require_lang('catalogues');
            require_code('permissions2');
            require_code('catalogues2');
            require_code('lang3');
            actual_add_catalogue('faqs', lang_code_to_default_content('c_title', 'DEFAULT_CATALOGUE_FAQS_TITLE', false, 2), '', C_DT_FIELDMAPS, 0, '', 0);
            $fields = [
                ['QUESTION', 'DESCRIPTION_QUESTION', 'short_trans', 0, 1, 1, ''],
                ['ANSWER', '_DESCRIPTION_ANSWER', 'long_trans', 0, 1, 1, ''],
                ['ORDER', 'DESCRIPTION_ORDER', 'integer', 1, 0, 0, 'default=AUTO_INCREMENT'],
            ];
            foreach ($fields as $i => $field) {
                actual_add_catalogue_field(
                    'faqs', // $c_name
                    lang_code_to_default_content('cf_name', $field[0], false, 2), // $name
                    lang_code_to_default_content('cf_description', $field[1], false, 3), // $description
                    $field[2], // $type
                    $i, // $order
                    $field[3], // $defines_order
                    $field[5], // $visible
                    0, // $sensitive
                    '', // $default
                    $field[4], // $required
                    1,
                    1,
                    0,
                    1, // $put_in_category
                    1, // $put_in_search
                    $field[6] // $options
                );
            }
            $cat_id = actual_add_catalogue_category('faqs', lang_code_to_default_content('cc_title', 'DEFAULT_CATALOGUE_FAQS_TITLE', false, 2), lang_code_to_default_content('cc_description', 'DEFAULT_CATALOGUE_FAQS_DESCRIPTION', true, 3), '', null, '');
            set_global_category_access('catalogues_catalogue', 'faqs');
            set_global_category_access('catalogues_category', $cat_id);
        }

        if ((($content === null) || (in_array('have_default_catalogues_links', $content))) && (!has_predefined_content('catalogues', 'have_default_catalogues_links'))) {
            require_lang('catalogues');
            require_code('permissions2');
            require_code('catalogues2');
            require_code('lang3');
            actual_add_catalogue('links', lang_code_to_default_content('c_title', 'DEFAULT_CATALOGUE_LINKS_TITLE', false, 2), lang_code_to_default_content('c_description', 'DEFAULT_CATALOGUE_LINKS_DESCRIPTION', true, 3), C_DT_TABULAR, 1, '', 0);
            $fields = [
                // Name, Description, Type, Defines order, Required, Put in category
                ['TITLE', 'DESCRIPTION_TITLE', 'short_trans', 1, 1, 1],
                ['URL', 'DESCRIPTION_URL', 'url', 0, 1, 0],
                ['DESCRIPTION', 'DESCRIPTION_DESCRIPTION', 'long_trans', 0, 0, 1],
            ];
            foreach ($fields as $i => $field) {
                actual_add_catalogue_field(
                    'links', // $c_name
                    lang_code_to_default_content('cf_name', $field[0], false, 2), // $name
                    lang_code_to_default_content('cf_description', $field[1], false, 3), // $description
                    $field[2], // $type
                    $i, // $order
                    $field[3], // $defines_order
                    1, // $visible
                    0, // $sensitive
                    '', // $default
                    $field[4], // $required
                    1,
                    1,
                    0,
                    $field[5] // $put_in_category
                );
            }
            $cat_id = $GLOBALS['SITE_DB']->query_select_value_if_there('catalogue_categories', 'id', ['c_name' => 'links']);
            set_global_category_access('catalogues_catalogue', 'links');
            set_global_category_access('catalogues_category', $cat_id);
        }

        if ((($content === null) || (in_array('have_default_catalogues_contacts', $content))) && (!has_predefined_content('catalogues', 'have_default_catalogues_contacts'))) {
            require_lang('catalogues');
            require_code('permissions2');
            require_code('catalogues2');
            require_code('lang3');
            actual_add_catalogue('contacts', lang_code_to_default_content('c_title', 'CONTACTS', false, 2), lang_code_to_default_content('c_description', 'DEFAULT_CATALOGUE_CONTACTS_DESCRIPTION', true, 2), C_DT_FIELDMAPS, 0, '', 30);
            $fields = [
                ['CONTACT_FIRST_NAME', '', 'short_text', 0, 1, 1],
                ['CONTACT_LAST_NAME', '', 'short_text', 1, 1, 1],
                ['EMAIL_ADDRESS', '', 'short_text', 0, 0, 1],
                ['CONTACT_COMPANY', '', 'short_text', 0, 0, 1],
                ['CONTACT_HOMEADDRESS', '', 'short_text', 0, 0, 1],
                ['CONTACT_CITY', '', 'short_text', 0, 0, 1],
                ['CONTACT_HOMEPHONE', '', 'short_text', 0, 0, 1],
                ['CONTACT_WORKPHONE', '', 'short_text', 0, 0, 1],
                ['CONTACT_HOMEPAGE', '', 'short_text', 0, 0, 1],
                ['CONTACT_IM', '', 'short_text', 0, 0, 1],
                ['NOTES', '', 'long_text', 0, 0, 1],
                ['CONTACT_PHOTO', '', 'picture', 0, 0, 1],
            ];
            foreach ($fields as $i => $field) {
                actual_add_catalogue_field(
                    'contacts', // $c_name
                    lang_code_to_default_content('cf_name', $field[0], false, 2), // $name
                    insert_lang('cf_description', '', 3), // $description
                    $field[2], // $type
                    $i, // $order
                    $field[3], // $defines_order
                    1, // $visible
                    $field[5], // $sensitive
                    '', // $default
                    $field[4], // $required
                    1,
                    1,
                    0
                );
            }
            actual_add_catalogue_category('contacts', lang_code_to_default_content('cc_title', 'CONTACTS', false, 2), '', '', null, '');
        }
    }

    /**
     * Uninstall predefined content.
     *
     * @param  ?array $content A list of predefined content labels to uninstall (null: all)
     */
    public function uninstall_predefined_content(?array $content = null)
    {
        if ((($content === null) || (in_array('have_default_catalogues_projects', $content))) && (has_predefined_content('catalogues', 'have_default_catalogues_projects'))) {
            require_lang('catalogues');
            require_code('catalogues2');
            actual_delete_catalogue('projects');

            require_code('menus2');
            delete_menu_item_simple(do_lang('DEFAULT_CATALOGUE_PROJECTS_TITLE'));
            delete_menu_item_simple('_SEARCH:cms_catalogues:add_entry:catalogue_name=projects');
            delete_menu_item_simple('_SEARCH:catalogues:index:projects');
        }

        if ((($content === null) || (in_array('have_default_catalogues_faqs', $content))) && (has_predefined_content('catalogues', 'have_default_catalogues_faqs'))) {
            require_lang('catalogues');
            require_code('catalogues2');
            actual_delete_catalogue('faqs');

            require_code('menus2');
            delete_menu_item_simple('_SEARCH:catalogues:index:faqs');
        }

        if ((($content === null) || (in_array('have_default_catalogues_links', $content))) && (has_predefined_content('catalogues', 'have_default_catalogues_links'))) {
            require_lang('catalogues');
            require_code('catalogues2');
            actual_delete_catalogue('links');

            require_code('menus2');
            delete_menu_item_simple('_SEARCH:catalogues:index:links');
        }

        if ((($content === null) || (in_array('have_default_catalogues_contacts', $content))) && (has_predefined_content('catalogues', 'have_default_catalogues_contacts'))) {
            require_lang('catalogues');
            require_code('catalogues2');
            actual_delete_catalogue('contacts');

            require_code('menus2');
            delete_menu_item_simple('_SEARCH:catalogues:index:contacts');
        }
    }
}
