<?php /*

 Composr
 Copyright (c) ocProducts, 2004-2016

 See text/EN/licence.txt for full licencing 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  ocProducts Ltd
 * @package    downloads
 */

require_code('crud_module');

/**
 * Module page class.
 */
class Module_cms_downloads extends Standard_crud_module
{
    public $lang_type = 'DOWNLOAD';
    public $select_name = 'NAME';
    public $permissions_require = 'mid';
    public $permissions_cat_require = 'downloads';
    public $permissions_cat_name = 'category_id';
    public $user_facing = true;
    public $seo_type = 'downloads_download';
    public $upload = 'file';
    public $javascript = 'var url=document.getElementById(\'file__url\'); var form=file_size.form; var crf=function() { var s=url.value!=\'\'; if (form.elements[\'copy_to_server\']) form.elements[\'copy_to_server\'].disabled=!s; if (form.elements[\'file_size\']) form.elements[\'file_size\'].disabled=!s; }; crf(); url.onchange=crf; url.onkeyup=crf; var cost=document.getElementById(\'cost\'); if (cost) { var form=cost.form; var crf2=function() { var s=(cost.value!=\'\') && (cost.value!=\'0\'); if (form.elements[\'submitter_gets_points\']) form.elements[\'submitter_gets_points\'].disabled=!s; }; crf2(); cost.onchange=crf2; cost.onkeyup=crf2; }';
    public $content_type = 'download';
    public $menu_label = 'SECTION_DOWNLOADS';
    public $table = 'download_downloads';
    public $supports_mass_delete = true;

    public $donext_type = null;

    /**
     * Find entry-points available within this module.
     *
     * @param  boolean $check_perms Whether to check permissions.
     * @param  ?MEMBER $member_id The member to check permissions as (null: current user).
     * @param  boolean $support_crosslinks Whether to allow cross links to other modules (identifiable via a full-page-link rather than a screen-name).
     * @param  boolean $be_deferential Whether to avoid any entry-point (or even return null to disable the page in the Sitemap) if we know another module, or page_group, is going to link to that entry-point. Note that "!" and "browse" entry points are automatically merged with container page nodes (likely called by page-groupings) as appropriate.
     * @return ?array A map of entry points (screen-name=>language-code/string or screen-name=>[language-code/string, icon-theme-image]) (null: disabled).
     */
    public function get_entry_points($check_perms = true, $member_id = null, $support_crosslinks = true, $be_deferential = false)
    {
        if ($member_id === null) {
            $member_id = get_member();
        }

        $ret = array(
            'browse' => array('MANAGE_DOWNLOADS', 'menu/rich_content/downloads'),
        );

        $this->cat_crud_module = class_exists('Mx_cms_downloads_cat') ? new Mx_cms_downloads_cat() : new Module_cms_downloads_cat();
        $this->alt_crud_module = class_exists('Mx_cms_downloads_alt') ? new Mx_cms_downloads_alt() : new Module_cms_downloads_alt();

        $ret += parent::get_entry_points();

        if (has_privilege($member_id, 'submit_cat_highrange_content', 'cms_downloads')) {
            $ret += array(
                'add_other' => array('ADD_DOWNLOAD_LICENCE', 'menu/cms/downloads/add_one_licence'),
            );
        }

        if (has_privilege($member_id, 'edit_cat_highrange_content', 'cms_downloads')) {
            $ret += array(
                'edit_other' => array('EDIT_DOWNLOAD_LICENCE', 'menu/cms/downloads/edit_one_licence'),
            );
        }

        if (has_privilege($member_id, 'mass_import', 'cms_downloads')) {
            if (function_exists('ftp_connect')) {
                $ret['import'] = array('FTP_DOWNLOADS', 'menu/_generic_admin/import');
            }

            $ret['import2'] = array('FILESYSTEM_DOWNLOADS', 'menu/_generic_admin/import');
        }

        if ($support_crosslinks) {
            require_code('fields');
            $ret += manage_custom_fields_entry_points('download') + manage_custom_fields_entry_points('download_category');
        }

        return $ret;
    }

    /**
     * Find privileges defined as overridable by this module.
     *
     * @return array A map of privileges that are overridable; privilege to 0 or 1. 0 means "not category overridable". 1 means "category overridable".
     */
    public function get_privilege_overrides()
    {
        require_lang('downloads');
        return array('view_private_content' => 0, 'download' => 1, 'mass_import' => 0, 'submit_cat_midrange_content' => array(0, 'ADD_DOWNLOAD_CATEGORY'), 'edit_cat_midrange_content' => array(0, 'EDIT_DOWNLOAD_CATEGORY'), 'delete_cat_midrange_content' => array(0, 'DELETE_DOWNLOAD_CATEGORY'), 'submit_midrange_content' => array(1, 'ADD_DOWNLOAD'), 'bypass_validation_midrange_content' => array(1, 'BYPASS_DOWNLOAD_VALIDATION'), 'edit_own_midrange_content' => array(1, 'EDIT_OWN_DOWNLOAD'), 'edit_midrange_content' => array(1, 'EDIT_DOWNLOAD'), 'delete_own_midrange_content' => array(1, 'DELETE_OWN_DOWNLOAD'), 'delete_midrange_content' => array(1, 'DELETE_DOWNLOAD'));
    }

    public $title;

    /**
     * Module pre-run function. Allows us to know metadata for <head> before we start streaming output.
     *
     * @param  boolean $top_level Whether this is running at the top level, prior to having sub-objects called.
     * @param  ?ID_TEXT $type The screen type to consider for metadata purposes (null: read from environment).
     * @return ?Tempcode Tempcode indicating some kind of exceptional output (null: none).
     */
    public function pre_run($top_level = true, $type = null)
    {
        $this->cat_crud_module = class_exists('Mx_cms_downloads_cat') ? new Mx_cms_downloads_cat() : new Module_cms_downloads_cat();
        $this->alt_crud_module = class_exists('Mx_cms_downloads_alt') ? new Mx_cms_downloads_alt() : new Module_cms_downloads_alt();
        $GLOBALS['MODULE_CMS_DOWNLOADS'] = $this;

        $type = get_param_string('type', 'browse');

        require_lang('downloads');

        inform_non_canonical_parameter('parent_id');
        inform_non_canonical_parameter('validated');
        inform_non_canonical_parameter('cat');

        set_helper_panel_tutorial('tut_downloads');

        if ($type == 'import' || $type == '_import') {
            $this->title = get_screen_title('FTP_DOWNLOADS');
        }

        if ($type == 'import2' || $type == '_import2') {
            $this->title = get_screen_title('FILESYSTEM_DOWNLOADS');
        }

        if ($type == '_import') {
            breadcrumb_set_parents(array(array('_SELF:_SELF:import', do_lang_tempcode('FTP_DOWNLOADS'))));
            breadcrumb_set_self(do_lang_tempcode('DONE'));
        }

        if ($type == '_import2') {
            breadcrumb_set_parents(array(array('_SELF:_SELF:import', do_lang_tempcode('FILESYSTEM_DOWNLOADS'))));
            breadcrumb_set_self(do_lang_tempcode('DONE'));
        }

        return parent::pre_run($top_level);
    }

