<?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    core_zone_editor
 */

/**
 * Module page class.
 */
class Module_admin_zones
{
    /**
     * Find details of the module.
     *
     * @return ?array Map of module info (null: module is disabled).
     */
    public function info()
    {
        $info = array();
        $info['author'] = 'Chris Graham';
        $info['organisation'] = 'ocProducts';
        $info['hacked_by'] = null;
        $info['hack_version'] = null;
        $info['version'] = 2;
        $info['locked'] = false;
        return $info;
    }

    /**
     * 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)
    {
        $ret = array(
            'browse' => array('ZONES', 'menu/adminzone/structure/zones/zones'),
            'add' => array('ADD_ZONE', 'menu/_generic_admin/add_one'),
            'edit' => array('EDIT_ZONE', 'menu/_generic_admin/edit_one'),
        );

        if (!$be_deferential) {
            $ret['editor'] = array('ZONE_EDITOR', 'menu/adminzone/structure/zones/zone_editor');
        }

        return $ret;
    }

    /**
     * Uninstall the module.
     */
    public function uninstall()
    {
        /* We don't really want to throw away on-disk data on reinstalls
        $zones = find_all_zones(true);
        require_code('files');
        foreach ($zones as $zone) {
            //if (!in_array($zone, array('', 'docs', 'adminzone', 'collaboration', 'forum', 'cms', 'site'))) {
            //    deldir_contents(get_file_base() . '/' . $zone, true);
            //}
            $langs = find_all_langs(true);
            foreach (array_keys($langs) as $lang) {
                $path = get_custom_file_base() . (($zone == '') ? '' : '/') . $zone . '/pages/comcode_custom/' . $lang;
                if (file_exists($path)) {
                    deldir_contents($path, true);
                }
                $path = get_custom_file_base() . (($zone == '') ? '' : '/') . $zone . '/pages/html_custom/' . $lang;
                if (file_exists($path)) {
                    deldir_contents($path, true);
                }
            }
            // deldir_contents(get_file_base() . (($zone == '') ? '' : '/') . $zone . '/pages/minimodules_custom', true);
            // modules_custom purposely left
        }
        */
    }

    public $title;
    public $id;
    public $nice_zone_name;

    /**
     * Module pre-run function. Allows us to know metadata for <head> before we start streaming output.
     *
     * @return ?Tempcode Tempcode indicating some kind of exceptional output (null: none).
     */
    public function pre_run()
    {
        $type = get_param_string('type', 'browse');

        require_lang('zones');

        if ($type == '_editor') {
            attach_to_screen_header(make_string_tempcode('<base target="_blank" />'));
        }

        if ($type != 'editor' && $type != '_editor' && $type != '__editor') {
            set_helper_panel_tutorial('tut_structure');
        }

        if ($type == 'editor') {
            breadcrumb_set_self(do_lang_tempcode('CHOOSE'));
        }

        if ($type == '_editor') {
            $id = get_param_string('id', ''); // '' needed for URL Schemes
            if ($id == '/') {
                $id = '';
            }

            $nice_zone_name = ($id == '') ? do_lang('_WELCOME') : $id;

            breadcrumb_set_parents(array(array('_SELF:_SELF:browse', do_lang_tempcode('ZONES')), array('_SELF:_SELF:editor', do_lang_tempcode('ZONE'))));
            breadcrumb_set_self($nice_zone_name);

            $this->title = get_screen_title('_ZONE_EDITOR', true, array(escape_html($nice_zone_name)));

            $this->id = $id;
            $this->nice_zone_name = $nice_zone_name;
        }

        if ($type == '__editor') {
            $this->title = get_screen_title('ZONE_EDITOR');
        }

        if ($type == 'add') {
            breadcrumb_set_parents(array(array('_SELF:_SELF:browse', do_lang_tempcode('ZONES'))));

            $this->title = get_screen_title('ADD_ZONE');
        }

        if ($type == '_add') {
            $this->title = get_screen_title('ADD_ZONE');
        }

        if ($type == 'edit') {
            breadcrumb_set_parents(array(array('_SELF:_SELF:browse', do_lang_tempcode('ZONES'))));
            breadcrumb_set_self(do_lang_tempcode('ZONE'));

            $this->title = get_screen_title('EDIT_ZONE');
        }

        if ($type == '_edit') {
            breadcrumb_set_parents(array(array('_SELF:_SELF:browse', do_lang_tempcode('ZONES')), array('_SELF:_SELF:edit_zone', do_lang_tempcode('ZONE'))));

            $this->title = get_screen_title('EDIT_ZONE');
        }

        if ($type == '__edit') {
            $delete = post_param_integer('delete', 0);
            if ($delete == 1) {
                $this->title = get_screen_title('DELETE_ZONE');
            } else {
                $this->title = get_screen_title('EDIT_ZONE');
            }
        }

        return null;
    }

