Last commit for src/views/elements/WikiElement.php: a003aabfc4025180a272e89029be4055134ed367

editing a description of a media detail for when in list or grid mode stays on iframe

Chris Pollett [2024-04-12 17:Apr:th]
editing a description of a media detail for when in list or grid mode stays on iframe
<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2023  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2023
 * @filesource
 */
namespace seekquarry\yioop\views\elements;

use seekquarry\yioop as B;
use seekquarry\yioop\configs as C;
use seekquarry\yioop\library as L;
use seekquarry\yioop\library\CrawlConstants;
use seekquarry\yioop\models\Model;

/** For tl, getLocaleTag and Yioop constants */
require_once __DIR__.'/../../library/Utility.php';
/**
 * Element responsible for drawing wiki pages in group view
 * It is also responsible for rendering wiki history pages, and listings of
 * wiki pages available for a group
 *
 * @author Chris Pollett
 */
class WikiElement extends Element implements CrawlConstants
{
    /**
     * Draw a wiki page for group, or, depending on $data['MODE'] a listing
     * of all pages for a group, or the history of revisions of a given page
     * or the edit page form
     *
     * @param array $data fields contain data about the page being
     *      displayed or edited, or the list of pages being displayed.
     */
    public function render($data)
    {
        $logged_in = isset($data["ADMIN"]) && $data["ADMIN"];
        $can_edit = $logged_in && isset($data["CAN_EDIT"]) && $data["CAN_EDIT"];
        $other_controller = "group";
        $base_query = htmlentities(B\wikiUrl("", true, $data['CONTROLLER'],
            $data["GROUP"]["GROUP_ID"]));
        $csrf_token = "";
        if ($logged_in) {
            $csrf_token = C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
            $base_query .= $csrf_token;
        }
        if (isset($data['page_type']) && $data['page_type']
            == 'presentation' && $data["MODE"] == 'read') {
            e('<div class="presentation-activity">');
            if (isset($data['QUERY_STATISTICS'])) {
                $this->view->layout_object->presentation = true;
            }
        } else {
            $page_border = "";
            if (isset($data["HEAD"]['page_border']) &&
                $data["HEAD"]['page_border'] &&
                $data['HEAD']['page_border'] != 'none') {
                $page_border = $data['HEAD']['page_border'];
            } else if (in_array($data["MODE"], ["edit", "source"])) {
                $page_border = "solid-border";
            }
            e('<div class="small-margin-current-activity '.$page_border.'">');
        }
        if (isset($data['BACK_URL'])) {
            $this->view->helper("close")->render(C\SHORT_BASE_URL . "?" .
                $data['BACK_URL'] . "&amp;" . C\CSRF_TOKEN . "=" .
                $data[C\CSRF_TOKEN]);
        }
        $folder_prefix = $base_query . '&amp;arg=read&amp;page_name='.
            $data['PAGE_NAME'];
        if (!empty($data['MEDIA_NAME'])) {
            if (!empty($data["PAGE"]) && stristr($data["PAGE"], "iframe") !==
                false) { ?>
                <div class="float-opposite"><a href="javascript:<?= "";
                    ?>window.location=tag('iframe')[0].src;">&#8648;</a><?php
                ?></div><?php
            }
            ?><div class="top-margin media-controls"><?php
                e("<b>".tl('wiki_element_places')."</b>");
                if (!empty($data['PREV_LINK'])) {
                    e("<a id='prev-link' href='".
                        "{$data['PREV_LINK']}'>&lt;&lt;</a>&nbsp;");
                } else {
                    e("<a id='prev-link' class='none'" .
                        " href=''>&lt;&lt;</a>&nbsp;");
                }
                $name_parts = pathinfo($data['MEDIA_NAME']);
                $this->renderPath('media-path', $data, [$folder_prefix =>
                    $data['PAGE_NAME']], "", $name_parts['filename']);
                if (!empty($data['NEXT_LINK'])) {
                    e("&nbsp;<a id='next-link' href='" .
                        "{$data['NEXT_LINK']}'>&gt;&gt;</a>");
                } else {
                    e("&nbsp;<a id='next-link' class='none'" .
                        " href=''>&gt;&gt;</a>");
                }
                ?>
            </div>
            <?php
        }
        switch ($data["MODE"]) {
            case "edit":
                $this->renderEditPageForm($data);
                break;
            case "pages":
                $this->renderPages($data, $can_edit, $logged_in);
                break;
            case "history":
                $this->renderHistory($data);
                break;
            case "source":
                $this->renderSourcePage($data);
                break;
            case "resources":
                $this->renderResources($data);
                break;
            case "relationships":
                $this->renderRelationships($data);
                break;
            case "read":
                // no break
            case "show":
            default:
                $is_page_and_feedback = (!empty($data["HEAD"]['page_type']) &&
                    $data["HEAD"]['page_type'] == 'page_and_feedback');
                $is_api = ($data['VIEW'] == 'api');
                if (!$is_page_and_feedback || !$is_api) {
                    $this->renderReadPage($data, $can_edit, $logged_in);
                }
                if ($is_page_and_feedback) {
                    if ($is_api) {
                        $data['API'] = true;
                    } else {
                        ?><hr ><?php
                    }
                    $base_query = htmlentities(B\wikiUrl("", true,
                        $data['CONTROLLER'], $data["GROUP"]["GROUP_ID"]));
                    if ($logged_in) {
                        $csrf_token = C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
                        $base_query .= $csrf_token;
                    }
                    $data['FRAGMENT'] = '#result-' . $data['DISCUSS_THREAD'];
                    $this->view->element('groupfeed')->renderUngroupedView(
                        $can_edit, $base_query, $data['PAGING_QUERY'], $data);
                    if (!$is_api) {
                        $this->view->element('groupfeed')->renderScripts($data);
                    }
                }
                break;
        }
        e('</div>');
    }
    /**
     * Used to draw a Wiki Page for reading. If the page does not exist
     * various create/login-to-create etc messages are displayed depending
     * of it the user is logged in. and has write permissions on the group
     *
     * @param array $data fields PAGE used for page contents
     * @param bool $can_edit whether the current user has permissions to
     *     edit or create this page
     * @param bool $logged_in whether current user is logged in or not
     */
    public function renderReadPage($data, $can_edit, $logged_in)
    {
        $group_id = (empty($data["GROUP"]["GROUP_ID"])) ? C\PUBLIC_GROUP_ID:
            $data["GROUP"]["GROUP_ID"];
        $stretch = ($_SERVER["MOBILE"]) ? 3.8 : 6;
        $word_wrap_len = intval(ceil($stretch * C\NAME_TRUNCATE_LEN));
        $base_query = htmlentities(B\wikiUrl("", true, $data['CONTROLLER'],
            $data["GROUP"]["GROUP_ID"]));
        if ($logged_in) {
            $csrf_token = C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
            $base_query .= $csrf_token;
        }
        if (isset($data["HEAD"]['page_type']) && $data["HEAD"]['page_type'] ==
            'media_list') {
            $this->renderResources($data, "read", $logged_in);
        } elseif (isset($data["PAGE"]) && isset($data["HEAD"]['page_type']) &&
            $data["HEAD"]['page_type'] == 'share') {
            $this->renderShareWall($data);
        } else if (!empty($data["PAGE"])) {
            $sub_path = (empty($data['SUB_PATH'])) ? "": $data['SUB_PATH'];
            $media_id = "";
            if (!empty($data['MEDIA_NAME'])) {
                $media_id = L\crawlHash($data['PAGE_ID'] . $data['MEDIA_NAME'] .
                    $sub_path);
            }
            ?><div><?= $this->dynamicSubstitutions($group_id, $data,
                $data["PAGE"]); ?></div><?php
            if (!empty($data['NEXT_LINK'])) {
                $num_resources = count($data['RESOURCES_INFO']['resources']);
                $url_prefix = html_entity_decode($data["URL_PREFIX"]);
                if ($logged_in) {
                    $csrf_token = C\CSRF_TOKEN . "=" .$data[C\CSRF_TOKEN];
                    if (C\REDIRECTS_ON) {
                        $url_prefix =  preg_replace("/\/-\//u",
                            "/$csrf_token/", $url_prefix);
                    } else {
                        $csrf_token = "&" . $csrf_token;
                        $url_prefix .= $csrf_token;
                    }
                } else {
                    $csrf_token = "";
                }
                ?>
                <script>
                media_elt = document.getElementById('<?=$media_id ?>');
                media_prefix = '<?=$url_prefix ?>';
                url_prefix = '<?=html_entity_decode($data["URL_PREFIX"]) ?>';
                next_resources = [<?php
                    $comma = "";
                    $prev_type = false;
                    for ($i = $data['NEXT_INDEX'] - 1;
                        $i < $num_resources; $i++) {
                        $resource = $data['RESOURCES_INFO']['resources'][$i];
                        if (!$resource['media_type'] || ($prev_type &&
                            $prev_type != $resource['media_type'])) {
                            break;
                        } else {
                            echo $comma . json_encode($resource['name']);
                        }
                        $prev_type = $resource['media_type'];
                        $comma = ",";
                    }
                    ?>];
                end_next_resource = false;
                <?php
                $url_connective =  "&n=";
                if ($i < $num_resources) { ?>
                    end_next_resource = url_prefix + '<?=$url_connective .
                        urlencode($resource["name"]) ?>';<?php
                }
                ?>
                current_resource_index = 1;
                if (media_elt) {
                    if (media_elt.tagName == 'AUDIO' ||
                        media_elt.tagName == 'VIDEO' ) {
                        if (localStorage) {
                            if (media_current_time = localStorage.getItem(
                                "current_time" + media_elt.id)) {
                                media_elt.currentTime = media_current_time;
                            }
                            setInterval(function () {
                                media_elt = document.getElementById('<?=
                                    $media_id ?>');
                                localStorage.setItem("current_time" +
                                    media_elt.id, media_elt.currentTime);
                                epsilon_time = 150;
                                if (media_elt.duration &&
                                    media_elt.duration < 600) {
                                    epsilon_time = Math.abs(0.05 *
                                        media_elt.duration);
                                }
                                if (media_elt.duration &&
                                     media_elt.duration -
                                     media_elt.currentTime < epsilon_time) {
                                     localStorage.removeItem(
                                         "current_time" + media_elt.id);
                                }

                            }, 5000);
                        }
                        media_elt.onended = function(evt) {
                            sources = media_elt.getElementsByTagName('source');
                            source = sources[0];
                            elt('prev-link').href= url_prefix +
                                '<?=$url_connective ?>' +
                                next_resources[current_resource_index - 1];
                            elt('prev-link').style.display = 'inline';
                            if (current_resource_index + 1 <
                                next_resources.length) {
                                elt('next-link').href= url_prefix +
                                    '<?=$url_connective ?>' +
                                    next_resources[current_resource_index + 1]
                            } else if (current_resource_index + 1 ==
                                next_resources.length && end_next_resource) {
                                elt('next-link').href = end_next_resource;
                            } else if (end_next_resource) {
                                window.location = end_next_resource;
                                return;
                            } else {
                                elt('next-link').style.display = 'none';
                            }
                            let old_src = source.getAttribute('src');
                            old_src = old_src.split("+").join("%20");
                            let old_resource =
                                next_resources[current_resource_index - 1];
                            source.setAttribute('src', old_src.replace(
                                encodeURIComponent(old_resource),
                                encodeURIComponent(
                                    next_resources[current_resource_index])));
                            if (next_resources[current_resource_index]) {
                                let next_resource_name =
                                    next_resources[current_resource_index
                                    ].replace(/\.\S{3,5}$/, "");
                                page_path_elt = elt('selected-media-path');
                                page_path_elt.innerHTML = next_resource_name;
                                page_path_elt = elt('selected2-media-path');
                                page_path_elt.innerHTML = next_resource_name;
                                current_resource_index++;
                                media_elt.load();
                                media_elt.play();
                            }
                        }
                    }
                }
                </script>
                <?php
            }
        } else if (!empty($data["HEAD"]['page_alias'])) {
            $alias = $data["HEAD"]['page_alias'];
            $data['PAGE']["DESCRIPTION"] = tl('wiki_element_redirect_to').
                " <a href='$base_query&amp;".
                "page_name=$alias'>$alias</a>";
            ?>
            <?=$data['PAGE']["DESCRIPTION"] ?>
            <?php
        } elseif ($can_edit) {
            ?>
            <h2><?= tl("wiki_element_page_no_exist",
                wordwrap(urldecode($data["PAGE_NAME"]), $word_wrap_len ,
                "\n", true)) ?></h2>
            <p><?= tl("wiki_element_create_edit") ?></p>
            <p><?= tl("wiki_element_use_form") ?></p>
            <form id="editpageForm" method="get" action="<?=C\SHORT_BASE_URL
            ?>" >
            <input type="hidden" name="c" value="<?= $data['CONTROLLER']?>" >
            <input type="hidden" name="<?= C\CSRF_TOKEN ?>" value="<?=
                $data[C\CSRF_TOKEN] ?>" >
            <input type="hidden" name="a" value="wiki" >
            <input type="hidden" name="arg" value="edit" >
            <input type="hidden" name="group_id" value="<?=
                $data['GROUP']['GROUP_ID'] ?>" >
            <input aria-label="<?= tl("wiki_element_create_load_page"); ?>"
                type="text" name="page_name" class="narrow-field"
                value="<?=urldecode($data["PAGE_NAME"]) ?>" >
            <button class="button-box" type="submit"><?=
                tl('wiki_element_go') ?></button>
            </form>
            <?php
            e("<p><a href=\"" . htmlentities(B\wikiUrl('Syntax', true,
                $data['CONTROLLER'], C\PUBLIC_GROUP_ID)) .
                C\CSRF_TOKEN .'='.$data[C\CSRF_TOKEN] . '&amp;arg=read'.
                "\">". tl('wiki_element_syntax_summary') .
                "</a>.</p>");
        } elseif (!$logged_in) {
            e("<h2>".tl("wiki_element_page_no_exist",
                wordwrap(urldecode($data["PAGE_NAME"]), $word_wrap_len ,
                "\n", true)) . "</h2>");
            e("<p>".tl("wiki_element_signin_edit")."</p>");
        } else {
            e("<h2>".tl("wiki_element_page_no_exist",
                wordwrap(urldecode($data["PAGE_NAME"]), $word_wrap_len ,
                "\n", true)) .
                "</h2>");
        }
    }
    /**
     *
     * @param array $data fields contain data about the page with the
     *  page being shared
     */
    public function renderShareWall($data)
    {
        ?>
        <h2><?= tl("wiki_element_share_wall", $data["PAGE_NAME"]) ?></h2><?php
        if (empty($data["PAGE"])) {?>
            <div class="red"><?=tl("wiki_element_no_data_shared") ?></div>
            <?php
        } else { ?>
            <div><?=tl("wiki_element_last_edited",
                $data['LAST_EDITOR'], date("r", $data['LAST_EDIT_TIME']));
            ?></div>
            <div class="formatted-share-wall"><div><div><?=
                str_replace("\n", "</div>\n<div>", $data["PAGE"]);
            ?></div></div>
            </div><?php
        } ?>
        <form method="post">
        <input type="hidden" name="c" value="<?=$data['CONTROLLER']
            ?>" >
        <input type="hidden" name="a" value="wiki" >
        <input type="hidden" name="arg" value="edit" >
        <input type="hidden" name="<?=C\CSRF_TOKEN ?>" value="<?=
            $data[C\CSRF_TOKEN];
        ?>" >
        <div id="share-container">
        <h3 class="top-margin"><label for='share-wall'><?=
            tl("wiki_element_raw_content") ?></label></h3>
        <p class="green"><?=tl("wiki_element_add_share")?></p>
        <textarea id="share-wall" class="share-wall"
            name="share_wall_data"><?= $data["PAGE"]
        ?></textarea>
        </div>
        <div class="top-margin center">
        <button class="button-box" type="submit"><?=
            tl("wiki_element_savebutton")
        ?></button>
        </div>
        </form><?php
    }
    /**
     * Used to drawn the form that let's someone edit a wiki page
     *
     * @param array $data fields contain data about the page being
     *      edited. In particular, PAGE contains the raw page data
     */
    public function renderEditPageForm($data)
    {
        $icon_helper = $this->view->helper('iconlink');
        $simple_base_url = B\wikiUrl("", true,
            $data['CONTROLLER'], $data['GROUP']['GROUP_ID']) .
            C\CSRF_TOKEN.'='.$data[C\CSRF_TOKEN];
        $base_url = htmlentities($simple_base_url);
        $simple_view_url = B\wikiUrl($data['PAGE_NAME'], true,
           $data['CONTROLLER'], $data['GROUP']['GROUP_ID']) .
           C\CSRF_TOKEN . '=' . $data[C\CSRF_TOKEN];
        $simple_current_url = $simple_view_url . "&arg=edit";
        $is_settings_view = !empty($data['settings']) &&
            $data['settings'] != "false";
        $is_resources_view = !empty($data['resources']) &&
            $data['resources'] != "false";
        $is_media_list =
            !empty($data['page_type']) && $data['page_type'] == 'media_list';
        $is_page_alias =
            !empty($data['page_type']) && $data['page_type'] == 'page_alias';
        $is_share =
            !empty($data['page_type']) && $data['page_type'] == 'share';
        $is_shortener =
            !empty($data['page_type']) && $data['page_type'] == 'url_shortener';
        if (!empty($data['SUB_PATH'])) {
            $simple_view_url .= "&sf=".urlencode($data['SUB_PATH']);
            $simple_current_url .= "&sf=".urlencode($data['SUB_PATH']);
        }
        $current_url = htmlentities($simple_current_url);
        $new_settings = $is_settings_view ? "&amp;settings=false" :
            "&amp;settings=true";
        $new_resources = $is_resources_view ? "&amp;resources=false" :
            "&amp;resources=true";
        if ($is_resources_view) {
            $simple_current_url .= "&resources=true";
        }
        $settings_toggle_url = $current_url . $new_settings;
        $resources_toggle_url = $current_url . $new_resources;
        if (isset($data['OTHER_BACK_URL'])) {
            $append = $data['OTHER_BACK_URL'];
        }
        $icon_helper = $this->view->helper('iconlink');
        if ($is_settings_view || $is_resources_view) {
            $toggle_url = ($is_settings_view) ? $settings_toggle_url :
                $resources_toggle_url;
            ?>
            <div class="float-opposite" ><?=
            $this->view->helper('close')->render($toggle_url);
            ?></div>
            <?php
        } else {?>
            <div class="float-opposite wiki-history-discuss" >
            <?=
            $icon_helper->renderButton( $base_url . $append .
                '&amp;arg=history&amp;page_id='.$data['PAGE_ID'], "history");
            ?>
            </div><?php
        }?>
        <form id="editpageForm" method="post"
            enctype="multipart/form-data"
            onsubmit="
                var caret_pos = elt('caret-pos');
                var scroll_top = elt('scroll-top');
                var wiki_page = elt('wiki-page');
                if (caret_pos && scroll_top && wiki_page) {
                    caret_pos.value =
                    (wiki_page.selectionStart) ?
                    wiki_page.selectionStart : 0;
                    scroll_top.value= (wiki_page.scrollTop) ?
                    wiki_page.scrollTop : 0;
                }" >
            <input type="hidden" name="c" value="<?=$data['CONTROLLER']
            ?>" >
            <input type="hidden" name="<?=C\CSRF_TOKEN ?>" value="<?=
                $data[C\CSRF_TOKEN] ?>" >
            <input type="hidden" name="a" value="wiki" >
            <input type="hidden" name="arg" value="edit" >
            <?php
            if (isset($data['RESOURCE_NAME'])) { ?>
                <input type="hidden" name="n" value="<?=
                    urlencode($data['RESOURCE_NAME']) ?>" >
                <?php
            }
            if (isset($data['BACK_PARAMS'])) {
                foreach ($data["BACK_PARAMS"] as
                         $back_param_key => $back_param_value) {
                    e('<input type="hidden" '
                        . 'name="' . $back_param_key .
                        '" value="' .
                        $back_param_value
                        . '" >');
                }
            }
            ?>
            <input type="hidden" name="group_id" value="<?=
                $data['GROUP']['GROUP_ID'] ?>" >
            <input type="hidden" name="page_name" value="<?=
                $data['PAGE_NAME'] ?>" >
            <input type="hidden" name="caret" id="caret-pos" >
            <input type="hidden" name="scroll_top" id="scroll-top" >
            <input type="hidden" id="p-settings" name="settings" value="<?=
                $data['settings'] ?>" >
            <input type="hidden" id="p-resources" name="resources" value="<?=
                $data['resources'] ?>" >
            <div class="top-margin">
                <b><?=tl('wiki_element_locale_name',
                    $data['CURRENT_LOCALE_TAG']) ?></b><br>
                <b><label for="wiki-page"><?php
                $human_page_name = preg_replace("/\_/", " ",
                    urldecode($data['PAGE_NAME']));
                e(tl('wiki_element_page', $human_page_name));
                if (isset($data['RESOURCE_NAME'])) {
                    e("<br>" .
                        tl('wiki_element_resource_name',
                        $data['RESOURCE_NAME']));
                    ?></label></b><?php
                } else {
                    ?></label></b><?php
                    if (!$is_settings_view && !$is_resources_view) { ?>
                        <div id="toggle-settings">
                        <?php
                        $icon_helper->renderButton(['settings-toggle-button',
                            $settings_toggle_url], 'settings', "");
                        if (!$is_media_list && !$is_page_alias && !$is_share &&
                            !$is_shortener) {
                            $icon_helper->renderButton(
                                ['resources-toggle-button',
                                $resources_toggle_url], 'resources', "");
                        }
                        $icon_helper->renderButton(htmlentities(
                            B\wikiUrl('Syntax', true, $data['CONTROLLER'],
                            C\PUBLIC_GROUP_ID)) . C\CSRF_TOKEN .'=' .
                            $data[C\CSRF_TOKEN] . '&amp;arg=read',
                            'wiki_syntax');?>
                        </div><?php
                    }
                }
                ?>
            </div>
            <div id='page-settings'>
            <div class="top-margin">
            <label for="page-type"><b><?=tl('wiki_element_page_type')
            ?></b></label><?php
            $attributes = ($is_settings_view) ? [] : ['disabled' => 'disabled'];
            $this->view->helper("options")->render("page-type", "page_type",
                $data['page_types'], $data['current_page_type'], true,
                $attributes);
            ?>
            </div>
            <div id='alias-type'>
            <div class="top-margin">
            <label for="page-alias"><b><?=tl('wiki_element_page_alias')
            ?></b></label><input type="text" id='page-alias'
                name="page_alias" value="<?= $data['page_alias']?>"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            </div><?php
            $shortened_url = '';
            if (!empty($data['url_shortener'])) {
                $shortened_url = C\BASE_URL . "group/" . $_REQUEST['group_id'] .
                    "/" . $_REQUEST['page_name'];
            }?>
            <div id='shortener-container'>
            <div class="top-margin">
            <label for="url-shortener"><b><?=tl('wiki_element_url_to_shorten')
            ?></b></label>
            <input type="text" id='url-shortener' name="url_shortener"
                value="<?= $data['url_shortener']?>" class="wide-field" >
            </div>
            </div>
            <div id='short-url-label'>
            <div class="top-margin">
            <b><?=tl('wiki_element_short_url') ?></b> <span class="gray"><?=
                $shortened_url?></span>
            </div>
            <div id="day-chart" ></div>
            <div id="month-chart" ></div>
            <div id="year-chart" ></div>
            </div>
            <div id='share-container'>
            <div class="top-margin">
            <label for='share-expires'><b><?=tl('wiki_element_share_expires')
            ?></b></label><?php
            $this->view->helper("options")->render(
                "share-expires", "share_expires",
                $data["share_page_expires"], ($data['share_expires'] ??
                C\FOREVER));
            ?>
            </div>
            </div>
            <div id='non-alias-type'>
            <div class="top-margin">
            <label for="page-border"><b><?=tl('wiki_element_page_border')
            ?></b></label><?php
            $this->view->helper("options")->render("page-border","page_border",
                $data['page_borders'], $data['page_border']);
            ?>
            </div>
            <div class="top-margin">
            <label for="page-theme"><b><?=tl('wiki_element_page_theme')
            ?></b></label><?php
            $this->view->helper("options")->render("page-theme","page_theme",
                $data['page_themes'], $data['page_theme']);
            ?>
            </div>
            <div class="top-margin">
            <label for="page-toc"><b><?=tl('wiki_element_table_of_contents')
            ?></b></label><input type="checkbox" name="toc" value="true"
                <?php
                    $checked = (isset($data['toc']) && $data['toc']) ?
                    'checked="checked"' : '';
                    e( $checked );
                ?> id='page-toc' >
            </div>
            <div class="top-margin">
            <label for="page-title"><b><?=tl('wiki_element_title')
            ?></b></label><input type="text" id='page-title'
                name="title" value="<?=$data['title'] ?>"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-author"><b><?=tl('wiki_element_meta_author')
            ?></b></label><input type="text" id='meta-author'
                name="author" value="<?= $data['author']?>"
                maxlength="<?= C\LONG_NAME_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-robots"><b><?=tl('wiki_element_meta_robots')
            ?></b></label><input type="text" id='meta-robots'
                name="robots" value="<?= $data['robots'] ?>"
                maxlength="<?=C\LONG_NAME_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-description"><b><?=
                tl('wiki_element_meta_description')
            ?></b></label>
            </div>
            <textarea id="meta-description" class="short-text-area"
                name="description" data-buttons='none'><?=$data['description']
            ?></textarea>
            <div class="top-margin">
            <label for="meta-properties"><b><?=
                tl('wiki_element_meta_properties')
            ?></b></label>
            </div>
            <div><?=tl('wiki_element_meta_property_format')?></div>
            <textarea id="meta-properties" class="short-text-area"
                name="properties" data-buttons='none'><?=$data['properties']
            ?></textarea>
            <?php
            if (!empty($_SESSION['USER_ID']) &&
                $_SESSION['USER_ID'] == C\ROOT_ID) { ?>
                <div class="top-margin">
                <label for="alt-path"><b><?=tl('wiki_element_alternative_path')
                ?></b></label><input type="text" id='alt-path'
                    placeholder="<?=tl('wiki_element_empty_use_default')
                    ?>" name="alternative_path" value="<?=
                    $data['alternative_path'] ?>"
                    maxlength="<?=C\LONG_NAME_LEN ?>" class="wide-field" >
                </div>
                <?php
            }
            ?>
            <div class="top-margin">
            <label for="update-description"><b><?=
            tl('wiki_element_resource_lookup') ?></b></label><?php
            $this->view->helper("options")->render("update-description",
                "update_description", $data['update_descriptions'],
                $data['update_description'] ?? "no-lookup");
            ?></div>
            <div class="top-margin">
            <label for="page-header"><b><?=tl('wiki_element_page_header')
            ?></b></label><input type="text" id='page-header'
                name="page_header" value="<?=$data['page_header']?>"
                maxlength="<?=C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="page-footer"><b><?=tl('wiki_element_page_footer')
            ?></b></label><input type="text" id='page-footer'
                name="page_footer" value="<?=$data['page_footer'] ?>"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            </div>
            </div>
            <?php
            if (!$is_settings_view && !$is_resources_view) { ?>
                <div id='page-container'><?php
                if (substr($data['current_page_type'], 0, 1) != 't' ||
                    !is_numeric(substr($data['current_page_type'], 1))) {
                    if (empty($data['SPREADSHEET'])) {?>
                        <textarea id="wiki-page"
                            class="tall-text-area" name="page"
                            <?php
                            if ((!isset($data['page_type']) ||
                                    $data['page_type'] != 'presentation')) {
                                $data_buttons = 'all,!wikibtn-slide';
                            } else {
                                $data_buttons = 'all';
                            }?>
                            data-buttons='<?=$data_buttons ?>' ><?=
                            $data['PAGE'] ?></textarea><?php
                    } else {
                        e("<div id='spreadsheet'>&nbsp;</div>");
                    }
                } else {
                    e($data['PAGE']);
                }
                if (!isset($data['RESOURCE_NAME'])) {
                    ?>
                    <div class="green center"><?php
                    $this->view->helper("fileupload")->render(
                        'wiki-page', 'page_resource', 'wiki-page-resource',
                        min(L\metricToInt(ini_get('upload_max_filesize')),
                        L\metricToInt(ini_get('post_max_size'))), 'textarea',
                        null, true);
                    e(tl('wiki_element_archive_info'));
                    ?></div>
                    <div class="top-margin">
                    <label for="edit-reason"><b><?=
                        tl('wiki_element_edit_reason')
                        ?></b></label><input type="text" id='edit-reason'
                        name="edit_reason" value="" maxlength="<?=
                        C\SHORT_TITLE_LEN ?>"
                        class="wide-field" >
                    </div><?php
                }
                ?></div><?php
            }?>
            <div id="save-container" class="top-margin center"><?php
            $resource_param = "";
            if (!$is_resources_view && isset($data['RESOURCE_NAME'])) { ?>
                <button class="button-box"
                    onclick="window.location='<?=$current_url;
                    ?>'; return false;" ><?=
                    tl('wiki_element_closebutton') ?></button><?php
                $resource_param = "&amp;arg=media&amp;n=" .
                    $data['RESOURCE_NAME'] . "&amp;page_id=" . $data['PAGE_ID'];
            }
            if (!$is_resources_view) { ?>
                <button class="button-box" type="submit"><?=
                    tl('wiki_element_savebutton') ?></button>
                <a class="source-anchor-button" target="show"
                    style="position:relative; left:-.04in; right:-.04in;"
                    href='<?=$simple_view_url . $resource_param ?>'><?=
                    tl('wiki_element_show');?></a><?php
            }?>
            </div>
        </form>
        <?php
        if ($is_resources_view || ($is_media_list && !$is_settings_view)) {
            ?><div id="page-resources">
            <h3><?= tl('wiki_element_page_resources')?></h3>
            <p><?= tl('wiki_element_resources_info') ?></p>
            <form id="resource-upload-form" method="post"
                enctype="multipart/form-data">
            <input type="hidden" name="c" value="<?= $data['CONTROLLER']
                ?>" >
            <input type="hidden" name="<?= C\CSRF_TOKEN ?>" value="<?=
                $data[C\CSRF_TOKEN] ?>" >
            <input type="hidden" name="a" value="wiki" >
            <input type="hidden" name="arg" value="edit" >
            <?php
                if (isset($data['BACK_PARAMS'])) {
                    foreach ($data["BACK_PARAMS"] as
                             $back_param_key => $back_param_value) {
                        e('<input type="hidden" '
                            . 'name="' . $back_param_key .
                            '" value="' .
                            $back_param_value
                            . '" >');
                    }
                }
            ?>
            <input type="hidden" name="group_id" value="<?=
                $data['GROUP']['GROUP_ID'] ?>" >
            <input type="hidden" name="page_name" value="<?=
                $data['PAGE_NAME'] ?>" >
            <input type="hidden" id="r-settings" name="settings" value="<?=
                $data['settings'] ?>" >
            <input type="hidden" id="r-resources" name="resources" value="<?=
                $data['resources'] ?>" >
            <div class="center">
            <?php
            $this->view->helper("fileupload")->render(
                'page-resources', 'page_resource',
                'media-page-resource',
                min(L\metricToInt(ini_get('upload_max_filesize')),
                L\metricToInt(ini_get('post_max_size'))),
                'immediate', null, false);
            ?>
            </div>
            </form>
            <?php
                $this->renderResources($data, "", true,
                    'media-page-resource');
                $detail_id = $data['PAGE_ID'];
                $detail_id .= (empty($data['SUB_PATH'])) ?
                    "" : base64_encode($data['SUB_PATH']);
            ?>
            <script>
            function renameResource(old_name, id)
            {
                let name_elt;
                if (typeof id === 'object') {
                    name_elt = id;
                } else {
                    name_elt = elt("resource-"+id);
                }
                let new_name = "";
                if (name_elt) {
                    new_name = name_elt.value;
                }
                if (!name_elt || !new_name) {
                    doMessage('<h1 class=\"red\" ><?=
                        tl("wiki_element_rename_failed") ?></h1>');
                    return;
                }
                if (localStorage) {
                    let detail_name = 'detail<?=$detail_id ?>';
                    let url = localStorage.getItem(detail_name);
                    if (url) {
                        localStorage.setItem(detail_name, url.replace(old_name,
                            new_name));
                    }
                }
                let location = "<?=$simple_current_url?>" +
                    "&new_resource_name=" + encodeURIComponent(new_name) +
                    "&old_resource_name=" +
                        old_name.replace('&quot;','"');
                window.location = location;
            }
            function emptyConfirm()
            {
                let really_meant_it =
                    confirm("<?= tl('wiki_element_delete_operation'); ?>");
                if (really_meant_it && localStorage) {
                    let detail_name = 'detail<?=$detail_id ?>';
                    localStorage.removeItem(detail_name);
                }
                return really_meant_it;
            }
            </script>
            </div><?php
        }
    }
    /**
     * Draws a list of media resources associated with a wiki page
     *
     * @param array $data fields RESOURCES_INFO contains info on resources
     * @param string $read_mode whether the rendering should be for a media
     *      list in read mode (value "read"), a source mode (value "source"),
     *      or for use on the edit task of any wiki page (value "")
     * @param bool $logged_in whether the user is currently logged in or not
     * @param string $file_upload_id of form element to be set if can upload
     *      files
     */
    public function renderResources($data, $read_mode, $logged_in = true,
        $file_upload_id = '')
    {
        if (isset($data['RESOURCES_INFO']) && $data['RESOURCES_INFO']) {
            $is_static = ($data['CONTROLLER'] == 'static') ? true : false;
            $token_string = (empty($data[C\CSRF_TOKEN])) ? "" :
                C\CSRF_TOKEN.'='.$data[C\CSRF_TOKEN];
            $base_url = htmlentities(B\wikiUrl($data['PAGE_NAME'] , true,
                $data['CONTROLLER'], $data['GROUP']['GROUP_ID']));
            $url_prefix = $data['RESOURCES_INFO']['url_prefix'];
            if ($logged_in) {
                $base_url .= $token_string;
                if (C\REDIRECTS_ON) {
                    $url_prefix =  preg_replace("/\/-\//u",
                        "/$token_string/", $url_prefix);
                } else {
                    $url_prefix .= "&amp;". $token_string;
                }
            }
            $folder_prefix = ($is_static) ? $base_url : $base_url . "&amp;";
            $folder_prefix .= "page_id=". $data["PAGE_ID"];
            $url_is_folder_prefix = false;
            $settings_and_resources = "";
            if (!empty($data['settings'])) {
                $settings_and_resources =  "&amp;settings={$data['settings']}" .
                "&amp;resources={$data['resources']}";
            }
            if (!empty($read_mode)) {
                $read_arg = ($read_mode == "source") ? "source" : "media";
                $folder_prefix .= "&amp;arg=$read_arg";
                $url_prefix = $folder_prefix;
                $url_is_folder_prefix = true;
            } else if ($data['CURRENT_LAYOUT'] == 'detail') {
                $folder_prefix .= "&amp;arg=media";
                $url_prefix = $folder_prefix;
                $folder_prefix = $base_url . "&amp;arg=edit";
                $base_url .= $settings_and_resources;
                $url_is_folder_prefix = true;
            } else {
                $folder_prefix = $base_url . "&amp;arg=edit";
                $base_url .= $settings_and_resources;
            }
            if ($read_mode != "media") {
                $data['resources'] ??= 'false';
                $folder_prefix .= "&amp;resources={$data['resources']}";
            }
            ?>
            <form>
            <div class="align-opposite media-controls"><?php
            $sub_path = $this->renderPath('resource-path',
                $data, [$folder_prefix => ""], "", "", "paths", false,
                "hover-selector");
            $sub_path_folder_prefix = (empty($data['RESOURCE_FILTER'])) ?
                $folder_prefix : $folder_prefix . "&amp;resource_filter=".
                urlencode($data['RESOURCE_FILTER']);
            $sub_path_var = "";
            if (!empty($data['SUB_PATH'])) {
                $sub_path_var = "&amp;sf=". urlencode($data['SUB_PATH']);
                $sub_path_folder_prefix .= $sub_path_var;
            }
            $layouts = ["list" => ["&#8803;", tl('wiki_element_list_view')],
                "grid" => ["&boxplus;", tl('wiki_element_grid_view')],
                "detail" => ["<span class='dotted-underline'>&#9634;</span>",
                    tl('wiki_element_detail_view')]
                ];
            ?>
            <div class="media-buttons-container"><?php
                foreach ($layouts as $layout => $layout_data) {
                    list($icon, $label) = $layout_data;
                    $is_current_layout = (($data['CURRENT_LAYOUT'] ?? "")
                        == $layout);
                    $layout_style = ($is_current_layout) ?
                        "class='selected' " : "";
                    ?><a class="media-anchor-button" href="<?=
                        $sub_path_folder_prefix . "&amp;layout=$layout"
                        ?>"><span <?=$layout_style ?> role="img" aria-label='<?=
                        $label ?>'><?=$icon ?></span></a><?php
                }
                ?>
            </div><?php
            $this->view->helper("options")->renderLinkDropDown(
                "sort-fields", $data['sort_fields'] ?? "",
                $data['CURRENT_SORT']?? "", "$sub_path_folder_prefix&amp;sort=",
                false, "",
                "<span class='hover-lightgray' role='img' aria-label='" .
                tl('wiki_element_sort_order') . "'>&#8645;</span>");
            $arg = ($data['CONTROLLER'] == 'static') ? 'read' :
                (($data['MODE'] == 'media-detail-edit') ? 'edit' :
                $data['MODE']);
            $a = ($data['CONTROLLER'] == 'static') ? 'showPage' : 'wiki';
            $page_name = ($data['CONTROLLER'] == 'static') ? 'p' : 'page_name';
            ?>
            <input type="hidden" name='<?=C\CSRF_TOKEN?>'
                value='<?=$data[C\CSRF_TOKEN]?>' >
            <input type="hidden" name='arg' value='<?=$arg ?>' >
            <input type="hidden" name='a' value='<?=$a ?>' >
            <input type="hidden" name='c' value='<?=$data['CONTROLLER'] ?>' >
            <input type="hidden" name='resources' value='<?=$data["resources"]
                ?? "false" ?>' >
            <input type="hidden" name='<?= $page_name?>'
                value='<?=$data['PAGE_NAME']?>' >
            <?php
            if (!empty($data['SUB_PATH'])) { ?>
                <input type="hidden" name='sf'
                    value='<?=$data['SUB_PATH']; ?>' >
                <?php
            }
            ?>
            <div class="filter-container">
            <input type="search" class="narrow-field" name='resource_filter'
                placeholder="<?=tl('wiki_element_resource_filter')?>"
                id='resource-filter' value="<?=$data['RESOURCE_FILTER']?>" >
            </div>
            <button type='submit' name='filter_resources'
                class="button-box media-filter-button"><?=
                tl('wiki_element_go') ?></button><?php
            if (empty($read_mode)) {
                ?><div class="media-buttons-container" id='clipboard-toggle'><a
                    class="media-anchor-button"
                    href="javascript:toggleDisplay('clipboard');<?php
                    ?>toggleClass('clipboard-toggle','back-gray');<?php
                    ?>this.preventDefault;"><span
                    role="img" aria-label='<?=
                    tl('wiki_element_clipboard')
                    ?>'>&#128203;</span></a></div><?php
                if ($file_upload_id != "") {
                    $data['resource_actions'][
                        "javascript:elt('$file_upload_id').click()"] =
                        tl('wiki_element_upload_file');
                }
                $this->view->helper("options")->renderLinkDropDown(
                    "resource-actions", $data['resource_actions'],
                    -1, "$sub_path_folder_prefix&amp;resource_actions=",
                    false, "inward-align",
                    "<span class='hover-lightgray' role='img' aria-label='" .
                    tl('wiki_element_actions') . "'>&#8943;</span>");
            }
            ?>
            </div></form>
            <div id="clipboard" class="none">
            <h3><?=tl('wiki_element_clipboard') ?></h3>
            <div>
            [<a href="<?=$base_url . $sub_path_var .
                '&amp;arg=edit&amp;paste_all=true'
                ?>"><?=tl('wiki_element_paste_all')?></a>]
            [<a onclick='return emptyConfirm();'
                href="<?=$base_url . $sub_path_var .
                '&amp;arg=edit&amp;empty_clip=true'
                ?>"><?=tl('wiki_element_empty_clipboard')?></a>]
            </div>
            <hr ><?php
            if (empty($data['CLIPBOARD_INFO'])) {?>
                <div class='red'><?=tl('wiki_element_no_clipboard_items')
                ?></div><?php
            } else {
                foreach ($data['CLIPBOARD_INFO'] as $clipboard_name) { ?>
                    [<a href="<?=$base_url . $sub_path_var .
                        '&amp;arg=edit&amp;paste='.urlencode($clipboard_name)
                        ?>"><?=tl('wiki_element_paste',
                        $clipboard_name)?></a>]
                    <?php
                }
            }
            ?></div>
            <?php
            if (count($data['RESOURCES_INFO']['resources']) > 0 ||
                empty($read_mode)) {
                $none = (count($data['RESOURCES_INFO']['resources']) == 0) ?
                    "none" : "";
                ?><div id="<?= ($data['SCROLL_CONTAINER_ID'] ?? "")
                    ?>" class="wiki-resources <?=$none?>"><?php
                $is_list = false;
                $is_grid = false;
                $is_detail = false;
                if (empty($data['CURRENT_LAYOUT']) ||
                    $data['CURRENT_LAYOUT'] == 'list') {
                    $is_list = true;
                    ?><table><thead><?php
                } else if ($data['CURRENT_LAYOUT'] == 'grid') {
                    $is_grid = true;
                    ?><div class="grid-container"><?php
                } else {
                    $is_detail = true;
                    $read_mode = empty($read_mode) ? "media" : $read_mode;
                    ?>
                    <div id='detail-item'>&nbsp;</div>
                    <div id='<?=$data['DETAIL_SCROLL_ID'];
                        ?>' class="detail-container"><?php
                }
                if (empty($read_mode) && $data['MODE'] != 'source' &&
                    $data['CURRENT_LAYOUT'] == 'list') {
                    ?><tr><th colspan="2"></th><th><a href='<?=
                        $sub_path_folder_prefix?>&amp;default_sort=name'><?=
                        tl('wiki_element_name')
                    ?></a></th><?php
                    if (!$_SERVER["MOBILE"]) {
                        e("<th><a href='$sub_path_folder_prefix&amp;".
                            "default_sort=size'>" . tl('wiki_element_size').
                            '</a>');
                        e("</th><th ><a href='".
                            "$sub_path_folder_prefix&amp;".
                            "default_sort=modified'>" .
                            tl('wiki_element_modified').'</a></th>');
                    } ?>
                </tr></thead><tbody><?php
                }
                $seen_resources = []; /* these are video and audio which
                   appear in different version such as mp4 and mov
                   This array keeps track if have seen an alternative version
                   earlier while processing resource list.
                   */
                $i = 0;
                $is_first = true;
                foreach ($data['RESOURCES_INFO']['resources'] as $resource) {
                    $this->renderResource($i, $is_first, $resource, $base_url,
                        $token_string, $url_prefix, $url_is_folder_prefix,
                        $folder_prefix, $seen_resources, $read_mode, $logged_in,
                        $data);
                    $i++;
                }
                if ($is_list) {
                    ?></tbody></table><?php
                } else if ($is_grid) {
                    ?></div><?php
                } else {
                    ?></div><?php
                }
                ?></div><?php
                if (!empty($read_mode)) {
                    $scroll_id_path = $data['PAGE_ID'];
                    $scroll_id_path .= (empty($data['SUB_PATH'])) ?
                        "" : base64_encode($data['SUB_PATH']);
                    ?>
                    <script>
                    function clearResource(id, url)
                    {
                        if (localStorage && localStorage.getItem(
                            "current_time" + id)) {
                            localStorage.removeItem("current_time" + id);
                        }
                        window.location = url;
                    }
                    function recordScrollTop()
                    {
                        let root_elt = document.documentElement;
                        localStorage.setItem("scroll_top<?=
                            $scroll_id_path ?>", root_elt.scrollTop);
                    }
                    function initializeResourceList()
                    {
                        let marked_elts = document.getElementsByClassName(
                            'marked');
                        for (let i = 0; i < marked_elts.length; i++) {
                            let cur_id = marked_elts.item(i).id;
                            if (localStorage && localStorage.getItem(
                                "current_time" + cur_id)) {
                                marked_elts.item(i).innerHTML = "&loz;";
                            }
                        }
                        let scroll_top;
                        if (localStorage) {
                            document.body.addEventListener("click",
                                recordScrollTop, true);
                            if (scroll_top = localStorage.getItem(
                                "scroll_top<?= $scroll_id_path ?>")) {
                                document.documentElement.scrollTop = scroll_top;
                            }
                        }
                    }
                    initializeResourceList();
                    </script>
                    <?php
                }
            }
        }
        if (empty($data['RESOURCES_INFO']['resources']) ||
            count($data['RESOURCES_INFO']['resources']) == 0) {
            ?>
            <div class='red'><?=tl('wiki_element_no_resources')?></div><?php
        }
    }
    /**
     * Renders a single resource description from the list of resources for
     * a given wiki page
     * @param int $i index in list of resources the current resource is
     *    (used when writing out element id's of tags to make unique)
     * @param bool &$is_first is this the first resource to be drawn
     * @param array $resource assiative array of information about the
     *     resource to be rendered
     * @param string $base_url
     * @param string $token_string token_name=CRSF_TOKEN string for URL
     *      to stay logged in
     * @param string $url_prefix
     * @param string $url_is_folder_prefix
     * @param string $folder_prefix
     * @param array &$seen_resources
     * @param string $read_mode whether the readering should be for a media
     *      list in read mode (valye "read"), a source mode (value "source"),
     *      or for use on the edit task of any wiki page (value "")
     * @param bool $logged_in is the context for rendering the resource of
     *      of someone who is looged in or not
     * @param array $data associate array of values to be sent to and used by
     *      view for rendering
     */
    public function renderResource($i, &$is_first, $resource, $base_url,
        $token_string, $url_prefix, $url_is_folder_prefix, $folder_prefix,
        &$seen_resources, $read_mode, $logged_in, $data)
    {
        $name = $resource['name'];
        $hash_id = L\crawlHash($data['PAGE_ID'] . urlencode($name) .
            ($data['ORIGINAL_SUB_PATH'] ?? ""));
        $hash2_id = L\crawlHash($data['PAGE_ID'] . $name .
            ($data['ORIGINAL_SUB_PATH'] ?? ""));
        if (C\REDIRECTS_ON) {
            $thumb_prefix =  preg_replace("/\/-\//u", "/$token_string/",
                $data['RESOURCES_INFO']['thumb_prefix']);
            $athumb_prefix =  preg_replace("/\/-\//u", "/$token_string/",
                $data['RESOURCES_INFO']['athumb_prefix']);
        } else {
            $thumb_prefix = $data['RESOURCES_INFO']['thumb_prefix'] .
                "&amp;$token_string";
            $athumb_prefix = $data['RESOURCES_INFO']['athumb_prefix'] .
                "&amp;$token_string";
        }
        $default_thumb = C\SHORT_BASE_URL .
            $data['RESOURCES_INFO']['default_thumb'];
        $default_editable_thumb = C\SHORT_BASE_URL .
            $data['RESOURCES_INFO']['default_editable_thumb'];
        $default_folder_thumb = C\SHORT_BASE_URL .
            $data['RESOURCES_INFO']['default_folder_thumb'];
        if (!empty($data['RESOURCE_FILTER'])&&
            mb_stripos($name, $data['RESOURCE_FILTER']) === false) {
            return;
        }
        $name_parts = pathinfo($name);
        $written_name = $name;
        $use_editable_thumb = false;
        if (!empty($name_parts['extension'])) {
            if (in_array($name_parts['extension'], ['txt',
                'csv', 'tex', 'php', 'sql', 'html', 'java', 'py',
                'pl', 'P', 'srt'])) {
                $use_editable_thumb = true;
            } elseif (in_array($name_parts['extension'], ['mov',
                'mp4', 'm4v', 'webm', 'mkv', 'm2ts'])) {
                $written_name = $name_parts['filename'] .
                    "[".tl('wiki_element_video')."]";
            } elseif (in_array($name_parts['extension'], ['wav',
                'mp3','aac', 'aif', 'aiff', 'oga', 'ogg', "m4a"])) {
                $written_name = $name_parts['filename'] .
                    "[".tl('wiki_element_audio')."]";
            } else if ($name_parts['extension'] == "vtt") {
                if (!empty($read_mode)) {
                    return;
                }
                $use_editable_thumb = true;
            }
        }
        if (!empty($read_mode) && isset($seen_resources[$written_name])) {
            return;
        }
        $is_list = false;
        $is_grid = false;
        $is_detail = false;
        if (empty($data['CURRENT_LAYOUT']) ||
            $data['CURRENT_LAYOUT'] == 'list') {
            $is_list = true;
        } else if ($data['CURRENT_LAYOUT'] == 'grid') {
            $is_grid = true;
        } else {
            $is_detail = true;
        }
        $seen_resources[$written_name] = true;
        $disabled = " disabled='disabled' ";
        if (!empty($data['CAN_EDIT']) && !empty($resource['is_writable'])) {
            $disabled = "";
        }
        if (empty($read_mode)) {
            $written_name = $name;
        }
        $thumb_connect = (C\REDIRECTS_ON)
            ? "/" : "&amp;n=";
        $name_connect = (C\REDIRECTS_ON &&
            !$url_is_folder_prefix)
            ? "/" : "&amp;n=";
        $encode_name = urlencode($name);
        if ($read_mode == "source"){
            $url_prefix = preg_replace("/arg=source/", "arg=media",
                $url_prefix);
        }
        $current_url = "$url_prefix$name_connect$encode_name";
        $clear_url = "$folder_prefix&amp;clear=" .
            $encode_name;
        $current_thumb = "$thumb_prefix$thumb_connect" .
            $encode_name;
        $current_animated_thumb = "$athumb_prefix$thumb_connect" .
            $encode_name;
        $is_a_default_thumb = false;
        if (!empty($data['SUB_PATH'])) {
            if (strpos($current_url, "sf=") === false &&
                $url_is_folder_prefix) {
                $encode_sub_path = urlencode($data['SUB_PATH']);
                $add_sub_path = "&amp;sf=$encode_sub_path";
                $current_url .= $add_sub_path;
                $clear_url .= $add_sub_path;
            }
            if (!$resource['has_thumb'] ||
                ($use_editable_thumb && empty($read_mode))) {
                $current_thumb = $default_thumb;
                $is_a_default_thumb = true;
                if (empty($read_mode) &&!$disabled &&
                    $use_editable_thumb) {
                    $current_thumb = $default_editable_thumb;
                    $current_url = "$folder_prefix&amp;sf=".
                        urlencode($data['SUB_PATH']) . "&amp;n=".
                        $encode_name;
                }
            }
            if (!empty($resource['is_dir'])) {
                $current_url = "$folder_prefix&amp;sf=".
                    urlencode($data['SUB_PATH'])."/$name";
                $current_thumb = $default_folder_thumb;
                $is_a_default_thumb = true;
            }
        } else {
            if (!$resource['has_thumb'] ||
                ($use_editable_thumb && empty($read_mode))) {
                $current_thumb = $default_thumb;
                $is_a_default_thumb = true;
                if (empty($read_mode) &&!$disabled &&
                    $use_editable_thumb) {
                    $current_thumb = $default_editable_thumb;
                    $current_url = "$folder_prefix&amp;n=".
                        urlencode($name);
                }
            }
            if (!empty($resource['is_dir'])) {
                $current_url = "$folder_prefix&amp;sf=".
                    urlencode($name);
                $current_thumb = $default_folder_thumb;
                $is_a_default_thumb = true;
            }
        }
        $is_seen = !empty($_SESSION['seen_media']) &&
            in_array($hash_id, $_SESSION['seen_media']);
        $current_media_url = $current_url;
        $first_resource = "";
        if ($is_list) {
            $tr = "tr";
            $td = "td";
            $td_img = "td";
            ?><tr class='list-resource' ><?php
        } else if ($is_grid) {
            $tr = "div";
            $td = "div";
            $td_img = "div";
            $seen = ($is_seen) ? " seen-resource " : "";
            $click = " onclick='" .
                "clearResource(this.id, \"". $clear_url . "\")' ";
            ?><div class='grid-resource <?=$seen ?>' <?=$click;?> ><?php
        } else {
            $tr = "div";
            $td = "div";
            $td_img = "div";
            $data['original_MODE'] = $data['MODE'];
            $media_detail = ($data['MODE'] == 'edit') ?
                "arg=media-detail-edit&amp;page_id=" . $data["PAGE_ID"]:
                "arg=media-detail-read";
            $data['MODE'] == 'read';
            $double_click_url = $current_url;
            $current_media_url = preg_replace('/arg=(media|edit|source)/',
                $media_detail, $current_url);
            if ($is_first) {
                $is_first = false;
                $detail_id = $data['PAGE_ID'];
                $detail_id .= (empty($data['SUB_PATH'])) ?
                    "" : base64_encode($data['SUB_PATH']);
                $reset_detail = (empty($data['RESET_DETAIL'])) ? "" :
                    "if (localStorage) {" .
                        "localStorage.removeItem('detail$detail_id');" .
                        "localStorage.removeItem('selected$detail_id');" .
                    "}";
                $first_resource = "<script>" .
                    "function changeDetail(id, url)".
                    "{".
                        "let detail = document.getElementById('detail-item');".
                        "let mode = '{$data['original_MODE']}';" .
                        "if (mode == 'edit') { url = url.replace(".
                            "'arg=media-detail-read','arg=media-detail-edit');".
                        "} else { url = url.replace(".
                            "'arg=media-detail-edit','arg=media-detail-read');".
                        "}".
                        "detail.innerHTML = '<iframe src=\"'+ url +'\" >' +" .
                            "'</iframe>';" .
                        "if (localStorage) {".
                            "localStorage.setItem('detail$detail_id', url);" .
                            "let old_selected_id = " .
                                "localStorage.getItem('selected$detail_id');" .
                            "if (old_selected_id) {" .
                                "let old_selected =".
                                    "document.getElementById(old_selected_id);".
                                "old_selected.classList.remove(" .
                                    "'back-aliceblue')" .
                            "}" .
                            "localStorage.setItem('selected$detail_id', id);" .
                        "}".
                        "let selected_detail = document.getElementById(".
                            "id);".
                        "selected_detail.classList.add('back-aliceblue');".
                    "}" .
                    $reset_detail .
                    "let detail_url;" .
                    "let selected_detail_id;" .
                    "if (!localStorage || !(detail_url = ".
                        "localStorage.getItem('detail$detail_id')) ||".
                            "!(selected_detail_id = ".
                            "localStorage.getItem('selected$detail_id'))) {".
                        "detail_url = '$current_media_url';".
                        "selected_detail_id = '$hash2_id';" .
                    "};" .
                    "window.addEventListener('load', (event) => {".
                        "changeDetail(selected_detail_id, detail_url); });" .
                    "</script>";
            }
            ?>
            <div id='<?= $hash2_id ?>' class='detail-resource' ><?php
        }
        if ($is_seen && $is_list) {
            e("<$td class='view-indicator huge-font'><span " .
                "id='$hash2_id' class='marked' onclick='" .
                "clearResource(this.id, \"". $clear_url . "\")' ".
                ">&diams;</span></$td>");
        } else {
            e("<$td class='view-indicator'></$td>");
        }
        $animated_thumb_info = "";
        if ($resource['has_animated_thumb']) {
            $animated_thumb_info = "class='animated' " .
                "data-src='$current_animated_thumb' ".
                "onmouseover= 'let src = this.src; ".
                "this.src = this.dataset.src; ".
                "this.dataset.src =src' " .
                "onmouseout= 'let src = this.src; ".
                "this.src = this.dataset.src; ".
                "this.dataset.src =src' ";
        }
        $dbl_click = "";
        $style = ($is_detail || $is_grid) ? " style='min-width:120px;' " : "";
        if ($is_detail) {
            $current_url = "javascript:changeDetail(\"$hash2_id\",".
                "\"$current_media_url\");";
            $dbl_click = "ondblclick='location = \"$double_click_url\";'";
        }
        $num_files_indicator = "";
        if (!empty($resource['is_dir'])) {
            if (isset($resource['num_files'])) {
                $num_files_indicator = "<div class='white back-blue badge'>".
                    $resource['num_files'] ."</div>";
            }
        }
        $thumb_class = ($is_a_default_thumb) ? ' class="default-thumb" ' : "";
        e("<$td_img class='resource-thumb'>".
            "$num_files_indicator<a href='$current_url'  $dbl_click >");
        e("<img $style loading='lazy' $thumb_class src='" . $current_thumb .
            "'  alt='$written_name'  $animated_thumb_info >");
        e("</a>$first_resource</$td>");
        if (!empty($read_mode)) {
            e("<$td><a href='$current_url'>".
                "$written_name</a></$td>");
        } else {
            // need tabindex to allow focus-within to work Safari
            e("<$td class='resource-field' tabindex='0' ><input type='text' ".
                "id='resource-$i' aria-label='".tl('wiki_element_name')."' ".
                "value='".str_replace("'", "&#39;", $name).
                "' $disabled ><br>");
            if (!$disabled) {
                ?><script>
                res = document.getElementById('resource-<?=$i?>');
                res.addEventListener("keyup", function (event) {
                    if (event.keyCode == 13) {
                        renameResource("<?= urlencode($name);?>", <?= $i ?>);
                    }
                });
                </script>
                <button onclick='renameResource("<?=
                urlencode($name);?>",
                <?= $i ?>)' ><?=
                tl('wiki_element_rename') ?></button><?php
            }
            if (!$disabled && empty($resource['is_dir'])
                && (!isset($data['page_type']) ||
                $data['page_type'] != 'media_list')) {
                $resource_sub_path = empty($data['SUB_PATH']) ?
                    "" : $data['SUB_PATH'] . "|";
                ?>
                <script>
                document.write(
                "<button onclick='alert(\"((resource:<?=$resource_sub_path .
                    urlencode($name) . "|" .
                tl('wiki_element_resource_description', $name) ."))" ?>\")' ><?=
                tl('wiki_element_wiki_code') ?></button>");
                </script><?php
            }
            $append = "";
            if (isset($data['OTHER_BACK_URL'])) {
                $append .= $data['OTHER_BACK_URL'];
            }
            if (!$disabled && !empty($resource['is_compressed'])) {
                $extract_url = $base_url .
                    "&amp;arg=edit&amp;extract=". urlencode($name) .
                        $append;
                if (!empty($data['SUB_PATH'])) {
                    $extract_url .= "&amp;sf=". urlencode($data['SUB_PATH']);
                }?>
                <a class="media-anchor-button"
                href='<?=$extract_url
                ?>'><?=tl('wiki_element_extract');?></a><?php
            }
            $copy_url = $base_url .
                "&amp;arg=edit&amp;clip_copy=". urlencode($name) . $append;
            if (!empty($data['SUB_PATH'])) {
                $copy_url .= "&amp;sf=". urlencode($data['SUB_PATH']);
            }?>
            <a class="media-anchor-button" href='<?=$copy_url
                ?>'><?=tl('wiki_element_clip_copy');?></a><?php
            if (!$disabled) {
                $cut_url = $base_url .
                    "&amp;arg=edit&amp;clip_cut=". urlencode($name) . $append;
                if (!empty($data['SUB_PATH'])) {
                    $cut_url .= "&amp;sf=" . urlencode($data['SUB_PATH']);
                }?>
                <a class="media-anchor-button"
                href='<?=$cut_url
                ?>'><?=tl('wiki_element_clip_cut');?></a><?php
            }
            e("</$td>");
            if (!$_SERVER["MOBILE"]) {
                e("<$td>" . L\intToMetric($resource['size']) .
                    "B</$td>");
                e("<$td>" . date("r", $resource['modified']) .
                    "</$td>");
            }
        }
        e("</$tr>");
    }
    /**
     * Used to render the dropdown that lists paths within media lists folders,
     * recent wiki pages, and groups a user has been to
     *
     * @param string $dropdown_id element id of select tag to be used for
     *      dropdown
     * @param array $data set up in controller and SocialComponent with
     *      data fields view and this element are supposed to render
     * @param array $options if nonempty, then this should be items, key-values
     *      in the form (url => label), to list first in dropdown
     * @param string $selected_url url which is selected by default in dropdown.
     * @param string $top_name name of root media list folder (defaults
     *      to something like "Root Folder" in the language of current locale)
     * @param string $render_type can be: "paths" if just listing folder path
     *      in wiki page resource folder, "just_groups_and_pages" if want a list
     *      of recent groups and wiki pages viewed, or "all" if want both
     * @param boolean $as_list whether to output the result as a dropdown
     *      or as an unordered list.
     * @param string $class_list list of css classes to add to top div in
     *      what is rendered
     */
    public function renderPath($dropdown_id, $data, $options,
        $selected_url = "", $top_name = "", $render_type = "paths",
        $as_list = false, $class_list = "")
    {
        $folder_prefix = "";
        if (empty($options)) {
            $options = [];
        } else if ($render_type != "just_groups_and_pages") {
            $folder_prefix = key($options);
            $root_name = $options[$folder_prefix];
            if (empty($root_name)) {
                $root_name = tl('wiki_element_root_folder');
            }
            $options[$folder_prefix] = $root_name;
        }
        $path_parts = (empty($data['SUB_PATH'])) ?
            [] : array_filter(explode("/", $data['SUB_PATH']));
        $sub_path = "";
        $selected_set = ($selected_url) ? true : false;
        if ($render_type == "just_groups_and_pages" && empty($options)) {
            $options = array_merge([-1 => tl('wiki_element_recent_places')],
                $options);
        } else if (in_array($render_type, ['all', 'paths'])) {
            $num_parts = count($path_parts);
            $i = 1;
            foreach ($path_parts as $part) {
                $sub_path .= $part;
                if ($i == $num_parts) {
                    if ($top_name == "") {
                        $options = array_merge([-1 => $part], $options);
                    } else {
                        $options = array_merge([-1 => $top_name,
                           "&amp;sf=$sub_path" => $part], $options);
                    }
                    break;
                } else {
                    $options = array_merge(
                        ["&amp;sf=$sub_path" => $part], $options);
                }
                $i++;
                $sub_path .= '/';
            }
            if ($num_parts == 0) {
                if ($top_name == "" && !empty($part)) {
                    $options = array_merge([-1 => $part], $options);
                } else if (!empty($top_name)){
                    $options = array_merge([-1 => $top_name], $options);
                }
                $selected_set = true;
            }
            $options = array_merge([tl('wiki_element_paths') => ""],
                $options);
        }
        if (in_array($render_type, ['all', 'just_groups_and_pages'])) {
            if (!empty($data['RECENT_PAGES'])) {
                $token_string = C\CSRF_TOKEN . "=". $data[C\CSRF_TOKEN];
                $add_options = [tl('wiki_element_recent_pages') => ""];
                $found_new = false;
                foreach ($data['RECENT_PAGES'] as $page_name => $url) {
                    $out_token = (strstr($url, C\CSRF_TOKEN) === false) ?
                        $token_string : "";
                    if (empty($options[$url . $out_token])) {
                        $add_options[$url . $out_token] = $page_name;
                        $found_new = true;
                    }
                }
                if ($found_new) {
                    $options = array_merge($options, $add_options);
                }
            }
            if (!empty($data['RECENT_GROUPS'])) {
                $token_string = C\CSRF_TOKEN . "=". $data[C\CSRF_TOKEN];
                $add_options = [tl('wiki_element_recent_groups') => ""];
                $found_new = false;
                foreach ($data['RECENT_GROUPS'] as $group_name => $url) {
                    $out_token = (strstr($url, C\CSRF_TOKEN) === false) ?
                        $token_string : "";
                    if (!empty($out_token) && (strstr($url, "?") === false)) {
                        $url .= "?";
                    }
                    if (empty($options[$url . $out_token])) {
                        $add_options[$url . $out_token] =
                            $group_name ;
                        $found_new = true;
                    }
                }
                if ($found_new) {
                    $options = array_merge($options, $add_options);
                }
            }
        }
        if (count($options) <= 1) {
            $options[tl('wiki_element_login_for_recent')] = "";
        }
        $this->view->helper('options')->renderLinkDropDown($dropdown_id,
            $options, $selected_url, $folder_prefix, $as_list,
            $class_list);
        return $sub_path;
    }
    /**
     * Used to draw a list of Wiki Pages for the current group. It also
     * draws a search form and can be used to create pages
     *
     * @param array $data fields for the current controller, CSRF_TOKEN
     *     etc needed to render the search for and paging queries
     * @param bool $can_edit whether the current user has permissions to
     *     edit or create this page
     * @param bool $logged_in whether current user is logged in or not
     */
    public function renderPages($data, $can_edit, $logged_in)
    {
        $icon_helper = $this->view->helper('iconlink');
        $token_string = ($logged_in) ? C\CSRF_TOKEN ."=". $data[C\CSRF_TOKEN] :
            "";
        $group_id = $data["GROUP"]["GROUP_ID"];
        $controller = $data['CONTROLLER'];
        $create_query = htmlentities(B\wikiUrl(preg_replace("/\s+/u", "_",
            $data["FILTER"]), true, $controller, $group_id)) . $token_string .
            "&amp;arg=edit";
        $paging_query = htmlentities(B\wikiUrl("pages", true, $controller,
            $group_id)) . $token_string;
        if (!empty($data['FILTER'])) {
            $paging_query .= "&amp;filter=" . $data['FILTER'];
        }
        ?><h2 class="page-list-header-footer"><?=
            tl("wiki_element_wiki_create_find", $data["GROUP"]["GROUP_NAME"])
        ?></h2><?php
        ?>
        <form id="editpageForm" method="get" class="page-list-header-footer">
        <input type="hidden" name="c" value="<?=$data['CONTROLLER'] ?>" >
        <input type="hidden" name="<?= C\CSRF_TOKEN ?>" value="<?=
            $data[C\CSRF_TOKEN] ?>" >
        <input type="hidden" name="a" value="wiki" >
        <input type="hidden" name="arg" value="pages" >
        <input type="hidden" name="group_id" value="<?=
            $data['GROUP']['GROUP_ID'] ?>" >
        <?php
        $this->view->helper("options")->renderLinkDropDown(
        "page-sort-fields", $data['sort_fields'] ?? "",
        $data['CURRENT_SORT']?? "", "$paging_query&amp;sort=",
        false, "",
        "<span class='hover-lightgray' role='img' aria-label='" .
        tl('wiki_element_sort_order') . "'>&#8645;</span>"); ?>
        <div class="search-filter-container">
        <input type="search" name="filter" class="extra-wide-field"
            maxlength="<?= C\SHORT_TITLE_LEN ?>"
            placeholder="<?= tl("wiki_element_filter_or_create")
            ?>" value="<?= $data['FILTER'] ?>" >
        </div>
        <button class="button-box"
            type="submit"><?=tl('wiki_element_go') ?></button>
        </form>
        <?php
        if ($data["FILTER"] != "") {
            ?><div class='page-list-header-footer'>
            <a href='<?= $create_query ?>'><?=tl("wiki_element_create_page",
                $data['FILTER']) ?></a></div><?php
        }
        ?>
        <div>&nbsp;</div>
        <?php
        if ($data['PAGES'] != []) {
            $time = time();
            foreach ($data['PAGES'] as $page) {
                if ($page['TYPE'] == 'page_alias' && isset($page['ALIAS'])) {
                    $page["DESCRIPTION"] = tl('wiki_element_redirect_to').
                        " <a href='".htmlentities(B\wikiUrl($page['ALIAS'],
                        true, $controller, $group_id)) . $token_string .
                        "'>".  urldecode($page['ALIAS']) . "</a>";
                } else {
                    $page["DESCRIPTION"] = strip_tags($page["DESCRIPTION"]);
                }
                ?>
                <div class='wiki-page-list-result'>
                <a href="<?= htmlentities(B\wikiUrl($page['TITLE'],
                    true, $controller, $group_id)) . $token_string
                    ?>&amp;noredirect=true" <?php
                    if ($data["OPEN_IN_TABS"]) { ?>
                        target="_blank" rel="noopener"<?php
                    }?>><?=urldecode($page["SHOW_TITLE"]) ?></a> <?php
                if ($can_edit) {
                    $tab_target = (empty($data['OPEN_IN_TABS'])) ?
                        "" : "_blank";
                    $icon_helper->renderButton(htmlentities(
                        B\wikiUrl($page['TITLE'], true, $controller,$group_id)).
                        $token_string . "&amp;noredirect=true&amp;arg=edit",
                        'edit', "", false, "float-opposite ".
                        "small-margin no-padding", "", false, $tab_target);
                } else {
                    $tab_target = (empty($data['OPEN_IN_TABS'])) ?
                        "" : "_blank";
                    $icon_helper->renderButton(htmlentities(
                        B\wikiUrl($page['TITLE'], true, $controller,$group_id)).
                        $token_string . "&amp;noredirect=true&amp;arg=source",
                        'view_source', "", false, "float-opposite ".
                        "small-margin no-padding", "", false, $tab_target);
                }
                ?></br >
                <?= $page["DESCRIPTION"] ?><br>
                <span class="float-opposite gray"><?=
                    $this->view->helper("feeds")->getPubdateString(
                    $time, $page['LAST_MODIFIED']); ?></span>
                </div>
                <?php
            }?>
            <div class="page-list-header-footer"><?php
            $this->view->helper("pagination")->render(
                $paging_query, $data['LIMIT'], $data['RESULTS_PER_PAGE'],
                $data['TOTAL_ROWS']);?>
            </div><?php
        }
        if (empty($data['PAGES'])) {
            ?><div class='page-list-header-footer'><?=
            tl('wiki_element_no_pages', "<b>" . L\getLocaleTag() .
            "</b>")?></div><?php
        }
    }
    /**
     * Used to draw the page which displays all wiki pages
     *    that link a wiki page with a particular relationship type
     *
     * @param array $data fields contain info about all such wiki pages
     */
    public function renderRelationships($data)
    {
        $logged_in = !empty($data["ADMIN"]);
        if ($logged_in) {
            $csrf_token = C\CSRF_TOKEN."=".$data[C\CSRF_TOKEN];
        }
        $page_name = $data['PAGE_NAME'];
        $page_id = $data['PAGE_ID'];
        $url_main = htmlentities(B\wikiUrl($page_name, true,
            $data['CONTROLLER'], $data['GROUP_ID'])) . $csrf_token;
        //display pages that link to the particular page
        ?><table><tr><td><?php
        if (!empty($data["PAGES_THAT_LINK_TO"])) {
            foreach ($data["PAGES_THAT_LINK_TO"] as $key => $value) {
                $var = $data["PAGES_THAT_LINK_TO"][$key]["PAGES_LINKING_TO"];
                $url = htmlentities(B\wikiUrl($var, true, $data['CONTROLLER'] ,
                    $data['GROUP_ID'])).$csrf_token."&amp;arg=relationships" .
                    "&amp;page_id=" .
                    $data["PAGES_THAT_LINK_TO"][$key]["PAGE_ID"] .
                    "&amp;reltype=" . $data["REL-TYPE"];?>
                <div class="center"><a href='<?=$url?>' ><?=$var?>
                    </a></div><?php
            }
        }
        ?></td><tr><?php
        $rel_top = (!empty($data["TOTAL_TO_PAGES"])) ? "rel-type-top" : "";
        ?>
        <tr><td class="<?=$rel_top ?> center">|</td></tr><?php
        //displaying the middle table - Current Page Name
        ?><tr><td><div class="rel-type-current"><b><a
            href='<?=$url_main ?>' ><?=$page_name?></a></b><br><?php
            if (empty($data["RELATIONSHIPS"])) {
                e("<b class='small-font'>".tl('wiki_element_no_cur_rel').
                    "</b>");
            } else {
                foreach ($data["RELATIONSHIPS"] as $key => $value) {
                    $url = $url_main . "&amp;arg=relationships" .
                        "&amp;page_id=" . $page_id;
                    $relationship_type =
                        $data["RELATIONSHIPS"][$key]["RELATIONSHIP_TYPE"];
                    $url .= "&amp;reltype=" . $relationship_type;
                    if (!empty($data["REL-TYPE"]) &&
                        $relationship_type == $data["REL-TYPE"]) {
                        $relationship_type = "<b>$relationship_type</b>";
                    }
                    e("<a class='small-font' href='$url'>".
                        "$relationship_type</a><br>");
                }
            }
           ?></div></td></tr><?php
        $rel_bottom = (!empty($data["TOTAL_FROM_PAGES"])) ?
            "rel-type-bottom" : "";
        ?>
        <tr><td class="<?=$rel_bottom ?> center">|</td></tr><?php
        //display pages that link from the particular page
        ?><tr><td><?php
        if (!empty($data["PAGES_THAT_LINK_FROM"])) {
            foreach ($data["PAGES_THAT_LINK_FROM"] as $key => $value) {
                $var =
                    $data["PAGES_THAT_LINK_FROM"][$key]["PAGES_LINKING_FROM"];
                $url = htmlentities(B\wikiUrl($var, true,
                    $data['CONTROLLER'], $data['GROUP_ID'])).$csrf_token.
                    "&amp;arg=relationships"."&amp;page_id=".
                    $data["PAGES_THAT_LINK_FROM"][$key]["PAGE_ID"].
                    "&amp;reltype=".$data["REL-TYPE"];
                ?><div class="center"><a href='<?=$url?>'><?=$var
                ?></a></div><?php
            }
        }
        ?></td></tr></table><?php
    }
    /**
     * Used to draw the revision history page for a wiki document
     * Has a form that can be used to draw the diff of two revisions
     *
     * @param array $data fields contain info about revisions of a Wiki page
     */
    public function renderHistory($data)
    {
        $base_query = htmlentities(B\wikiUrl("", true, $data['CONTROLLER'],
            $data["GROUP"]["GROUP_ID"]) .C\CSRF_TOKEN."=".
            $data[C\CSRF_TOKEN]);
        $append = "";
        if (isset($data['OTHER_BACK_URL']) && $data['OTHER_BACK_URL'] != '') {
            $append = $data['OTHER_BACK_URL'];
        }
        $edit_or_source = (!empty($data['CAN_EDIT'])) ? 'edit' : 'source';
        if (count($data['HISTORY']) > 1) { ?>
            <div>
            <form id="differenceForm" method="get">
            <input type="hidden" name="c" value="<?=$data['CONTROLLER']
             ?>" >
            <input type="hidden" name="<?=C\CSRF_TOKEN ?>" value="<?=
                $data[C\CSRF_TOKEN] ?>" >
            <input type="hidden" name="a" value="wiki" >
            <input type="hidden" name="arg" value="history" >
            <input type="hidden" name="group_id" value="<?=
                $data['GROUP']['GROUP_ID'] ?>" >
            <input type="hidden" name="page_id" value="<?=
                $data["PAGE_ID"] ?>" >
            <input type="hidden" name="diff" value="1" >
            <b><?=tl('wiki_element_difference') ?></b>
            <input type="text" id="diff-1" name="diff1"
                value="<?=$data['diff1'] ?>" > -
            <input type="text" id="diff-2" name="diff2"
                value="<?= $data['diff2'] ?>" >
            <button class="button-box" type="submit"><?=
                tl('wiki_element_go') ?></button>
            </form>
            </div>
            <?php
        }
        ?>
        <div>&nbsp;</div>
        <?php
        $time = time();
        $feed_helper = $this->view->helper("feeds");
        $base_query .= "&amp;arg=history&amp;page_id=".$data["PAGE_ID"];
        $first = true;
        foreach ($data['HISTORY'] as $item) {
            ?>
            <div class='group-result'>
            <?php
            if (count($data['HISTORY']) > 1) { ?>
                (<a href="javascript:updateFirst('<?=$item['PUBDATE']
                    ?>');" ><?= tl("wiki_element_diff_first")
                    ?></a> | <a href="javascript:updateSecond('<?=
                    $item['PUBDATE']?>');" ><?= tl("wiki_element_diff_second")
                    ?></a>)
                <?php
            } else { ?>
                (<b><?= tl("wiki_element_diff_first")
                    ?></b> | <b><?= tl("wiki_element_diff_second")
                    ?></b>)
                <?php
            }
            e("<a href='$base_query&show={$item['PUBDATE']}'>" .
                date("c",$item["PUBDATE"])."</a>. <b>{$item['PUBDATE']}</b>. ");
            e(tl("wiki_element_edited_by", $item["USER_NAME"]));
            if (strlen($item["EDIT_REASON"] ?? "") > 0) {
                e("<i>{$item["EDIT_REASON"]}</i>. ");
            }
            e(tl("wiki_element_page_len", $item["PAGE_LEN"])." ");
            if (!empty($data['CAN_EDIT'])) {
                if ($first && $data['LIMIT'] == 0) {
                    e("[<b>".tl("wiki_element_revert")."</b>].");
                } else {
                    e("[<a href='$base_query&amp;revert=".$item['PUBDATE'].
                    "'>".tl("wiki_element_revert")."</a>].");
                }
            }
            $first = false;
            $next = $item['PUBDATE'];
            ?>
            </div>
            <div>&nbsp;</div>
            <?php
        }?>
        <div class="page-list-header-footer"><?php
        $this->view->helper("pagination")->render(
            $base_query,
            $data['LIMIT'], $data['RESULTS_PER_PAGE'], $data['TOTAL_ROWS']);
        ?></div>
        <script>
        function updateFirst(val)
        {
            elt('diff-1').value=val;
        }
        function updateSecond(val)
        {
            elt('diff-2').value=val;
        }
        </script>
        <?php
    }
    /**
     * Used to drawn the form that let's someone see the source of a wiki page
     *
     * @param array $data fields contain data about the page being
     *      edited. In particular, PAGE contains the raw page data
     */
    public function renderSourcePage($data)
    {
        $icon_helper = $this->view->helper('iconlink');
        $simple_base_url = B\wikiUrl("", true,
            $data['CONTROLLER'], $data['GROUP']['GROUP_ID']) .
            C\CSRF_TOKEN . '=' . $data[C\CSRF_TOKEN];
        $base_url = htmlentities($simple_base_url);
        $simple_view_url = B\wikiUrl($data['PAGE_NAME'], true,
           $data['CONTROLLER'], $data['GROUP']['GROUP_ID']) .
           C\CSRF_TOKEN . '=' . $data[C\CSRF_TOKEN];
        $simple_current_url = $simple_view_url . "&arg=source";
        $is_settings_view = !empty($data['settings']) &&
            $data['settings'] != "false";
        $is_resources_view = !empty($data['resources']) &&
            $data['resources'] != "false";
        $is_media_list =
            !empty($data['page_type']) && $data['page_type'] == 'media_list';
        $is_page_alias =
            !empty($data['page_type']) && $data['page_type'] == 'page_alias';
        $is_shortener =
            !empty($data['page_type']) && $data['page_type'] == 'url_shortener';
        $is_share =
            !empty($data['page_type']) && $data['page_type'] == 'share';
        if (!empty($data['SUB_PATH'])) {
            $simple_view_url .= "&sf=".urlencode($data['SUB_PATH']);
            $simple_current_url .= "&sf=".urlencode($data['SUB_PATH']);
        }
        $current_url = htmlentities($simple_current_url);
        $new_settings = $is_settings_view ? "&amp;settings=false" :
            "&amp;settings=true";
        $new_resources = $is_resources_view ? "&amp;resources=false" :
            "&amp;resources=true";
        $is_settings_view = !empty($data['settings']) &&
            $data['settings'] != "false";
        $is_resources_view = !empty($data['resources']) &&
            $data['resources'] != "false";
        $settings_toggle_url = $current_url . $new_settings;
        $resources_toggle_url = $current_url . $new_resources;
        $append = "";
        if (isset($data['OTHER_BACK_URL'])) {
            $append = $data['OTHER_BACK_URL'];
        }
        $icon_helper = $this->view->helper('iconlink');
        if ($is_settings_view || $is_resources_view) {
            $toggle_url = ($is_settings_view) ? $settings_toggle_url :
                $resources_toggle_url;
            ?>
            <div class="float-opposite" ><?=
            $this->view->helper('close')->render($toggle_url);
            ?></div>
            <?php
        } else { ?>
            <div class="float-opposite wiki-history-discuss" >
            <?=
            $icon_helper->renderButton( $base_url . $append .
                '&amp;arg=history&amp;page_id='.$data['PAGE_ID'], "history");?>
            </div><?php
        } ?>
        <form id="editpageForm" onsubmit="
            var caret_pos = elt('caret-pos');
            var scroll_top = elt('scroll-top');
            var wiki_page = elt('wiki-page');
            if (caret_pos && scroll_top && wiki_page) {
                caret_pos.value =
                (wiki_page.selectionStart) ?
                wiki_page.selectionStart : 0;
                scroll_top.value= (wiki_page.scrollTop) ?
                wiki_page.scrollTop : 0;
            }" >
            <input type="hidden" name="c" value="<?=$data['CONTROLLER']
            ?>" >
            <input type="hidden" name="<?=C\CSRF_TOKEN ?>" value="<?=
                $data[C\CSRF_TOKEN] ?>" >
            <input type="hidden" name="a" value="wiki" >
            <input type="hidden" name="arg" value="source" >
            <?php
            if (isset($data['BACK_PARAMS'])) {
                foreach ($data["BACK_PARAMS"] as
                         $back_param_key => $back_param_value) {
                    e('<input type="hidden" '
                        . 'name="' . $back_param_key .
                        '" value="' .
                        $back_param_value
                        . '" >');
                }
            }
            ?>
            <input type="hidden" name="group_id" value="<?=
                $data['GROUP']['GROUP_ID'] ?>" >
            <input type="hidden" name="page_name" value="<?=
                $data['PAGE_NAME'] ?>" >
            <input type="hidden" name="caret" id="caret-pos" >
            <input type="hidden" name="scroll_top" id="scroll-top" >
            <input type="hidden" id="p-settings" name="settings" value="<?=
                $data['settings'] ?>" >
            <div class="top-margin">
                <b><?=tl('wiki_element_locale_name',
                    $data['CURRENT_LOCALE_TAG']) ?></b><br>
                <b><label for="wiki-page"><?php
                $human_page_name = preg_replace("/\_/", " ",
                    urldecode($data['PAGE_NAME']));
                e(tl('wiki_element_page', $human_page_name));
                ?></label></b><?php
                if (!$is_settings_view && !$is_resources_view) { ?>
                    <div id="toggle-settings">
                    <?php
                    $icon_helper->renderButton(['settings-toggle-button',
                        $settings_toggle_url], 'settings', "");
                    if (!$is_media_list && !$is_page_alias && !$is_share &&
                        !$is_shortener) {
                        $icon_helper->renderButton(
                            ['resources-toggle-button',
                            $resources_toggle_url], 'resources', "");
                    }?>
                    </div><?php
                } ?>
            </div>
            <div id='page-settings'>
            <div class="top-margin">
            <label for="page-type"><b><?=tl('wiki_element_page_type')
            ?></b></label><?php
            $this->view->helper("options")->render("page-type", "page_type",
                $data['page_types'], $data['current_page_type'], true,
                ['disabled' => 'disabled']);
            ?>
            </div>
            <div id='alias-type'>
            <div class="top-margin">
            <label for="page-alias"><b><?=tl('wiki_element_page_alias')
            ?></b></label><input type="text" id='page-alias' disabled="disabled"
                name="page_alias" value="<?= $data['page_alias']?>"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            </div>
            <div id='non-alias-type'>
            <div class="top-margin">
            <label for="page-border"><b><?=tl('wiki_element_page_border')
            ?></b></label><?php
            $this->view->helper("options")->render("page-border","page_border",
                $data['page_borders'], $data['page_border'], false,
                ['disabled' => 'disabled']);
            ?>
            </div>
            <div class="top-margin">
            <label for="page-toc"><b><?=tl('wiki_element_table_of_contents')
            ?></b></label><input type="checkbox" name="toc" value="true"
                <?php
                    $checked = (isset($data['toc']) && $data['toc']) ?
                    'checked="checked"' : '';
                    e( $checked );
                ?> id='page-toc' disabled="disabled" >
            </div>
            <div class="top-margin">
            <label for="page-title"><b><?=tl('wiki_element_title')
            ?></b></label><input type="text" id='page-title'
                disabled="disabled"
                name="title" value="<?=$data['title'] ?>"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-author"><b><?=tl('wiki_element_meta_author')
            ?></b></label><input type="text" id='meta-author'
                name="author" value="<?= $data['author']?>"
                disabled="disabled"
                maxlength="<?= C\LONG_NAME_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-robots"><b><?=tl('wiki_element_meta_robots')
            ?></b></label><input type="text" id='meta-robots'
                disabled="disabled"
                name="robots" value="<?= $data['robots'] ?>"
                maxlength="<?=C\LONG_NAME_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="meta-description"><b><?=
                tl('wiki_element_meta_description')
            ?></b></label>
            </div>
            <textarea id="meta-description" class="short-text-area"
                disabled="disabled"
                name="description" data-buttons='none'><?=$data['description']
            ?></textarea>
            <div class="top-margin">
            <label for="meta-properties"><b><?=
                tl('wiki_element_meta_properties')
            ?></b></label>
            </div>
            <div><?=tl('wiki_element_meta_property_format')?></div>
            <textarea id="meta-properties" class="short-text-area"
                disabled="disabled"
                name="properties" data-buttons='none'><?=$data['properties']
            ?></textarea><?php
            if (!empty($_SESSION['USER_ID']) &&
                $_SESSION['USER_ID'] == C\ROOT_ID) { ?>
                <div class="top-margin">
                <label for="alt-path"><b><?=tl('wiki_element_alternative_path')
                ?></b></label><input type="text" id='alt-path'
                    placeholder="<?=tl('wiki_element_empty_use_default')
                    ?>" name="alternative_path" value="<?=
                    $data['alternative_path'] ?>"
                    disabled="disabled"
                    maxlength="<?=C\LONG_NAME_LEN ?>" class="wide-field" >
                </div>
                <?php
            }
            ?>
            <div class="top-margin">
            <label for="page-header"><b><?=tl('wiki_element_page_header')
            ?></b></label><input type="text" id='page-header'
                name="page_header" value="<?=$data['page_header']?>"
                disabled="disabled"
                maxlength="<?=C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            <div class="top-margin">
            <label for="page-footer"><b><?=tl('wiki_element_page_footer')
            ?></b></label><input type="text" id='page-footer'
                name="page_footer" value="<?=$data['page_footer'] ?>"
                disabled="disabled"
                maxlength="<?= C\SHORT_TITLE_LEN ?>" class="wide-field" >
            </div>
            </div>
        </div><?php
        if (!$is_media_list && !$is_resources_view && !$is_settings_view) {?>
            <div id='page-container'><textarea id="wiki-page"
                class="tall-text-area" name="page" data-buttons='none'
                disabled="disabled"><?= $data['PAGE']
                ?></textarea>
            </div><?php
        } ?>
        </form>
        <?php
        if (($is_media_list && !$is_settings_view )|| $is_resources_view) {?>
            <div id="page-resources">
            <h3><?= tl('wiki_element_page_resources')?></h3>
            <p><?= tl('wiki_element_resources_info') ?></p>
            </div><?php
            $this->renderResources($data, "source");
            ?></div>
            <?php
        }
    }
    /**
     * The controller used to display a wiki page might vary (could be
     * group or static). Links within a wiki page need to be updated
     * to reflect which controller is being used. This method does the
     * update.
     *
     * @param int $group_id id of wiki page the passed page belongs to
     * @param array $data fields etc which will be sent to the view
     * @param string $pre_page a wiki page where links,etc have not yet
     *      had dynamic substitutions applied
     * @return string page after subustitutions
     */
    public function dynamicSubstitutions($group_id, $data, $pre_page)
    {
        $csrf_token = "";
        $no_amp_csrf_token = "";
        $no_right_amp_csrf_token = "";
        $resource_csrf_token = "";
        $resource_no_amp_csrf_token = "";
        $resource_no_right_amp_csrf_token = "";
        if (!empty($data['ADMIN'])) {
            $resource_token = $data[C\CSRF_TOKEN];
            if ($group_id == C\PUBLIC_GROUP_ID ||
                (!empty($data["GROUP"]["GROUP_ID"]) &&
                !empty($data["GROUP"]["REGISTER_TYPE"]) &&
                $group_id == $data["GROUP"]["GROUP_ID"]) &&
                $data["GROUP"]["REGISTER_TYPE"] == C\PUBLIC_JOIN) {
                $resource_token = str_pad("", 11,  "0");
            }
            $no_amp_csrf_token = C\CSRF_TOKEN . "=" . $data[C\CSRF_TOKEN];
            $resource_no_amp_csrf_token = C\CSRF_TOKEN . "=" . $resource_token;
            $no_right_amp_csrf_token =
                "&amp;". $no_amp_csrf_token;
            $resource_no_right_amp_csrf_token = "&amp;".
                $resource_no_amp_csrf_token;
            $csrf_token = $no_right_amp_csrf_token . "&amp;";
            $resource_csrf_token = $resource_no_right_amp_csrf_token . "&amp;";
        }
        if ($data['CONTROLLER'] == 'static') {
            $address = C\SHORT_BASE_URL . "p/";
            $pre_address = B\controllerUrl("group", true) .
                "{$csrf_token}a=wiki&amp;arg=read&amp;";
        } else {
            $pre_address = B\controllerUrl($data['CONTROLLER'], true) .
                "{$csrf_token}a=wiki&amp;arg=read&amp;";
            $address = $pre_address .
                "group_id=$group_id&amp;page_name=";
        }
        $pre_page = preg_replace('/@@(.*)@(.*)@@/',
            $pre_address . "group_name=$1&amp;page_name=$2", $pre_page);
        $pre_page = preg_replace('/\[{controller_and_page}\]/', $address,
            $pre_page);
        $pre_page = preg_replace('/\[{controller}\]/', $data['CONTROLLER'],
            $pre_page);
        $pre_page = preg_replace('/\/\[{token}\]\//',
            (empty($no_amp_csrf_token)) ? "/-/" : "/$no_amp_csrf_token/" ,
            $pre_page);
        $pre_page = preg_replace('/\[{token}\]/', $csrf_token,
            $pre_page);
        $pre_page = preg_replace('/\/\[{rtoken}\]\//',
            (empty($no_amp_csrf_token)) ? "/-/" :
            "/$resource_no_amp_csrf_token/" , $pre_page);
        $pre_page = preg_replace('/\[{rtoken}\]/', $resource_csrf_token,
            $pre_page);
        $pre_page = preg_replace('/\[{just\-token}\]/', $data[C\CSRF_TOKEN],
            $pre_page);
        $pre_page = preg_replace('/\[{image-captcha}\]/',
            "<img src='". ($data["CAPTCHA_IMAGE"] ?? "") ."' alt='captcha' >",
            $pre_page);
        $pre_page = preg_replace('/\[{username}\]/',
            $_SESSION['USER_NAME'] ?? "PUBLIC_USER", $pre_page);
        if (preg_match('/\[{form\-hash([^}]+)}\]/', $pre_page,
            $hash_matches) != false) {
            $page_hash = L\crawlHash(C\AUTH_KEY . $data[C\CSRF_TOKEN] .
                $hash_matches[1]);
            $pre_page = preg_replace('/\[{form-hash([^}]+)}\]/', $page_hash,
                $pre_page);
            if (preg_match_all('/\[{csv\-(.+)}\]/', $pre_page,
                $csv_field_matches, PREG_SET_ORDER) > 0) {
                foreach ($csv_field_matches as $csv_field_match) {
                    if (empty($csv_field_match[1])) {
                        continue;
                    } else if (substr($csv_field_match[1], 0, 8) == "checked-"){
                        $csv_field_name = substr($csv_field_match[1], 8);
                        $replace = (empty($_REQUEST[$csv_field_name])) ? "" :
                            ' checked="checked" ';
                    } else {
                        $csv_field_name = $csv_field_match[1];
                        $replace = $_REQUEST[$csv_field_name] ?? "";
                    }
                    $pre_page = str_replace($csv_field_match[0],
                        $replace, $pre_page);
                }
            }
        }
        if (stripos($pre_page, "[{recent_places}]") !== false) {
            ob_start();
            $this->renderPath("", $data, [], "", "",
                "just_groups_and_pages");
            $recent_dropdown = ob_get_clean();
            $pre_page = preg_replace('/\[{recent_places}\]/', $recent_dropdown,
                $pre_page);
        }
        return $pre_page;
    }
}
ViewGit