    /**
     * Standard crud_module run_start.
     *
     * @param  ID_TEXT $type The type of module execution
     * @return Tempcode The output of the run
     */
    public function run_start($type)
    {
        require_code('downloads');
        require_code('downloads2');
        require_css('downloads');

        // Decide what to do
        if ($type == 'browse') {
            return $this->browse();
        }
        if ($type == 'import') {
            return $this->import_interface();
        }
        if ($type == '_import') {
            return $this->_import();
        }
        if ($type == 'import2') {
            return $this->import_interface2();
        }
        if ($type == '_import2') {
            return $this->_import2();
        }

        return new Tempcode();
    }

    /**
     * The do-next manager for before download content management.
     *
     * @return Tempcode The UI
     */
    public function browse()
    {
        require_code('templates_donext');
        require_code('fields');
        return do_next_manager(get_screen_title('MANAGE_DOWNLOADS'), comcode_lang_string('DOC_DOWNLOADS'),
            array_merge(array(
                has_privilege(get_member(), 'submit_cat_midrange_content', 'cms_downloads') ? array('menu/_generic_admin/add_one_category', array('_SELF', array('type' => 'add_category'), '_SELF'), do_lang('ADD_DOWNLOAD_CATEGORY')) : null,
                has_privilege(get_member(), 'edit_own_cat_midrange_content', 'cms_downloads') ? array('menu/_generic_admin/edit_one_category', array('_SELF', array('type' => 'edit_category'), '_SELF'), do_lang('EDIT_DOWNLOAD_CATEGORY')) : null,
                has_privilege(get_member(), 'submit_cat_midrange_content', 'cms_downloads') ? array('menu/cms/downloads/add_one_licence', array('_SELF', array('type' => 'add_other'), '_SELF'), do_lang('ADD_DOWNLOAD_LICENCE')) : null,
                has_privilege(get_member(), 'edit_own_cat_midrange_content', 'cms_downloads') ? array('menu/cms/downloads/edit_one_licence', array('_SELF', array('type' => 'edit_other'), '_SELF'), do_lang('EDIT_DOWNLOAD_LICENCE')) : null,
                has_privilege(get_member(), 'mass_import') ? array('menu/_generic_admin/import', array('_SELF', array('type' => 'import'), '_SELF'), do_lang('LOAD_FTP_FILES')) : null,
                has_privilege(get_member(), 'mass_import') ? array('menu/_generic_admin/import', array('_SELF', array('type' => 'import2'), '_SELF'), do_lang('LOAD_FILESYSTEM_FILES')) : null,
                has_privilege(get_member(), 'submit_midrange_content', 'cms_downloads') ? array('menu/_generic_admin/add_one', array('_SELF', array('type' => 'add'), '_SELF'), do_lang('ADD_DOWNLOAD')) : null,
                has_privilege(get_member(), 'edit_own_midrange_content', 'cms_downloads') ? array('menu/_generic_admin/edit_one', array('_SELF', array('type' => 'edit'), '_SELF'), do_lang('EDIT_DOWNLOAD')) : null,
            ), manage_custom_fields_donext_link('download'), manage_custom_fields_donext_link('download_category')),
            do_lang('MANAGE_DOWNLOADS')
        );
    }

    /**
     * The UI for importing FTP downloads.
     *
     * @return Tempcode The UI
     */
    public function import_interface()
    {
        if (!function_exists('ftp_connect')) {
            warn_exit(do_lang_tempcode('FTP_NEEDED'));
        }

        check_privilege('mass_import');

        $post_url = build_url(array('page' => '_SELF', 'type' => '_import'), '_SELF');
        $submit_name = do_lang_tempcode('LOAD_FTP_FILES');
        $fields = new Tempcode();
        require_code('form_templates');
        $fields->attach(form_input_line(do_lang_tempcode('FTP_SERVER_URL'), do_lang_tempcode('DESCRIPTION_FTP_SERVER_URL'), 'server_url', 'ftp://ftp.example.com/files/', true));
        $fields->attach(form_input_tree_list(do_lang_tempcode('DESTINATION_PATH'), do_lang_tempcode('DESCRIPTION_DESTINATION_PATH'), 'destination', null, 'choose_download_category', array('addable_filter' => true), true));
        $fields->attach(form_input_tick(do_lang_tempcode('KEEP_SUBFOLDERS'), do_lang_tempcode('DESCRIPTION_KEEP_SUBFOLDERS'), 'subfolders', true));

        return do_template('FORM_SCREEN', array('_GUID' => '3b0fadb204770861ab34a91fc062cf03', 'TITLE' => $this->title, 'HIDDEN' => '', 'TEXT' => paragraph(do_lang_tempcode('DESCRIPTION_LOAD_FTP_FILES')), 'FIELDS' => $fields, 'SUBMIT_ICON' => 'menu___generic_admin__import', 'SUBMIT_NAME' => $submit_name, 'URL' => $post_url));
    }

    /**
     * The actualiser for importing FTP downloads.
     *
     * @return Tempcode The UI
     */
    public function _import()
    {
        $destination = post_param_integer('destination');

        check_privilege('mass_import'/*Not currently scoped to categories, array('downloads', $destination)*/);

        $server_url = post_param_string('server_url');
        $subfolders = post_param_integer('subfolders', 0);

        require_code('tasks');
        return call_user_func_array__long_task(do_lang('FTP_DOWNLOADS'), $this->title, 'import_ftp_downloads', array($destination, $server_url, $subfolders));
    }

    /**
     * The UI for importing filesystem downloads.
     *
     * @return Tempcode The UI
     */
    public function import_interface2()
    {
        check_privilege('mass_import');

        $post_url = build_url(array('page' => '_SELF', 'type' => '_import2'), '_SELF');
        $submit_name = do_lang_tempcode('LOAD_FILESYSTEM_FILES');
        $fields = new Tempcode();
        require_code('form_templates');
        $fields->attach(form_input_line(do_lang_tempcode('DIRECTORY'), do_lang_tempcode('DIRECTORY_RELATIVE_INSTALL'), 'server_path', 'uploads/website_specific/my_downloads/', true));
        $fields->attach(form_input_tree_list(do_lang_tempcode('DESTINATION_PATH'), do_lang_tempcode('DESCRIPTION_DESTINATION_PATH'), 'destination', null, 'choose_download_category', array('addable_filter' => true), true));
        $fields->attach(form_input_tick(do_lang_tempcode('KEEP_SUBFOLDERS'), do_lang_tempcode('DESCRIPTION_KEEP_SUBFOLDERS'), 'subfolders', true));

        return do_template('FORM_SCREEN', array('_GUID' => 'b2a15e705e907f0b20373a80ca8839c6', 'TITLE' => $this->title, 'HIDDEN' => '', 'TEXT' => paragraph(do_lang_tempcode('DESCRIPTION_LOAD_FILESYSTEM_FILES')), 'FIELDS' => $fields, 'SUBMIT_ICON' => 'menu___generic_admin__import', 'SUBMIT_NAME' => $submit_name, 'URL' => $post_url));
    }