    /**
     * Execute the module.
     *
     * @return Tempcode The result of execution.
     */
    public function run()
    {
        require_code('zones2');
        require_code('zones3');

        require_css('zone_editor');

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

        if ($type == 'browse') {
            return $this->browse();
        }
        if ($type == 'editor') {
            return $this->editor();
        }
        if ($type == '_editor') {
            return $this->_editor();
        }
        if ($type == '__editor') {
            return $this->__editor();
        }
        if ($type == 'add') {
            return $this->add_zone();
        }
        if ($type == '_add') {
            return $this->_add_zone();
        }
        if ($type == 'edit') {
            return $this->edit_zone();
        }
        if ($type == '_edit') {
            return $this->_edit_zone();
        }
        if ($type == '__edit') {
            return $this->__edit_zone();
        }

        return $this->browse();
    }

    /**
     * The do-next manager for before content management.
     *
     * @return Tempcode The UI
     */
    public function browse()
    {
        require_code('templates_donext');
        return do_next_manager(get_screen_title('ZONES'), comcode_lang_string('DOC_ZONES'),
            array(
                array('menu/_generic_admin/add_one', array('_SELF', array('type' => 'add'), '_SELF'), do_lang('ADD_ZONE')),
                array('menu/_generic_admin/edit_one', array('_SELF', array('type' => 'edit'), '_SELF'), do_lang('EDIT_ZONE')),
            ),
            do_lang('ZONES')
        );
    }

    /**
     * The UI to choose a zone to edit using the zone editor.
     *
     * @return Tempcode The UI
     */
    public function editor()
    {
        return $this->edit_zone('_editor', get_screen_title('ZONE_EDITOR'));
    }