    /**
     * The actualiser for importing filesystem downloads.
     *
     * @return Tempcode The UI
     */
    public function _import2()
    {
        $destination = post_param_integer('destination');

        check_privilege('mass_import'/*Not currently scoped to categories, array('downloads', $destination)*/);

        $server_path = post_param_string('server_path');

        $subfolders = post_param_integer('subfolders', 0);

        require_code('tasks');
        return call_user_func_array__long_task(do_lang('FILESYSTEM_DOWNLOADS'), $this->title, 'import_filesystem_downloads', array($destination, $server_path, $subfolders));
    }

    /**
     * Standard crud_module list function.
     *
     * @return array A triple: The tree field (Tempcode), Search URL, Archive URL
     */
    public function create_selection_list_ajax_tree()
    {
        if ($GLOBALS['SITE_DB']->query_select_value('download_downloads', 'COUNT(*)') == 0) {
            inform_exit(do_lang_tempcode('NO_ENTRIES', 'download'));
        }

        $search_url = build_url(array('page' => 'search', 'id' => 'downloads'), get_module_zone('search'));
        $archive_url = build_url(array('page' => 'downloads'), get_module_zone('downloads'));

        $only_owned = has_privilege(get_member(), 'edit_midrange_content', 'cms_downloads') ? null : get_member();
        $tree = form_input_tree_list(do_lang_tempcode('NAME'), '', 'id', null, 'choose_download', array('only_owned' => $only_owned, 'editable_filter' => true), true, null, false, null, has_js() && $this->supports_mass_delete);
        return array($tree, $search_url, $archive_url);
    }

    /**
     * Get Tempcode for a download adding/editing form.
     *
     * @param  ?AUTO_LINK $id The ID of the download (null: new)
     * @param  SHORT_TEXT $name The name of the download
     * @param  ?AUTO_LINK $category_id The download category (null: first)
     * @param  URLPATH $url The URL for the downloadable file
     * @param  SHORT_TEXT $author The name of the author
     * @param  LONG_TEXT $description Description for the download
     * @param  LONG_TEXT $additional_details Supplementary description for the download
     * @param  ?AUTO_LINK $out_mode_id The ID of the download this download is out-moding (null: none)
     * @param  BINARY $validated Whether the download is validated
     * @param  ?BINARY $allow_rating Whether rating is allowed (null: decide statistically, based on existing choices)
     * @param  ?SHORT_INTEGER $allow_comments Whether comments are allowed (0=no, 1=yes, 2=review style) (null: decide statistically, based on existing choices)
     * @param  ?BINARY $allow_trackbacks Whether trackbacks are allowed (null: decide statistically, based on existing choices)
     * @param  LONG_TEXT $notes Notes
     * @param  ?integer $file_size The file size (null: not added yet therefore unknown)
     * @param  integer $cost The point cost of the download
     * @param  BINARY $submitter_gets_points Whether the submitter gets the point cost
     * @param  ?SHORT_TEXT $original_filename The original file name for the file (we can't rely on the one on disk) (null: not added yet therefore unknown)
     * @param  ?AUTO_LINK $licence The licence to use (null: none)
     * @param  integer $default_pic Which image to use for the downloads representative image (counts from 1)
     * @param  URLPATH $url_redirect The URL to redirect
     * @return array A pair: the Tempcode for the visible fields, and the Tempcode for the hidden fields
     */
    public function get_form_fields($id = null, $name = '', $category_id = null, $url = '', $author = '', $description = '', $additional_details = '', $out_mode_id = null, $validated = 1, $allow_rating = null, $allow_comments = null, $allow_trackbacks = null, $notes = '', $file_size = null, $cost = 0, $submitter_gets_points = 1, $original_filename = null, $licence = null, $default_pic = 1, $url_redirect = '')
    {
        list($allow_rating, $allow_comments, $allow_trackbacks) = $this->choose_feedback_fields_statistically($allow_rating, $allow_comments, $allow_trackbacks);

        if ((is_null($id)) && (is_null($category_id))) {
            $category_id = get_param_integer('cat', null);
        }

        if (is_null($category_id)) {
            $num_categories = $GLOBALS['SITE_DB']->query_select_value('download_categories', 'COUNT(*)');
            if ($num_categories == 1) {
                $cat = db_get_first_id(); // Only option!
            }
        }

        $fields = new Tempcode();
        $hidden = new Tempcode();
        require_code('form_templates');
        handle_max_file_size($hidden);
        $fields->attach(form_input_line(do_lang_tempcode('NAME'), do_lang_tempcode('DESCRIPTION_NAME'), 'name', $name, true));
        if (!is_null($original_filename)) {
            $fields->attach(form_input_line(do_lang_tempcode('ORIGINAL_FILENAME'), do_lang_tempcode('DESCRIPTION_ORIGINAL_FILENAME'), 'original_filename', $original_filename, false));
        }
        if ((get_value('no_confirm_url_spec_cats') !== '1') || (is_null($category_id))) {
            $fields->attach(form_input_tree_list(do_lang_tempcode('CATEGORY'), do_lang_tempcode('DESCRIPTION_CATEGORY_TREE', 'download_category'), 'category_id', null, 'choose_download_category', array(), true, strval(is_null($category_id) ? db_get_first_id() : $category_id)));
        } else {
            $hidden->attach(form_input_hidden('category_id', strval($category_id)));
        }

        $fields->attach(form_input_upload_multi_source(do_lang_tempcode('FILE'), '', $hidden, 'file', null, true, $url, false, null, false));

        if (has_privilege(get_member(), 'draw_to_server')) {
            $fields->attach(form_input_tick(do_lang_tempcode('COPY_TO_SERVER'), do_lang_tempcode('DESCRIPTION_COPY_TO_SERVER'), 'copy_to_server', false));
        }
        $fields->attach(form_input_integer(do_lang_tempcode('FILE_SIZE'), do_lang_tempcode('DESCRIPTION_FILE_SIZE'), 'file_size', $file_size, false));
        if (addon_installed('authors')) {
            if ($author == '') {
                $author = $GLOBALS['SITE_DB']->query_select_value_if_there('authors', 'author', array('member_id' => get_member()));
                if (is_null($author)) {
                    $author = $GLOBALS['FORUM_DRIVER']->get_username(get_member());
                }
            }
        }
        if (addon_installed('authors')) {
            $fields->attach(form_input_author(do_lang_tempcode('AUTHOR'), do_lang_tempcode('DESCRIPTION_AUTHOR', 'download'), 'author', $author, true));
        }
        $fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'), do_lang_tempcode('DESCRIPTION_DESCRIPTION'), 'description', $description, false));
        $image_upload_field = form_input_upload(do_lang_tempcode('IMAGE'), do_lang_tempcode('DESCRIPTION_DOWNLOAD_IMAGE_SHORTCUT'), 'img_file', false, null, null, true, str_replace(' ', '', get_option('valid_images')));
        if ((is_null($id)) && (addon_installed('galleries'))) {
            $fields->attach($image_upload_field);
        }
        if ($validated == 0) {
            $validated = get_param_integer('validated', 0);
            if (($validated == 1) && (addon_installed('unvalidated'))) {
                attach_message(do_lang_tempcode('WILL_BE_VALIDATED_WHEN_SAVING'));
            }
        }
        if (has_some_cat_privilege(get_member(), 'bypass_validation_' . $this->permissions_require . 'range_content', null, $this->permissions_cat_require)) {
            if (addon_installed('unvalidated')) {
                $fields->attach(form_input_tick(do_lang_tempcode('VALIDATED'), do_lang_tempcode($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member()) ? 'DESCRIPTION_VALIDATED_SIMPLE' : 'DESCRIPTION_VALIDATED', 'download'), 'validated', $validated == 1));
            }
        }

        $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => '3014367d92010c4ff78684f7c792efa0', 'SECTION_HIDDEN' => $additional_details == '' && is_null($out_mode_id) && ($cost == 0) && is_null($licence), 'TITLE' => do_lang_tempcode('ADVANCED'))));
        $fields->attach(form_input_text_comcode(do_lang_tempcode('ADDITIONAL_INFO'), do_lang_tempcode('DESCRIPTION_ADDITIONAL_INFO'), 'additional_details', $additional_details, false));
        if (!is_null($id)) {
            if (addon_installed('galleries')) {
                $images = $GLOBALS['SITE_DB']->query_select('images', array('thumb_url', 'description'), array('cat' => 'download_' . strval($id)), 'ORDER BY id', 200);
                if (count($images) == 0) {
                    $fields->attach($image_upload_field);
                } else {
                    $selected_path = '';

                    require_code('images');
                    $radios = new Tempcode();
                    foreach ($images as $i => $image) {
                        $selected = ($i + 1) == $default_pic;
                        if ($selected) {
                            $selected_path = $image['thumb_url'];
                        }
                        $radios->attach(form_input_radio_entry('default_pic', strval($i + 1), $selected, do_image_thumb($image['thumb_url'], get_translated_tempcode('images', $image, 'description'), false, false, 50, 50)));
                    }

                    $fields->attach(form_input_radio(do_lang_tempcode('DEFAULT_IMAGE'), do_lang_tempcode('DESCRIPTION_DEFAULT_IMAGE'), 'default_pic', $radios, false, true, $selected_path));
                }
            }
        }
        if (!is_null($id)) {
            $fields->attach(form_input_tree_list(do_lang_tempcode('OUTMODE'), do_lang_tempcode('DESCRIPTION_OUTMODE'), 'out_mode_id', null, 'choose_download', array('shun' => $id), false, is_null($out_mode_id) ? '' : strval($out_mode_id)));
        }
        if (addon_installed('points')) {
            require_lang('points');
            $fields->attach(form_input_integer(do_lang_tempcode('COST'), do_lang_tempcode('DESCRIPTION_DOWNLOAD_COST'), 'cost', $cost, true));
            $fields->attach(form_input_tick(do_lang_tempcode('SUBMITTER_GETS_POINTS'), do_lang_tempcode('DESCRIPTION_SUBMITTER_GETS_POINTS', 'download'), 'submitter_gets_points', $submitter_gets_points == 1));
        } else {
            $hidden->attach(form_input_hidden('cost', ''));
        }
        $fields->attach(form_input_line(do_lang_tempcode('URL_REDIRECT'), do_lang_tempcode('DESCRIPTION_URL_REDIRECT'), 'url_redirect', $url_redirect, false));
        $licences = create_selection_list_download_licences($licence);
        if (!$licences->is_empty()) {
            $licences = create_selection_list_download_licences($licence, true);
            $fields->attach(form_input_list(do_lang_tempcode('LICENCE'), do_lang_tempcode('DESCRIPTION_DOWNLOAD_LICENCE'), 'licence', $licences));
        }

        // Metadata
        require_code('seo2');
        $seo_fields = seo_get_fields($this->seo_type, is_null($id) ? null : strval($id), false);
        require_code('feedback2');
        $feedback_fields = feedback_fields($this->content_type, $allow_rating == 1, $allow_comments == 1, $allow_trackbacks == 1, false, $notes, $allow_comments == 2, false, true, false);
        $fields->attach(metadata_get_fields('download', is_null($id) ? null : strval($id), false, null, ($seo_fields->is_empty() && $feedback_fields->is_empty()) ? METADATA_HEADER_YES : METADATA_HEADER_FORCE));
        if (has_privilege(get_member(), 'edit_meta_fields')) {
            $fields->attach(form_input_integer(do_lang_tempcode('NUM_DOWNLOADS'), do_lang_tempcode('DESCRIPTION_META_NUM_DOWNLOADS'), 'meta_num_downloads', null, false));
        }
        $fields->attach($seo_fields);
        $fields->attach($feedback_fields);

        if (addon_installed('content_privacy')) {
            require_code('content_privacy2');
            if (is_null($id)) {
                $fields->attach(get_privacy_form_fields('download'));
            } else {
                $fields->attach(get_privacy_form_fields('download', strval($id)));
            }
        }

        if (addon_installed('content_reviews')) {
            $fields->attach(content_review_get_fields('download', is_null($id) ? null : strval($id)));
        }

        return array($fields, $hidden);
    }

    /**
     * Standard crud_module submitter getter.
     *
     * @param  ID_TEXT $id The entry for which the submitter is sought
     * @return array The submitter, and the time of submission (null submission time implies no known submission time)
     */
    public function get_submitter($id)
    {
        $rows = $GLOBALS['SITE_DB']->query_select('download_downloads', array('submitter', 'add_date'), array('id' => intval($id)), '', 1);
        if (!array_key_exists(0, $rows)) {
            return array(null, null);
        }
        return array($rows[0]['submitter'], $rows[0]['add_date']);
    }

    /**
     * Standard crud_module cat getter.
     *
     * @param  ID_TEXT $id The entry for which the cat is sought
     * @return mixed The cat
     */
    public function get_cat($id)
    {
        $temp = $GLOBALS['SITE_DB']->query_select_value_if_there('download_downloads', 'category_id', array('id' => intval($id)));
        if (is_null($temp)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'download'));
        }
        return $temp;
    }

    /**
     * Standard crud_module edit form filler.
     *
     * @param  ID_TEXT $_id The entry being edited
     * @return array A tuple of lots of info
     */
    public function fill_in_edit_form($_id)
    {
        $id = intval($_id);

        $myrows = $GLOBALS['SITE_DB']->query_select('download_downloads', array('*'), array('id' => $id), '', 1);
        if (!array_key_exists(0, $myrows)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'download'));
        }
        $myrow = $myrows[0];

        $cat = $myrow['category_id'];

        $ret = $this->get_form_fields($id, get_translated_text($myrow['name']), $cat, $myrow['url'], $myrow['author'], get_translated_text($myrow['description']), get_translated_text($myrow['additional_details']), $myrow['out_mode_id'], $myrow['validated'], $myrow['allow_rating'], $myrow['allow_comments'], $myrow['allow_trackbacks'], $myrow['notes'], $myrow['file_size'], $myrow['download_cost'], $myrow['download_submitter_gets_points'], $myrow['original_filename'], $myrow['download_licence'], $myrow['default_pic'], $myrow['url_redirect']);

        if (has_delete_permission('mid', get_member(), $myrow['submitter'], 'cms_downloads', array('downloads', $cat))) {
            $radios = form_input_radio_entry('delete', '0', true, do_lang_tempcode('LEAVE'));
            $radios->attach(form_input_radio_entry('delete', '1', false, do_lang_tempcode('DELETE_PARTIAL')));
            $radios->attach(form_input_radio_entry('delete', '2', false, do_lang_tempcode('DELETE_FULL')));
            $delete_fields = form_input_radio(do_lang_tempcode('DELETE_STATUS'), do_lang_tempcode('DESCRIPTION_DELETE_STATUS'), 'delete', $radios);
        } else {
            $delete_fields = new Tempcode();
        }

        $ret[2] = $delete_fields;
        $ret[3] = '';
        $ret[4] = true;
        return $ret;
    }

    /**
     * Standard crud_module add actualiser.
     *
     * @return ID_TEXT The ID of the new entry
     */
    public function add_actualisation()
    {
        $category_id = post_param_integer('category_id');
        $name = post_param_string('name');
        $description = post_param_string('description');
        $author = post_param_string('author', get_site_name());
        $url_redirect = post_param_string('url_redirect');
        $_out_mode_id = post_param_string('out_mode_id', '');
        $out_mode_id = ($_out_mode_id == '') ? null : intval($_out_mode_id);
        $_licence = post_param_string('licence', '');
        $licence = ($_licence == '') ? null : intval($_licence);
        $validated = post_param_integer('validated', 0);
        $additional_details = post_param_string('additional_details');
        $allow_trackbacks = post_param_integer('allow_trackbacks', 0);
        $allow_rating = post_param_integer('allow_rating', 0);
        $allow_comments = post_param_integer('allow_comments', 0);
        $notes = post_param_string('notes', '');
        $file_size = post_param_integer('file_size', 0);
        $cost = post_param_integer('cost', 0);
        $submitter_gets_points = post_param_integer('submitter_gets_points', 0);
        $copy_to_server = post_param_integer('copy_to_server', 0);
        if (!has_privilege(get_member(), 'draw_to_server')) {
            $copy_to_server = 0;
        }

        $original_filename = '';
        $thumb_url = null;
        $url = post_param_multi_source_upload('file', 'uploads/downloads', true, false, $original_filename, $thumb_url, CMS_UPLOAD_ANYTHING, $copy_to_server == 1, OBFUSCATE_BIN_SUFFIX);

        $metadata = actual_metadata_get_fields('download', null);
        actual_metadata_get_fields__special($metadata, 'num_downloads', 0);

        $id = add_download($category_id, $name, fixup_protocolless_urls($url), $description, $author, $additional_details, $out_mode_id, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes, $original_filename, $file_size, $cost, $submitter_gets_points, $licence, $metadata['add_time'],/*$metadata['num_downloads']*/0, $metadata['views'], $metadata['submitter'], null, null, '', '', 1, $url_redirect);

        set_url_moniker('download', strval($id));

        if (addon_installed('galleries')) {
            require_code('permissions2');
            set_category_permissions_from_environment('galleries', 'download_' . strval($id));

            $img_urls = get_url('', 'img_file', 'uploads/galleries', 0, CMS_UPLOAD_IMAGE, true);
            if ($img_urls[0] != '') {
                require_code('galleries2');
                add_image('', 'download_' . strval($id), '', $img_urls[0], $img_urls[1], 1, 0, 0, 0, '');
            }
        }

        $this->donext_type = $category_id;

        if ((!is_null(get_param_string('redirect', null))) && (addon_installed('galleries'))) {
            $redirect_url = build_url(array('page' => 'downloads', 'type' => 'entry', 'id' => $id), get_module_zone('downloads'));
            $add_image_url = build_url(array('page' => 'cms_galleries', 'type' => 'add', 'cat' => 'download_' . strval($id), 'redirect' => $redirect_url->evaluate()), get_module_zone('cms_galleries'));
            $this->do_next_description = do_lang_tempcode('DOWNLOAD_ADDED', escape_html($add_image_url->evaluate()));
        }

        if (addon_installed('content_privacy')) {
            require_code('content_privacy2');
            list($privacy_level, $additional_access) = read_privacy_fields();
            save_privacy_form_fields('download', strval($id), $privacy_level, $additional_access);
        }

        if (($validated == 1) || (!addon_installed('unvalidated'))) {
            if ((has_actual_page_access(get_modal_user(), 'downloads')) && (has_category_access(get_modal_user(), 'downloads', strval($category_id)))) {
                $privacy_ok = true;
                if (addon_installed('content_privacy')) {
                    require_code('content_privacy');
                    $privacy_ok = has_privacy_access('download', strval($id), $GLOBALS['FORUM_DRIVER']->get_guest_id());
                }
                if ($privacy_ok) {
                    require_code('activities');
                    syndicate_described_activity('downloads:ACTIVITY_ADD_DOWNLOAD', $name, '', '', '_SEARCH:downloads:entry:' . strval($id), '', '', 'downloads');
                }
            }
        }

        if (addon_installed('content_reviews')) {
            content_review_set('download', strval($id));
        }

        return strval($id);
    }

    /**
     * Standard crud_module edit actualiser.
     *
     * @param  ID_TEXT $_id The entry being edited
     */
    public function edit_actualisation($_id)
    {
        $id = intval($_id);

        $validated = post_param_integer('validated', fractional_edit() ? INTEGER_MAGIC_NULL : 0);

        $category_id = post_param_integer('category_id', fractional_edit() ? INTEGER_MAGIC_NULL : false);
        $name = post_param_string('name');
        $out_mode_id = post_param_integer('out_mode_id', fractional_edit() ? INTEGER_MAGIC_NULL : null);
        $licence = post_param_integer('licence', fractional_edit() ? INTEGER_MAGIC_NULL : null);

        if (!fractional_edit()) {
            $copy_to_server = post_param_integer('copy_to_server', 0);
            if (!has_privilege(get_member(), 'draw_to_server')) {
                $copy_to_server = 0;
            }
            $filename = '';
            $thumb_url = null;
            $url = post_param_multi_source_upload('file', 'uploads/downloads', true, true, $filename, $thumb_url, CMS_UPLOAD_ANYTHING, $copy_to_server == 1, OBFUSCATE_BIN_SUFFIX);
        } else {
            $url = STRING_MAGIC_NULL;
        }

        $description = post_param_string('description', STRING_MAGIC_NULL);
        $author = post_param_string('author', STRING_MAGIC_NULL);
        $url_redirect = post_param_string('url_redirect', STRING_MAGIC_NULL);
        $additional_details = post_param_string('additional_details', STRING_MAGIC_NULL);
        $default_pic = post_param_integer('default_pic', fractional_edit() ? INTEGER_MAGIC_NULL : 1);
        if (addon_installed('galleries')) {
            $img_urls = get_url('', 'img_file', 'uploads/galleries', 0, CMS_UPLOAD_IMAGE, true);
            if ($img_urls[0] != '') {
                require_code('galleries2');
                add_image('', 'download_' . strval($id), '', $img_urls[0], $img_urls[1], 1, 0, 0, 0, '');
                $default_pic = 1;
            }
        }
        $allow_rating = post_param_integer('allow_rating', fractional_edit() ? INTEGER_MAGIC_NULL : 0);
        $allow_comments = post_param_integer('allow_comments', fractional_edit() ? INTEGER_MAGIC_NULL : 0);
        $notes = post_param_string('notes', STRING_MAGIC_NULL);
        $file_size = post_param_integer('file_size', fractional_edit() ? INTEGER_MAGIC_NULL : null);
        $cost = post_param_integer('cost', fractional_edit() ? INTEGER_MAGIC_NULL : 0);
        $submitter_gets_points = post_param_integer('submitter_gets_points', fractional_edit() ? INTEGER_MAGIC_NULL : 0);
        $original_filename = post_param_string('original_filename', STRING_MAGIC_NULL);
        if ((!fractional_edit()) && ($original_filename == '')) {
            $original_filename = $filename;
        }
        $allow_trackbacks = post_param_integer('allow_trackbacks', fractional_edit() ? INTEGER_MAGIC_NULL : 0);

        $this->donext_type = $category_id;

        if (addon_installed('content_privacy')) {
            require_code('content_privacy2');
            list($privacy_level, $additional_access) = read_privacy_fields();
            save_privacy_form_fields('download', strval($id), $privacy_level, $additional_access);
        }

        if (($validated == 1) && ($GLOBALS['SITE_DB']->query_select_value_if_there('download_downloads', 'validated', array('id' => $id)) === 0)) { // Just became validated, syndicate as just added
            $submitter = $GLOBALS['SITE_DB']->query_select_value('download_downloads', 'submitter', array('id' => $id));

            if ((has_actual_page_access(get_modal_user(), 'downloads')) && (has_category_access(get_modal_user(), 'downloads', strval($category_id)))) {
                $privacy_ok = true;
                if (addon_installed('content_privacy')) {
                    require_code('content_privacy');
                    $privacy_ok = has_privacy_access('download', strval($id), $GLOBALS['FORUM_DRIVER']->get_guest_id());
                }
                if ($privacy_ok) {
                    require_code('activities');
                    syndicate_described_activity(($submitter != get_member()) ? 'downloads:ACTIVITY_VALIDATE_DOWNLOAD' : 'downloads:ACTIVITY_ADD_DOWNLOAD', $name, '', '', '_SEARCH:downloads:entry:' . strval($id), '', '', 'downloads', 1, null/*$submitter*/);
                }
            }
        }

        $metadata = actual_metadata_get_fields('download', strval($id));
        actual_metadata_get_fields__special($metadata, 'num_downloads', INTEGER_MAGIC_NULL);

        edit_download($id, $category_id, $name, $url, $description, $author, $additional_details, $out_mode_id, $default_pic, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes, $original_filename, $file_size, $cost, $submitter_gets_points, $licence, post_param_string('meta_keywords', STRING_MAGIC_NULL), post_param_string('meta_description', STRING_MAGIC_NULL), $metadata['edit_time'], $metadata['add_time'], $metadata['views'], $metadata['submitter'], $metadata['num_downloads'], true, $url_redirect);

        if ((addon_installed('galleries')) && (!fractional_edit())) {
            require_code('permissions2');
            set_category_permissions_from_environment('galleries', 'download_' . strval($id));
        }

        if (addon_installed('content_reviews')) {
            content_review_set('download', strval($id));
        }
    }

    /**
     * Standard crud_module delete actualiser.
     *
     * @param  ID_TEXT $_id The entry being deleted
     */
    public function delete_actualisation($_id)
    {
        $id = intval($_id);

        $delete_status = post_param_string('delete', 'leave');
        delete_download($id, !($delete_status == '2'));

        if (addon_installed('content_privacy')) {
            require_code('content_privacy2');
            delete_privacy_form_fields('download', strval($id));
        }
    }

    /**
     * The do-next manager for after download content management (events only).
     *
     * @param  Tempcode $title The title (output of get_screen_title)
     * @param  Tempcode $description Some description to show, saying what happened
     * @param  ?AUTO_LINK $id The ID of whatever was just handled (null: N/A)
     * @return Tempcode The UI
     */
    public function do_next_manager($title, $description, $id)
    {
        return $this->cat_crud_module->_do_next_manager($title, $description, is_null($id) ? null : intval($id), $this->donext_type);
    }
}