    /**
     * The UI for the zone editor.
     *
     * @return Tempcode The UI
     */
    public function _editor()
    {
        require_code('input_filter_2');
        modsecurity_workaround_enable();

        $id = $this->id;
        $nice_zone_name = $this->nice_zone_name;

        $lang = choose_language($this->title, true);
        if (is_object($lang)) {
            return $lang;
        }

        require_javascript('zone_editor');
        require_javascript('ajax');
        require_javascript('posting');
        require_javascript('editing');
        require_javascript('checking');
        require_code('form_templates');
        require_lang('comcode');

        if (!has_js()) {
            // Send them to the page permissions screen
            $url = build_url(array('page' => '_SELF', 'type' => 'edit'), '_SELF');
            return redirect_screen($this->title, $url, do_lang_tempcode('NO_JS_ADVANCED_SCREEN_ZONE_EDITOR'));
        }

        // After completion prep/relay
        $_default_redirect = build_url(array('page' => ''), $id);
        $default_redirect = $_default_redirect->evaluate();
        $post_url = build_url(array('page' => '_SELF', 'type' => '__editor', 'lang' => $lang, 'redirect' => get_param_string('redirect', $default_redirect), 'id' => $id), '_SELF');

        // Zone editing stuff
        $rows = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => $id), '', 1);
        if (!array_key_exists(0, $rows)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'zone'));
        }
        $row = $rows[0];
        $header_text = get_translated_text($row['zone_header_text'], null, $lang);
        $default_page = $row['zone_default_page'];
        list($fields, ,) = $this->get_form_fields(true, get_translated_text($row['zone_title'], null, $lang), $default_page, $header_text, $row['zone_theme'], $row['zone_require_session'], $id);

        // Page editing stuff
        $editor = array();
        foreach (array('panel_left', $default_page, 'panel_right') as $i => $for) {
            $page_info = _request_page($for, $id, null, $lang);
            if ($page_info === false) {
                $page_info = array('COMCODE_CUSTOM', $id, $for, $lang);
            }
            $is_comcode = false;
            $redirecting_to = null;
            $current_for = $for;
            $pure = false;
            switch ($page_info[0]) {
                case 'COMCODE_CUSTOM_PURE':
                    $pure = true;
                case 'COMCODE':
                case 'COMCODE_CUSTOM':
                    $is_comcode = true;
                    $type = do_lang_tempcode('COMCODE_PAGE');
                    break;
                case 'HTML':
                case 'HTML_CUSTOM':
                    $type = protect_from_escaping(escape_html('HTML'));
                    break;
                case 'MODULES':
                case 'MODULES_CUSTOM':
                    $type = do_lang_tempcode('MODULE');
                    break;
                case 'MINIMODULES':
                case 'MINIMODULES_CUSTOM':
                    $type = do_lang_tempcode('MINIMODULE');
                    break;
                case 'REDIRECT':
                    $type = do_lang_tempcode('REDIRECT_PAGE_TO', escape_html($page_info[1]['r_to_zone']), escape_html($page_info[1]['r_to_page']));
                    $redirecting_to = $page_info[1]['r_to_zone'];
                    $current_for = $page_info[1]['r_to_page'];

                    $page_info = _request_page($current_for, $redirecting_to, null, $lang);
                    if ($page_info !== false) {
                        switch ($page_info[0]) {
                            case 'COMCODE_CUSTOM_PURE':
                                $pure = true;
                            case 'COMCODE':
                            case 'COMCODE_CUSTOM':
                                $is_comcode = true;
                                break;
                        }
                    }
                    break;
                default:
                    $type = do_lang_tempcode('UNKNOWN');
                    break;
            }
            $class = '';
            $w = false;
            $current_zone = is_null($redirecting_to) ? $id : $redirecting_to;
            $default_parsed = null;
            if ($is_comcode) {
                $full_path = zone_black_magic_filterer((($page_info[0] == 'comcode' || $pure) ? get_file_base() : get_custom_file_base()) . '/' . $current_zone . '/pages/' . strtolower($page_info[0]) . '/' . $lang . '/' . $current_for . '.txt');
                if (!file_exists($full_path)) {
                    $full_path = zone_black_magic_filterer((($page_info[0] == 'comcode' || $pure) ? get_file_base() : get_custom_file_base()) . '/' . $current_zone . '/pages/' . strtolower($page_info[0]) . '/' . get_site_default_lang() . '/' . $current_for . '.txt');
                }
                if (file_exists($full_path)) {
                    $comcode = cms_file_get_contents_safe($full_path);

                    if (strpos($full_path, '_custom/') === false) {
                        global $LANG_FILTER_OB;
                        $comcode = $LANG_FILTER_OB->compile_time(null, $comcode, $lang);
                    }

                    $default_parsed = comcode_to_tempcode($comcode, null, false, null, null, null, true);
                } else {
                    $comcode = '';
                }

                $edit_url = build_url(array('page' => 'cms_comcode_pages', 'type' => '_edit', 'page_link' => $current_zone . ':' . $current_for), get_module_zone('cms_comcode_pages'));

                // WYSIWYG?
                require_javascript('editing');
                $w = (has_js()) && (browser_matches('wysiwyg') && (strpos($comcode, '{$,page hint: no_wysiwyg}') === false));
                attach_wysiwyg();
                if ($w) {
                    $class .= ' wysiwyg';
                }
            } else { // Can't edit a non-Comcode page in the zone editor
                $comcode = null;
                $edit_url = new Tempcode();
            }

            $field_name = 'edit_' . $for . '_textarea';
            if ($i == 1) {
                $settings = $fields;
                $comcode_editor = get_comcode_editor($field_name);
            } else {
                $settings = null;
                $comcode_editor = new Tempcode();
                $button = 'block';
                $comcode_editor->attach(do_template('COMCODE_EDITOR_BUTTON', array('_GUID' => '0acc5dcf299325d0cf55871923148a54', 'DIVIDER' => false, 'IS_POSTING_FIELD' => false, 'FIELD_NAME' => $field_name, 'TITLE' => do_lang_tempcode('INPUT_COMCODE_' . $button), 'B' => $button)));
                $button = 'comcode';
                $comcode_editor->attach(do_template('COMCODE_EDITOR_BUTTON', array('_GUID' => '1acc5dcf299325d0cf55871923148a54', 'DIVIDER' => false, 'IS_POSTING_FIELD' => false, 'FIELD_NAME' => $field_name, 'TITLE' => do_lang_tempcode('INPUT_COMCODE_' . $button), 'B' => $button)));
            }

            if (substr($page_info[0], 0, 6) == 'MODULE') {
                $preview = null;
            } else {
                require_code('urls2');
                list($old_get, $old_zone, $old_current_script) = set_execution_context(
                    array('page' => $for),
                    $id
                );

                $preview = request_page($for, false, $id, null, true);

                // Get things back to prior state
                set_execution_context(
                    $old_get,
                    $old_zone,
                    $old_current_script,
                    false
                );
            }
            if (!is_null($preview)) {
                $_preview = $preview->evaluate();
                if ((!$is_comcode) || (strpos($comcode, '<') !== false)) { // Save RAM by only doing this if needed
                    require_code('xhtml');
                    $_preview = xhtmlise_html($_preview, true); // Fix potential errors by passing it through our XHTML fixer functions
                } else {
                    $new = $_preview;
                    if (preg_replace('#\s+#', '', $new) != preg_replace('#\s+#', '', $_preview)) { // If it was changed there was probably an error
                        $_preview = $new;
                        $_preview .= do_lang('BROKEN_XHTML_FIXED');
                    }
                }


                if ($GLOBALS['XSS_DETECT']) {
                    ocp_mark_as_escaped($_preview);
                }
            } else {
                $_preview = null;
            }

            $is_panel = (substr($for, 0, 6) == 'panel_');

            if (($redirecting_to !== null) && ($redirecting_to != $id)) {
                $zone_list = null;
            } else {
                require_code('zones3');
                $zone_list = ($for == $current_for) ? create_selection_list_zones($redirecting_to, array($id)) : new Tempcode(); // not simple so leave field out
            }

            $editor[$for] = static_evaluate_tempcode(do_template('ZONE_EDITOR_PANEL', array(
                '_GUID' => 'f32ac84fe18b90497acd4afa27698bf0',
                'DEFAULT_PARSED' => $default_parsed,
                'CLASS' => $class,
                'CURRENT_ZONE' => $current_zone,
                'ZONES' => $zone_list,
                'COMCODE' => $comcode,
                'PREVIEW' => $_preview,
                'ZONE' => $id,
                'ID' => $for,
                'IS_PANEL' => $is_panel,
                'TYPE' => $type,
                'EDIT_URL' => $edit_url,
                'SETTINGS' => $settings,
                'COMCODE_EDITOR' => $comcode_editor,
            )));
        }

        list($warning_details, $ping_url) = handle_conflict_resolution($id);

        return do_template('ZONE_EDITOR_SCREEN', array(
            '_GUID' => '3cb1aab6b16444484e82d22f2c8f1e9a',
            'ID' => $id,
            'LANG' => $lang,
            'PING_URL' => $ping_url,
            'WARNING_DETAILS' => $warning_details,
            'TITLE' => $this->title,
            'URL' => $post_url,
            'LEFT_EDITOR' => $editor['panel_left'],
            'RIGHT_EDITOR' => $editor['panel_right'],
            'MIDDLE_EDITOR' => $editor[$default_page],
        ));
    }

    /**
     * The actualiser to edit a zone (via zone editor).
     *
     * @return Tempcode The UI
     */
    public function __editor()
    {
        require_code('input_filter_2');
        modsecurity_workaround_enable();

        $lang = choose_language($this->title, true);
        if (is_object($lang)) {
            return $lang;
        }

        $id = get_param_string('id', '');

        // Edit settings
        $_title = post_param_string('title');
        $default_page = post_param_string('default_page');
        $header_text = post_param_string('header_text');
        $theme = post_param_string('theme');
        $require_session = post_param_integer('require_session', 0);
        actual_edit_zone($id, $_title, $default_page, $header_text, $theme, $require_session, $id);
        if ($id != '') {
            $this->set_permissions($id);
        }

        // Edit pages
        foreach (array('panel_left', 'start', 'panel_right') as $for) {
            $redirect = post_param_string('redirect_' . $for, null);
            if (!is_null($redirect)) {
                if (addon_installed('redirects_editor')) {
                    $GLOBALS['SITE_DB']->query_delete('redirects', array(
                        'r_from_page' => $for,
                        'r_from_zone' => $id,
                    ), '', 1);

                    if ($redirect != $id) {
                        $GLOBALS['SITE_DB']->query_insert('redirects', array(
                            'r_from_page' => $for,
                            'r_from_zone' => $id,
                            'r_to_page' => $for,
                            'r_to_zone' => $redirect,
                            'r_is_transparent' => 1,
                        ), false, true); // Avoid problem when same key entered twice
                    } else {
                        $redirect = null;
                    }
                } else {
                    $redirect = null;
                }
            }

            $comcode = post_param_string($for, null);
            if (!is_null($comcode)) {
                // Where to save to
                $full_path = zone_black_magic_filterer(get_custom_file_base() . (((is_null($redirect) ? $id : $redirect) == '') ? '' : '/') . (is_null($redirect) ? $id : $redirect) . '/pages/comcode_custom/' . $lang . '/' . $for . '.txt');

                // Store revision
                if (addon_installed('actionlog')) {
                    require_code('revisions_engine_files');
                    $revision_engine = new RevisionEngineFiles();
                    list(, , $existing_path) = find_comcode_page($lang, $for, $id);
                    if ($existing_path != '') {
                        $revision_engine->add_revision(dirname($existing_path), $for, 'txt', file_get_contents($existing_path), filemtime($existing_path));
                    }
                }

                // Save
                require_code('files');
                cms_file_put_contents_safe($full_path, $comcode, FILE_WRITE_FIX_PERMISSIONS | FILE_WRITE_SYNC_FILE);

                // De-cache
                $caches = $GLOBALS['SITE_DB']->query_select('cached_comcode_pages', array('string_index'), array('the_zone' => is_null($redirect) ? $id : $redirect, 'the_page' => $for));
                foreach ($caches as $cache) {
                    delete_lang($cache['string_index']);
                }
                $GLOBALS['SITE_DB']->query_delete('cached_comcode_pages', array('the_zone' => is_null($redirect) ? $id : $redirect, 'the_page' => $for));
            }
        }

        erase_persistent_cache();

        // Redirect
        $url = get_param_string('redirect');
        return redirect_screen($this->title, $url, do_lang_tempcode('SUCCESS'));
    }

    /**
     * Get Tempcode for a zone adding/editing form.
     *
     * @param  boolean $in_zone_editor Whether the zone editor will be used
     * @param  SHORT_TEXT $title The zone title
     * @param  ID_TEXT $default_page The zones default page
     * @param  SHORT_TEXT $header_text The header text
     * @param  ?ID_TEXT $theme The theme (null: no override)
     * @param  BINARY $require_session Whether the zone requires a session for pages to be used
     * @param  ?ID_TEXT $zone Name of the zone (null: unknown)
     * @return array A tuple: The Tempcode for the fields, hidden fields, and extra JavaScript
     */
    public function get_form_fields($in_zone_editor = false, $title = '', $default_page = 'start', $header_text = '', $theme = null, $require_session = 0, $zone = null)
    {
        require_lang('permissions');

        $javascript = "
            var zone=document.getElementById('new_zone');
            if (!zone) zone=document.getElementById('zone');
            if (zone)
            {
                zone.onblur=function() {
                    var title=document.getElementById('title');
                    if (title.value=='') title.value=zone.value.substr(0,1).toUpperCase()+zone.value.substring(1,zone.value.length).replace(/\_/g,' ');
                }
            }
        ";

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

        require_code('form_templates');
        $fields .= static_evaluate_tempcode(form_input_line(do_lang_tempcode('TITLE'), do_lang_tempcode('DESCRIPTION_TITLE'), 'title', $title, true));
        $fields .= static_evaluate_tempcode(form_input_line(do_lang_tempcode('DEFAULT_PAGE'), do_lang_tempcode('DESCRIPTION_DEFAULT_PAGE'), 'default_page', $default_page, true));
        $fields .= static_evaluate_tempcode(form_input_line(do_lang_tempcode('HEADER_TEXT'), do_lang_tempcode('DESCRIPTION_HEADER_TEXT'), 'header_text', $header_text, false));
        $list = '';

        // Theme
        require_code('themes2');
        $entries = create_selection_list_themes($theme, false, true);
        $theme_field = form_input_list(do_lang_tempcode('THEME'), do_lang_tempcode((get_forum_type() == 'cns') ? '_DESCRIPTION_THEME_CNS' : '_DESCRIPTION_THEME', get_default_theme_name()), 'theme', $entries);
        $is_normal_zone = ($zone !== 'adminzone') && ($zone !== 'cms');
        if ($is_normal_zone) {
            $fields .= static_evaluate_tempcode($theme_field);
        }

        $fields .= static_evaluate_tempcode(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => 'b997e901934b59fa72c944e0ce6fc1b0', 'SECTION_HIDDEN' => true, 'TITLE' => do_lang_tempcode('ADVANCED'))));
        $fields .= static_evaluate_tempcode(form_input_tick(do_lang_tempcode('REQUIRE_SESSION'), do_lang_tempcode('DESCRIPTION_REQUIRE_SESSION'), 'require_session', ($require_session == 1)));
        if (!$is_normal_zone) {
            $fields .= static_evaluate_tempcode($theme_field);
        }

        $base_url = '';
        if (($zone !== null) && ($zone != '')) {
            global $SITE_INFO;
            if (isset($SITE_INFO['ZONE_MAPPING_' . $zone])) {
                $base_url = 'http://' . $SITE_INFO['ZONE_MAPPING_' . $zone][0] . '/' . $SITE_INFO['ZONE_MAPPING_' . $zone][1];
            }
        }
        if (is_null($GLOBALS['CURRENT_SHARE_USER'])) {
            $fields .= static_evaluate_tempcode(form_input_line(do_lang_tempcode('ZONE_BASE_URL'), do_lang_tempcode('DESCRIPTION_ZONE_BASE_URL'), 'base_url', $base_url, false));
        }

        if ((!$in_zone_editor) && (!is_null($zone)) && (addon_installed('zone_logos'))) {
            // Logos
            handle_max_file_size($hidden, 'image');
            require_code('themes2');
            $themes = find_all_themes();
            foreach ($themes as $theme => $theme_name) {
                $fields .= static_evaluate_tempcode(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => '8c4c1267060970f8b89d1068d03280a7', 'SECTION_HIDDEN' => true, 'TITLE' => do_lang_tempcode('THEME_LOGO', escape_html($theme_name)))));

                require_code('themes2');
                $ids = get_all_image_ids_type('logo', false, null, $theme);

                $set_name = 'logo_choose_' . $theme;
                $required = true;
                $set_title = do_lang_tempcode('LOGO');
                $field_set = (count($ids) == 0) ? new Tempcode() : alternate_fields_set__start($set_name);

                $field_set->attach(form_input_upload(do_lang_tempcode('UPLOAD'), '', 'logo_upload_' . $theme, $required, null, null, true, str_replace(' ', '', get_option('valid_images'))));

                $current_logo = 'logo/' . $zone . '-logo';
                if (!in_array($current_logo, $ids)) {
                    $current_logo = 'logo/-logo';
                }

                foreach ($ids as $id) {
                    $test = find_theme_image($id, true, false, $theme);
                    if ($test == '') {
                        $test = find_theme_image($id, false, false, 'default');
                    }
                    if (($test == '') && ($id == $current_logo)) {
                        $current_logo = $ids[0];
                    }
                }
                $field_set->attach(form_input_theme_image(do_lang_tempcode('STOCK'), '', 'logo_select_' . $theme, $ids, null, $current_logo, null, false, null, $theme));

                $fields .= static_evaluate_tempcode(alternate_fields_set__end($set_name, $set_title, '', $field_set, $required));
            }
        }

        if ($zone !== '') {
            $fields .= static_evaluate_tempcode(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => '579ab823f5f8ec7b48e3b59af8a64ba2', 'TITLE' => do_lang_tempcode('PERMISSIONS'))));

            // Permissions
            $admin_groups = $GLOBALS['FORUM_DRIVER']->get_super_admin_groups();
            $groups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(false, true);
            foreach ($groups as $id => $name) {
                if (in_array($id, $admin_groups)) {
                    continue;
                }

                $perhaps = is_null($zone) ? true : $GLOBALS['SITE_DB']->query_select_value_if_there('group_zone_access', 'zone_name', array('zone_name' => $zone, 'group_id' => $id));
                $fields .= static_evaluate_tempcode(form_input_tick(do_lang_tempcode('ACCESS_FOR', escape_html($name)), do_lang_tempcode('DESCRIPTION_ACCESS_FOR', escape_html($name)), 'access_' . strval($id), !is_null($perhaps)));
            }
        }

        return array(make_string_tempcode($fields), $hidden, $javascript);
    }

    /**
     * The UI to add a zone.
     *
     * @return Tempcode The UI
     */
    public function add_zone()
    {
        appengine_live_guard();

        if (!is_null($GLOBALS['CURRENT_SHARE_USER'])) {
            warn_exit(do_lang_tempcode('SHARED_INSTALL_PROHIBIT'));
        }

        $url_scheme = get_option('url_scheme');
        $change_htaccess = (($url_scheme == 'HTM') || ($url_scheme == 'SIMPLE'));
        $htaccess_path = get_file_base() . '/.htaccess';
        if (($change_htaccess) && (file_exists($htaccess_path)) && (!is_writable_wrap($htaccess_path))) {
            attach_message(do_lang_tempcode('HTM_SHORT_URLS_CARE'), 'warn');
        }

        require_code('form_templates');

        url_default_parameters__enable();

        $fields = new Tempcode();
        $fields->attach(form_input_codename(do_lang_tempcode('CODENAME'), do_lang_tempcode('DESCRIPTION_NAME'), 'zone', '', true));
        list($_fields, $hidden, $javascript) = $this->get_form_fields();
        $fields->attach($_fields);

        url_default_parameters__disable();

        $post_url = build_url(array('page' => '_SELF', 'type' => '_add'), '_SELF');
        $submit_name = do_lang_tempcode('ADD_ZONE');
        $text = paragraph(do_lang_tempcode('ZONE_ADD_TEXT'));

        require_javascript('ajax');
        $script = find_script('snippet');
        $javascript .= "
            var form=document.getElementById('main_form');
            form.old_submit=form.onsubmit;
            form.onsubmit=function() {
                document.getElementById('submit_button').disabled=true;
                var url='" . addslashes($script) . "?snippet=exists_zone&name='+window.encodeURIComponent(form.elements['zone'].value);
                if (!do_ajax_field_test(url))
                {
                    document.getElementById('submit_button').disabled=false;
                    return false;
                }
                document.getElementById('submit_button').disabled=false;
                if (typeof form.old_submit!='undefined' && form.old_submit) return form.old_submit();
                return true;
            };
        ";

        return do_template('FORM_SCREEN', array('_GUID' => 'd8f08884cc370672c2e5604aefe78c6c', 'JAVASCRIPT' => $javascript, 'HIDDEN' => $hidden, 'SUBMIT_ICON' => 'menu___generic_admin__add_one', 'SUBMIT_NAME' => $submit_name, 'TITLE' => $this->title, 'FIELDS' => $fields, 'URL' => $post_url, 'TEXT' => $text, 'SUPPORT_AUTOSAVE' => true));
    }

    /**
     * The actualiser to add a zone.
     *
     * @return Tempcode The UI
     */
    public function _add_zone()
    {
        appengine_live_guard();

        if (!is_null($GLOBALS['CURRENT_SHARE_USER'])) {
            warn_exit(do_lang_tempcode('SHARED_INSTALL_PROHIBIT'));
        }

        $zone = post_param_string('zone');

        check_zone_name($zone);

        require_code('abstract_file_manager');
        force_have_afm_details();

        $_title = post_param_string('title');
        $default_page = post_param_string('default_page');
        $header_text = post_param_string('header_text');
        $theme = post_param_string('theme');
        $require_session = post_param_integer('require_session', 0);
        $base_url = post_param_string('base_url', '');

        actual_add_zone($zone, $_title, $default_page, $header_text, $theme, $require_session, false, $base_url);

        sync_htaccess_with_zones();

        $this->set_permissions($zone);

        // Show it worked / Refresh
        $url = build_url(array('page' => $default_page), $zone);
        return redirect_screen($this->title, $url, do_lang_tempcode('SUCCESS'));
    }

    /**
     * The UI to choose a zone to edit.
     *
     * @param  string $type The follow-on type
     * @param  ?Tempcode $title The title to use (null: the EDIT_ZONE title)
     * @return Tempcode The UI
     */
    public function edit_zone($type = '_edit', $title = null)
    {
        if (is_null($title)) {
            $title = $this->title;
        }

        $start = get_param_integer('start', 0);
        $max = get_param_integer('max', 50);

        $_zones = find_all_zones(false, true, false, $start, $max);

        $url_map = array('page' => '_SELF', 'type' => $type);
        if ($type == '_editor') {
            $url_map['wide'] = 1;
        }

        require_code('templates_results_table');

        $current_ordering = 'name ASC';
        if (strpos($current_ordering, ' ') === false) {
            warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
        }
        list($sortable, $sort_order) = explode(' ', $current_ordering, 2);
        $sortables = array();

        $header_row = results_field_title(array(
            do_lang_tempcode('NAME'),
            do_lang_tempcode('TITLE'),
            do_lang_tempcode('DEFAULT_PAGE'),
            do_lang_tempcode('THEME'),
            do_lang_tempcode('REQUIRE_SESSION'),
            do_lang_tempcode('ACTIONS'),
        ), $sortables, 'sort', $sortable . ' ' . $sort_order);

        $fields = new Tempcode();

        require_code('form_templates');
        $max_rows = $GLOBALS['SITE_DB']->query_select_value('zones', 'COUNT(*)');
        foreach ($_zones as $_zone_details) {
            list($zone_name, $zone_title, $zone_default_page, $remaining_row) = $_zone_details;

            $edit_link = build_url($url_map + array('id' => $zone_name), '_SELF');

            $fields->attach(results_entry(array(
                hyperlink(build_url(array('page' => ''), $zone_name), ($zone_name == '') ? do_lang_tempcode('NA_EM') : make_string_tempcode(escape_html($zone_name)), false, false),
                $zone_title,
                $zone_default_page,
                ($remaining_row['zone_theme'] == '-1') ? do_lang_tempcode('NA_EM') : hyperlink(build_url(array('page' => 'admin_themes'), 'adminzone'), $remaining_row['zone_theme'], false, true),
                ($remaining_row['zone_require_session'] == 1) ? do_lang_tempcode('YES') : do_lang_tempcode('NO'),
                protect_from_escaping(hyperlink($edit_link, do_lang_tempcode('EDIT'), false, true, $zone_name)),
            ), true));
        }

        $table = results_table(do_lang('ZONES'), get_param_integer('start', 0), 'start', either_param_integer('max', 20), 'max', $max_rows, $header_row, $fields, $sortables, $sortable, $sort_order);

        $text = do_lang_tempcode('CHOOSE_EDIT_LIST');
        $tpl = do_template('COLUMNED_TABLE_SCREEN', array('_GUID' => 'a33d3ff1178e7898b42acd83b38b5dcb', 'TITLE' => $title, 'TEXT' => $text, 'TABLE' => $table, 'SUBMIT_ICON' => 'menu___generic_admin__edit_this', 'SUBMIT_NAME' => null, 'POST_URL' => get_self_url()));

        require_code('templates_internalise_screen');
        return internalise_own_screen($tpl);
    }

    /**
     * The UI to edit a zone.
     *
     * @return Tempcode The UI
     */
    public function _edit_zone()
    {
        require_lang('themes');

        $zone = get_param_string('id', ''); // '' needed for URL Schemes
        if ($zone == '/') {
            $zone = '';
        }

        $rows = $GLOBALS['SITE_DB']->query_select('zones', array('*'), array('zone_name' => $zone), '', 1);
        if (!array_key_exists(0, $rows)) {
            warn_exit(do_lang_tempcode('MISSING_RESOURCE', 'zone'));
        }
        $row = $rows[0];

        $header_text = get_translated_text($row['zone_header_text']);
        list($fields, $hidden, $javascript) = $this->get_form_fields(false, get_translated_text($row['zone_title']), $row['zone_default_page'], $header_text, $row['zone_theme'], $row['zone_require_session'], $zone);
        $hidden->attach(form_input_hidden('zone', $zone));
        $no_delete_zones = (get_forum_type() == 'cns') ? array('', 'adminzone', 'forum') : array('', 'adminzone');
        $no_rename_zones = array('', 'adminzone', 'forum');
        $no_rename = (appengine_is_live()) || (in_array($zone, $no_rename_zones)) || (get_file_base() != get_custom_file_base());
        if ($no_rename) {
            $hidden->attach(form_input_hidden('new_zone', $zone));
        } else {
            $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => 'b6915d8e00ae36d2f47e44bbbb14ae69', 'TITLE' => do_lang_tempcode('ACTIONS'))));
            $rename_label = 'DESCRIPTION_ZONE_RENAME';
            if (in_array($zone, array('site', 'cms', 'collaboration'))) {
                $rename_label = 'DESCRIPTION_ZONE_RENAME_DEFAULT_ZONE';
            }
            $fields->attach(form_input_codename(do_lang_tempcode('CODENAME'), do_lang_tempcode($rename_label), 'new_zone', $zone, true));
        }
        if ((!in_array($zone, $no_delete_zones)) && (!appengine_is_live()) && (is_null($GLOBALS['CURRENT_SHARE_USER']))) {
            if ($no_rename) {
                $fields->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('_GUID' => '2fec0bddfe975b573da9bbd68ec16689', 'TITLE' => do_lang_tempcode('ACTIONS'))));
            }
            $fields->attach(form_input_tick(do_lang_tempcode('DELETE'), do_lang_tempcode('DESCRIPTION_DELETE_LOSE_CONTENTS', 'zone'), 'delete', false));
        }

        $map = array('page' => '_SELF', 'type' => '__edit');
        $url = get_param_string('redirect', null);
        if (!is_null($url)) {
            $map['redirect'] = $url;
        }
        $post_url = build_url($map, '_SELF');
        $submit_name = do_lang_tempcode('SAVE');

        return do_template('FORM_SCREEN', array('_GUID' => '54a578646aed86da06f30c459c9586c2', 'JAVASCRIPT' => $javascript, 'HIDDEN' => $hidden, 'SUBMIT_ICON' => 'menu___generic_admin__edit_this', 'SUBMIT_NAME' => $submit_name, 'TITLE' => $this->title, 'FIELDS' => $fields, 'URL' => $post_url, 'TEXT' => '', 'SUPPORT_AUTOSAVE' => true));
    }

    /**
     * The actualiser to edit a zone.
     *
     * @return Tempcode The UI
     */
    public function __edit_zone()
    {
        $zone = post_param_string('zone');

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

        if (($delete == 1) && (!appengine_is_live())) {
            actual_delete_zone($zone);

            // Show it worked / Refresh
            $_url = build_url(array('page' => '_SELF', 'type' => 'edit'), '_SELF');
            return redirect_screen($this->title, $_url, do_lang_tempcode('SUCCESS'));
        } else {
            $_title = post_param_string('title');
            $default_page = post_param_string('default_page');
            $header_text = post_param_string('header_text');
            $theme = post_param_string('theme');
            $require_session = post_param_integer('require_session', 0);
            $base_url = post_param_string('base_url', '');

            $new_zone = post_param_string('new_zone');
            if ($new_zone != $zone) {
                appengine_live_guard();
                check_zone_name($new_zone);
            }
            actual_edit_zone($zone, $_title, $default_page, $header_text, $theme, $require_session, $new_zone, false, false, $base_url);

            if ($new_zone != '') {
                $this->set_permissions($new_zone);
            }

            $this->title = get_screen_title('EDIT_ZONE'); // Re-get title late, as we might be changing the theme this title is got from

            // Handle logos
            if (addon_installed('zone_logos')) {
                require_code('themes2');
                require_code('uploads');
                $themes = find_all_themes();
                foreach (array_keys($themes) as $theme) {
                    $iurl = '';
                    if ((is_plupload()) || (((array_key_exists('logo_upload_' . $theme, $_FILES)) && (is_uploaded_file($_FILES['logo_upload_' . $theme]['tmp_name']))))) {
                        $urls = get_url('', 'logo_upload_' . $theme, 'themes/' . $theme . '/images_custom', 0, CMS_UPLOAD_IMAGE);
                        $iurl = $urls[0];
                    }
                    if ($iurl == '') {
                        $theme_img_code = post_param_string('logo_select_' . $theme, '');
                        if ($theme_img_code == '') {
                            continue; // Probably a theme was added half-way
                            //warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN_UPLOAD'));
                        }
                        $iurl = find_theme_image($theme_img_code, false, true, $theme);
                    }
                    $GLOBALS['SITE_DB']->query_delete('theme_images', array('id' => 'logo/' . $new_zone . '-logo', 'theme' => $theme, 'lang' => get_site_default_lang()), '', 1);
                    $GLOBALS['SITE_DB']->query_insert('theme_images', array('id' => 'logo/' . $new_zone . '-logo', 'theme' => $theme, 'path' => $iurl, 'lang' => get_site_default_lang()));
                    Self_learning_cache::erase_smart_cache();
                }
            }

            sync_htaccess_with_zones();

            // Show it worked / Refresh
            $url = get_param_string('redirect', null);
            if (is_null($url)) {
                $_url = build_url(array('page' => '_SELF', 'type' => 'edit'), '_SELF');
                $url = $_url->evaluate();
            }
            return redirect_screen($this->title, $url, do_lang_tempcode('SUCCESS'));
        }
    }

    /**
     * Set zone access permissions from info in the POST request.
     *
     * @param  ID_TEXT $zone The zone that we're setting permissions for
     */
    public function set_permissions($zone)
    {
        $groups = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(false, true);
        $admin_groups = $GLOBALS['FORUM_DRIVER']->get_super_admin_groups();
        foreach (array_keys($groups) as $id) {
            if (in_array($id, $admin_groups)) {
                continue;
            }

            $value = post_param_integer('access_' . strval($id), 0);
            $GLOBALS['SITE_DB']->query_delete('group_zone_access', array('zone_name' => $zone, 'group_id' => $id), '', 1);
            if ($value == 1) {
                $GLOBALS['SITE_DB']->query_insert('group_zone_access', array('zone_name' => $zone, 'group_id' => $id));
            }
        }

        decache('menu');
        require_code('caches3');
        erase_block_cache();
        erase_persistent_cache();
    }
}