/**
 * Module page class.
 */
class Module_cms_downloads_alt extends Standard_crud_module
{
    public $lang_type = 'DOWNLOAD_LICENCE';
    public $select_name = 'TITLE';
    public $permissions_require = 'cat_high';
    public $user_facing = false;
    public $menu_label = 'SECTION_DOWNLOADS';
    public $is_chained_with_parent_browse = true;

    public $donext_type = null;

    /**
     * Standard CRUD-module entry list fetcher.
     *
     * @return Tempcode The list
     */
    public function create_selection_list_entries()
    {
        return create_selection_list_download_licences();
    }

    /**
     * Get Tempcode for a download adding/editing form.
     *
     * @param  ID_TEXT $title The title of the licence
     * @param  LONG_TEXT $text The text of the licence
     * @return array A pair: The input fields, Hidden fields
     */
    public function get_form_fields($title = '', $text = '')
    {
        $fields = new Tempcode();
        require_code('form_templates');
        $fields->attach(form_input_line(do_lang_tempcode('TITLE'), do_lang_tempcode('DESCRIPTION_TITLE'), 'title', $title, true));
        $fields->attach(form_input_text_comcode(do_lang_tempcode('TEXT'), do_lang_tempcode('DESCRIPTION_LICENCE_TEXT'), 'text', $text, true));

        return array($fields, new Tempcode());
    }

    /**
     * Standard crud_module edit form filler.
     *
     * @param  ID_TEXT $_id The entry being edited
     * @return array A pair: The input fields, Hidden fields
     */
    public function fill_in_edit_form($_id)
    {
        $id = intval($_id);

        $myrows = $GLOBALS['SITE_DB']->query_select('download_licences', array('*'), array('id' => $id), '', 1);
        if (!array_key_exists(0, $myrows)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'download_licence'));
        }
        $myrow = $myrows[0];

        return $this->get_form_fields($myrow['l_title'], $myrow['l_text']);
    }

    /**
     * Standard crud_module add actualiser.
     *
     * @return ID_TEXT The ID of the new entry
     */
    public function add_actualisation()
    {
        $id = add_download_licence(post_param_string('title'), post_param_string('text'));

        return strval($id);
    }

    /**
     * Standard crud_module edit actualiser.
     *
     * @param  ID_TEXT $_id The entry being edited
     */
    public function edit_actualisation($_id)
    {
        $id = intval($_id);

        edit_download_licence($id, post_param_string('title'), post_param_string('text'));
    }

    /**
     * Standard crud_module delete actualiser.
     *
     * @param  ID_TEXT $_id The entry being deleted
     */
    public function delete_actualisation($_id)
    {
        $id = intval($_id);

        delete_download_licence($id);
    }

    /**
     * The do-next manager for after download content management (events only).
     *
     * @param  Tempcode $title The title (output of get_screen_title)
     * @param  Tempcode $description Some description to show, saying what happened
     * @param  ?AUTO_LINK $id The ID of whatever was just handled (null: N/A)
     * @return Tempcode The UI
     */
    public function do_next_manager($title, $description, $id)
    {
        return $GLOBALS['MODULE_CMS_DOWNLOADS']->cat_crud_module->_do_next_manager($title, $description, null, null, $id);
    }
}

/**
 * Module page class.
 */
class Module_cms_downloads_cat extends Standard_crud_module
{
    public $lang_type = 'DOWNLOAD_CATEGORY';
    public $select_name = 'NAME';
    public $permissions_require = 'cat_mid';
    public $permission_module = 'downloads';
    public $seo_type = 'downloads_category';
    public $upload = 'image';
    public $content_type = 'download_category';
    public $protect_first = 1;
    public $menu_label = 'SECTION_DOWNLOADS';
    public $is_chained_with_parent_browse = true;

    /**
     * Standard crud_module list function.
     *
     * @return array A triple: The tree field (Tempcode), Search URL, Archive URL
     */
    public function create_selection_list_ajax_tree()
    {
        $search_url = build_url(array('page' => 'search', 'id' => 'download_categories'), get_module_zone('search'));
        $archive_url = build_url(array('page' => 'downloads'), get_module_zone('downloads'));

        $tree = form_input_tree_list(do_lang_tempcode('NAME'), '', 'id', null, 'choose_download_category', array(), true);
        return array($tree, $search_url, $archive_url);
    }

    /**
     * Get Tempcode for a download category adding/editing form.
     *
     * @param  ?AUTO_LINK $id The download ID (null: new)
     * @param  SHORT_TEXT $category The name of the download category
     * @param  ?AUTO_LINK $parent_id The download category parent (null: use root)
     * @param  LONG_TEXT $description Description
     * @param  LONG_TEXT $notes Notes
     * @param  ?AUTO_LINK $category_id The ID of the download category (null: we're adding, not editing)
     * @param  URLPATH $rep_image The rep-image for the download category
     * @return array A pair: the Tempcode for the visible fields, and the Tempcode for the hidden fields
     */
    public function get_form_fields($id = null, $category = '', $parent_id = null, $description = '', $notes = '', $category_id = -1, $rep_image = '')
    {
        if ((is_null($parent_id)) && ($category_id == -1)) {
            $parent_id = get_param_integer('parent_id', -1);
            if ($parent_id == -1) {
                $parent_id = db_get_first_id();
            }
        }

        $fields = new Tempcode();
        $hidden = new Tempcode();

        require_code('form_templates');

        $fields->attach(form_input_line(do_lang_tempcode('NAME'), do_lang_tempcode('DESCRIPTION_NAME'), 'category', $category, true));

        if (!is_null($parent_id)) {
            $fields->attach(form_input_tree_list(do_lang_tempcode('PARENT'), do_lang_tempcode('DESCRIPTION_PARENT', 'download_category'), 'parent_id', null, 'choose_download_category', array(), true, strval($parent_id)));
        }

        $fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'), do_lang_tempcode('DESCRIPTION_DESCRIPTION'), 'description', $description, false));

        if (get_option('enable_staff_notes') == '1') {
            $fields->attach(form_input_text(do_lang_tempcode('NOTES'), do_lang_tempcode('DESCRIPTION_NOTES'), 'notes', $notes, false));
        }

        $fields->attach(form_input_upload_multi_source(do_lang_tempcode('REPRESENTATIVE_IMAGE'), do_lang_tempcode('DESCRIPTION_REPRESENTATIVE_IMAGE', 'download_category'), $hidden, 'image', null, false, $rep_image));

        $fields->attach(metadata_get_fields('download_category', is_null($id) ? null : strval($id)));
        require_code('seo2');
        $fields->attach(seo_get_fields($this->seo_type, is_null($id) ? null : strval($id), false));

        if (addon_installed('content_reviews')) {
            $fields->attach(content_review_get_fields('download_category', is_null($id) ? null : strval($id)));
        }

        // Permissions
        $fields->attach($this->get_permission_fields(($category_id == -1) ? null : strval($category_id), null, ($category == '')));

        return array($fields, $hidden);
    }

    /**
     * Standard crud_module edit form filler.
     *
     * @param  ID_TEXT $id The entry being edited
     * @return array A pair: The input fields, Hidden fields
     */
    public function fill_in_edit_form($id)
    {
        $category_id = intval($id);

        $rows = $GLOBALS['SITE_DB']->query_select('download_categories', array('*'), array('id' => $category_id), '', 1);
        if (!array_key_exists(0, $rows)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'download_category'));
        }
        $myrow = $rows[0];

        return $this->get_form_fields($category_id, get_translated_text($myrow['category']), $myrow['parent_id'], get_translated_text($myrow['description']), $myrow['notes'], $category_id, $myrow['rep_image']);
    }

    /**
     * Standard crud_module add actualiser.
     *
     * @return ID_TEXT The entry added
     */
    public function add_actualisation()
    {
        $category = post_param_string('category');

        $parent_id = post_param_integer('parent_id');

        $description = post_param_string('description');

        $notes = post_param_string('notes', '');

        require_code('themes2');
        $rep_image = resize_rep_image(post_param_image('image', 'uploads/repimages', null, false));

        $metadata = actual_metadata_get_fields('download_category', null);

        $category_id = add_download_category($category, $parent_id, $description, $notes, $rep_image, null, $metadata['add_time']);

        set_url_moniker('download_category', strval($category_id));

        $this->set_permissions(strval($category_id));

        if (addon_installed('content_reviews')) {
            content_review_set('download_category', strval($category_id));
        }

        return strval($category_id);
    }

    /**
     * Standard crud_module edit actualiser.
     *
     * @param  ID_TEXT $id The entry being edited
     */
    public function edit_actualisation($id)
    {
        $category_id = intval($id);

        $category = post_param_string('category');

        $parent_id = post_param_integer('parent_id', fractional_edit() ? INTEGER_MAGIC_NULL : null);

        $description = post_param_string('description', STRING_MAGIC_NULL);

        $notes = post_param_string('notes', STRING_MAGIC_NULL);

        if (!fractional_edit()) {
            require_code('themes2');
            $rep_image = resize_rep_image(post_param_image('image', 'uploads/repimages', null, false, true));
        } else {
            $rep_image = STRING_MAGIC_NULL;
        }

        $metadata = actual_metadata_get_fields('download_category', strval($category_id));

        edit_download_category($category_id, $category, $parent_id, $description, $notes, $rep_image, post_param_string('meta_keywords', STRING_MAGIC_NULL), post_param_string('meta_description', STRING_MAGIC_NULL), $metadata['add_time']);
        if (!fractional_edit()) {
            $this->set_permissions(strval($category_id));
        }

        if (addon_installed('content_reviews')) {
            content_review_set('download_category', strval($category_id));
        }
    }

    /**
     * Standard crud_module delete actualiser.
     *
     * @param  ID_TEXT $id The entry being deleted
     */
    public function delete_actualisation($id)
    {
        $category_id = intval($id);

        check_delete_permission('cat_high', null);

        delete_download_category($category_id);
    }

    /**
     * The do-next manager for after download content management (event types only).
     *
     * @param  Tempcode $title The title (output of get_screen_title)
     * @param  Tempcode $description Some description to show, saying what happened
     * @param  ?AUTO_LINK $id The ID of whatever was just handled (null: N/A)
     * @return Tempcode The UI
     */
    public function do_next_manager($title, $description, $id)
    {
        return $this->_do_next_manager($title, $description, null, is_null($id) ? null : intval($id));
    }

    /**
     * The do-next manager for after download content management.
     *
     * @param  Tempcode $title The title (output of get_screen_title)
     * @param  Tempcode $description Some description to show, saying what happened
     * @param  ?AUTO_LINK $id The ID of whatever was just handled (null: delete/NA)
     * @param  ?AUTO_LINK $category_id The category ID we were working in (null: deleted/NA)
     * @param  ?AUTO_LINK $download_licence_id The download licence ID we were working in (null: deleted/NA)
     * @return Tempcode The UI
     */
    public function _do_next_manager($title, $description, $id = null, $category_id = null, $download_licence_id = null)
    {
        require_code('templates_donext');

        if ((is_null($id)) && (is_null($category_id))) {
            return do_next_manager($title, $description,
                null,
                null,
                /* TYPED-ORDERED LIST OF 'LINKS'    */
                array('_SELF', array('type' => 'add'), '_SELF'), // Add one
                null, // Edit this
                has_privilege(get_member(), 'edit_own_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'edit'), '_SELF') : null, // Edit one
                null, // View this
                array('downloads', array('type' => 'browse'), get_module_zone('downloads')), // View archive
                null, // Add to category
                has_privilege(get_member(), 'submit_cat_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'add_category'), '_SELF') : null, // Add one category
                has_privilege(get_member(), 'edit_own_cat_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'edit_category'), '_SELF') : null, // Edit one category
                null, // Edit this category
                null, // View this category
                /* SPECIALLY TYPED 'LINKS' */
                array(
                    has_privilege(get_member(), 'mass_import', 'cms_downloads') ? array('menu/_generic_admin/import', array('_SELF', array('type' => 'import'), '_SELF'), do_lang('LOAD_FTP_FILES')) : null,
                ),
                array(),
                array(
                    has_privilege(get_member(), 'submit_cat_highrange_content', 'cms_downloads') ? array('menu/cms/downloads/add_one_licence', array('_SELF', array('type' => 'add_other'), '_SELF'), do_lang('ADD_DOWNLOAD_LICENCE')) : null,
                    has_privilege(get_member(), 'edit_cat_highrange_content', 'cms_downloads') ? array('menu/cms/downloads/edit_one_licence', array('_SELF', array('type' => 'edit_other'), '_SELF'), do_lang('EDIT_DOWNLOAD_LICENCE')) : null
                ),
                do_lang('LICENCES'),
                null,
                null,
                null,
                'download',
                'download_category'
            );
        }

        $special_links = array(has_privilege(get_member(), 'mass_import', 'cms_downloads') ? array('menu/_generic_admin/import', array('_SELF', array('type' => 'import'), '_SELF'), do_lang('LOAD_FTP_FILES')) : null);

        if ((addon_installed('galleries')) && (!is_null($id))) {
            require_lang('galleries');
            $special_links[] = (has_privilege(get_member(), 'submit_midrange_content', 'cms_galleries', array('galleries', 'download_' . strval($id))) && (!is_null($id))) ? array('menu/cms/galleries/add_one_image', array('cms_galleries', array('type' => 'add', 'cat' => 'download_' . strval($id)), get_module_zone('cms_galleries'))) : null;
        }

        return do_next_manager($title, $description,
            null,
            null,
            /* TYPED-ORDERED LIST OF 'LINKS'  */
            array('_SELF', array('type' => 'add', 'cat' => $category_id), '_SELF'), // Add one
            (is_null($id) || (!has_privilege(get_member(), 'edit_own_midrange_content', 'cms_downloads', array('downloads', $category_id)))) ? null : array('_SELF', array('type' => '_edit', 'id' => $id), '_SELF'), // Edit this
            has_privilege(get_member(), 'edit_own_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'edit'), '_SELF') : null, // Edit one
            is_null($id) ? null : array('downloads', array('type' => 'entry', 'id' => $id), get_module_zone('downloads')), // View this
            array('downloads', array('type' => 'browse'), get_module_zone('downloads')), // View archive
            null, // Add to category
            has_privilege(get_member(), 'submit_cat_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'add_category'), '_SELF') : null, // Add one category
            has_privilege(get_member(), 'edit_own_cat_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => 'edit_category'), '_SELF') : null, // Edit one category
            has_privilege(get_member(), 'edit_own_cat_midrange_content', 'cms_downloads') ? array('_SELF', array('type' => '_edit_category', 'id' => $category_id), '_SELF') : null, // Edit this category
            array('downloads', array('type' => 'browse', 'id' => ($category_id == db_get_first_id()) ? null : $category_id), get_module_zone('downloads')), // View this category
            /* SPECIALLY TYPED 'LINKS' */
            $special_links,
            array(),
            array(
                has_privilege(get_member(), 'submit_cat_highrange_content', 'cms_downloads') ? array('menu/cms/downloads/add_one_licence', array('_SELF', array('type' => 'add_other'), '_SELF'), do_lang('ADD_DOWNLOAD_LICENCE')) : null,
                has_privilege(get_member(), 'edit_cat_highrange_content', 'cms_downloads') ? array('menu/cms/downloads/edit_one_licence', array('_SELF', array('type' => 'edit_other'), '_SELF'), do_lang('EDIT_DOWNLOAD_LICENCE')) : null
            ),
            do_lang('LICENCES'),
            null,
            null,
            null,
            'download',
            'download_category'
        );
    }
}
