mambax7/gwiki

View on GitHub
admin/pages.php

Summary

Maintainability
D
2 days
Test Coverage
<?php
/**
 * admin/pages.php - manage wiki page revision
 *
 * @copyright  Copyright © 2013 geekwright, LLC. All rights reserved.
 * @license    gwiki/docs/license.txt  GNU General Public License (GPL)
 * @since      1.0
 * @author     Richard Griffith <richard@geekwright.com>
 * @package    gwiki
 */

use Xmf\Database\TableLoad;
use Xmf\Request;
use XoopsModules\Gwiki;
use XoopsModules\Gwiki\Helper;

//use Xmf\Database\TableLoad;

require_once __DIR__ . '/header.php';

require_once \dirname(__DIR__) . '/include/functions.php';
require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php';

$helper = Helper::getInstance();

$adminObject->displayNavigation(basename(__FILE__));

/**
 * @param $url
 * @param $params
 */
function post_clean_request($url, $params)
{
    foreach ($params as $key => &$val) {
        if (is_array($val)) {
            $val = implode(',', $val);
        }
        $post_params[] = $key . '=' . urlencode($val);
    }
    $post_string = implode('&', $post_params);

    $parts = parse_url($url);

    $fp = fsockopen($parts['host'], $parts['port'] ?? 80, $errno, $errstr, 30);

    $out = 'POST ' . $parts['path'] . " HTTP/1.1\r\n";
    $out .= 'Host: ' . $parts['host'] . "\r\n";
    $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out .= 'Content-Length: ' . mb_strlen($post_string) . "\r\n";
    $out .= "Connection: Close\r\n\r\n";
    if (isset($post_string)) {
        $out .= $post_string;
    }

    fwrite($fp, $out);
    fclose($fp);
}

/**
 * @param null $message
 */
function showPages($message = null)
{
    global $xoopsDB;
    echo <<<EOT
<style>
div.pagination.default {display:inline;}
form {display:inline;}
</style>
EOT;
    $total = 0;
    $limit = 10;
    $start = 0;
    $like  = '';
    if (Request::hasVar('start', 'GET')) {
        $start = Request::getInt('start', 0, 'GET');
    }
    if (Request::hasVar('like', 'GET')) {
        $like = cleaner($_GET['like']);
    }

    $sql = 'SELECT COUNT(*) FROM ' . $xoopsDB->prefix('gwiki_pageids');
    if (!empty($like)) {
        $sql .= " WHERE keyword LIKE '{$like}%' ";
    }
    $result = $xoopsDB->query($sql);
    if ($result) {
        $myrow = $xoopsDB->fetchRow($result);
        $total = $myrow[0];
    }

    echo '<form method="get"><b>' . _AD_GWIKI_KEYWORD_FILTER . '</b><input type="text" name="like"><input type="submit"></form><br>';
    adminTableStart(_AD_GWIKI_ADMINTITLE, 4);
    if (!empty($message)) {
        echo '<tr><td colspan="4" align="center"><br><b>' . $message . '</b><br><br></td></tr>';
    }
    echo '<tr><th width="15%">' . _AD_GWIKI_KEYWORD . '</th><th>' . _MD_GWIKI_TITLE . '</th><th width="5%">' . _AD_GWIKI_REVISIONS . '</th><th width="30%">' . _AD_GWIKI_ACTION . '</th></tr>';
    $sqlwhere = '';
    if (!empty($like)) {
        $sqlwhere = " WHERE t1.keyword LIKE '{$like}%' ";
    }
    $sql    = 'SELECT t1.keyword, COUNT(*), t2.title, t2.admin_lock, t2.active FROM ' . $xoopsDB->prefix('gwiki_pages') . ' t1 ' . ' LEFT JOIN ' . $xoopsDB->prefix('gwiki_pages') . ' t2 ON t1.keyword = t2.keyword AND t2.active = 1 ' . $sqlwhere . ' GROUP BY keyword ';
    $result = $xoopsDB->query($sql, $limit, $start);

    for ($i = 0, $iMax = $xoopsDB->getRowsNum($result); $i < $iMax; ++$i) {
        [$page, $revs, $title, $lock, $active] = $xoopsDB->fetchRow($result);
        if (empty($active)) {
            $title = _AD_GWIKI_NO_ACTIVE_PAGE;
        }
        //if(empty($title)) $title=_AD_GWIKI_NO_ACTIVE_PAGE;
        if ($lock) {
            $lockaction = ' | <a href="pages.php?page=' . $page . '&op=unlock">' . _AD_GWIKI_UNLOCK . '</a>';
        } else {
            $lockaction = ' | <a href="pages.php?page=' . $page . '&op=lock">' . _AD_GWIKI_LOCK . '</a>';
        }
        echo '<tr class="'
             . (($i % 2) ? 'even' : 'odd')
             . '"><td><a href="pages.php?page='
             . $page
             . '&op=history">'
             . $page
             . '</a></td>'
             . '<td>'
             . htmlspecialchars($title, ENT_QUOTES)
             . '</td>'
             . '<td>'
             . $revs
             . '</td>'
             . '<td><a href="pages.php?page='
             . $page
             . '&op=display">'
             . _AD_GWIKI_VIEW
             . '</a> | <a href="pages.php?page='
             . $page
             . '&op=history">'
             . _AD_GWIKI_HISTORY
             . '</a>'
             . $lockaction
             . ' | <a href="pages.php?page='
             . $page
             . '&op=delete">'
             . _DELETE
             . '</a></td></tr>';
    }
    if (0 === $i) {
        echo '<tr class="odd"><td colspan="3">' . _AD_GWIKI_EMPTYWIKI . '</td></tr>';
    }

    $endarray[_AD_GWIKI_CLEANUPDB] = 'pages.php?op=clean';
    $endarray[_AD_GWIKI_PARTITION] = 'pages.php?op=partition';
    $endarray[_AD_GWIKI_ADD_HELP]  = 'pages.php?op=addhelp';
    // set up pagenav
    $pager = '';
    if ($total > $limit) {
        require_once XOOPS_ROOT_PATH . '/class/pagenav.php';
        $likenav = '';
        if (!empty($like)) {
            $likenav = "like={$like}";
        }
        $nav = new xoopsPageNav($total, $limit, $start, 'start', $likenav);
        if ((int)($total / $limit) < 5) {
            $pager = $nav->renderNav();
        } else {
            $pager = _AD_GWIKI_PAGENAV . $nav->renderSelect(false);
        }
    }
    if (!empty($pager)) {
        $endarray['!PREFORMATTED!'] = $pager;
    }

    adminTableEnd($endarray);
}

/**
 * @param $page
 */
function showHistory($page)
{
    global $xoopsDB, $wikiPage;
    $helper = Helper::getInstance();

    allowRestoration($page);

    adminTableStart(_AD_GWIKI_ADMINTITLE . ' : ' . $page, 4);
    echo '<tr><th>' . _MD_GWIKI_TITLE . '</th><th width="20%">' . _AD_GWIKI_MODIFIED . '</th><th width="10%">' . _AD_GWIKI_AUTHOR . '</th><th width="30%">' . _AD_GWIKI_ACTION . '</th></tr>';

    $sql    = 'SELECT gwiki_id, title, body, lastmodified, uid, active, FROM_UNIXTIME(lastmodified) FROM ' . $xoopsDB->prefix('gwiki_pages') . " WHERE keyword='{$page}' ORDER BY active DESC, lastmodified DESC";
    $result = $xoopsDB->query($sql);

    for ($i = 0, $iMax = $xoopsDB->getRowsNum($result); $i < $iMax; ++$i) {
        [$id, $title, $body, $lastmodified, $uid, $active, $modified] = $xoopsDB->fetchRow($result);

        echo '<tr class="' . (($i % 2) ? 'even' : 'odd') . '"><td><a href="pages.php?page=' . $page . '&op=display&id=' . $id . '">' . htmlspecialchars($title, ENT_QUOTES) . '</a></td>';
        echo '<td>' . $modified . ($active ? '*' : '') . '</td>';
        echo '<td>' . $wikiPage->getUserName($uid) . '</td>';
        echo '<td><a href="pages.php?page=' . $page . '&op=display&id=' . $id . '">' . _AD_GWIKI_VIEW . '</a> | <a href="javascript:restoreRevision(\'' . $id . '\');">' . _AD_GWIKI_RESTORE . '</a> ';
        echo ' | <a href="pages.php?page=' . $page . '&op=fix&id=' . $id . '">' . _AD_GWIKI_FIX . '</a> | <a href="pages.php?page=' . $page . '&op=tool&id=' . $id . '">' . _AD_GWIKI_PAGETOOLS . '</a>';
        echo ' | <a href="../edit.php?page=' . $page . '&id=' . $id . '">' . _EDIT . '</a> </td></tr>';
    }
    if (0 === $i) {
        echo '<tr class="odd"><td colspan="4">' . _MD_GWIKI_PAGENOTFOUND . '</td></tr>';
    }

    adminTableEnd([_BACK => 'pages.php?op=manage']);
}

/**
 * @param $page
 * @param $id
 */
function showPage($page, $id)
{
    global $xoopsDB, $wikiPage, $xoTheme;
    $helper = Helper::getInstance();

    $dir = \basename(\dirname(__DIR__));
    if (is_object($xoTheme)) {
        $xoTheme->addStylesheet(XOOPS_URL . '/modules/' . $dir . '/assets/css/module.css');
    }

    //    xoops_cp_header();
    allowRestoration($page);

    $wikiPage->setWikiLinkURL('pages.php?page=%s&op=history');
    $wikiPage->getPage($page, $id);
    if (empty($id)) {
        $id = $wikiPage->gwiki_id;
    }

    adminTableStart(_AD_GWIKI_SHOWPAGE, 1);
    echo '<tr><td width="100%" >';
    echo '<div style="width: 94%; margin: 2em;">';
    echo '<p style="padding-bottom: 2px; border-bottom: 1px solid #000000;">' . _MD_GWIKI_PAGE . ": <strong>{$page}</strong> - " . _MD_GWIKI_LASTMODIFIED . ' <i>' . date($helper->getConfig('date_format'), $wikiPage->lastmodified) . '</i> ' . _MD_GWIKI_BY . ' <i>' . $wikiPage->getUserName(
            $wikiPage->uid
        ) . '</i></p>';

    echo '<div id="wikipage"><h1 class="wikititle" id="toc0">' . htmlspecialchars($wikiPage->title, ENT_QUOTES | ENT_HTML5) . '</h1>';
    echo $wikiPage->renderPage();
    echo '</div>';

    echo '</div>';
    echo '</td></tr>';
    adminTableEnd(
        [
            _BACK               => "pages.php?page={$page}&op=history",
            _AD_GWIKI_RESTORE   => "javascript:restoreRevision('{$id}');",
            _AD_GWIKI_PAGETOOLS => "pages.php?page={$page}&op=tool&id={$id}",
            _AD_GWIKI_FIX       => "pages.php?page={$page}&op=fix&id={$id}",
        ]
    );
}

/**
 * @param $page
 * @param $id
 */
function showPageTool($page, $id)
{
    global $xoopsDB, $wikiPage, $xoTheme;
    $helper = Helper::getInstance();

    $dir = \basename(\dirname(__DIR__));
    if (is_object($xoTheme)) {
        $xoTheme->addStylesheet(XOOPS_URL . '/modules/' . $dir . '/assets/css/module.css');
    }

    //    xoops_cp_header();
    allowRestoration($page);

    $wikiPage->setWikiLinkURL("javascript:alert('%s');");
    $wikiPage->getPage($page, $id);

    $form = new \XoopsThemeForm(_AD_GWIKI_PAGETOOLS . ": {$page}", 'gwikiform', "pages.php?page={$page}");
    $form->addElement(new \XoopsFormSelectUser('user', 'uid', true, $wikiPage->uid));
    $form->addElement(new \XoopsFormDateTime(_MD_GWIKI_LASTMODIFIED, 'lastmodified', $size = 15, $wikiPage->lastmodified));
    $form->addElement(new \XoopsFormHidden('op', 'toolupdate'));
    $form->addElement(new \XoopsFormHidden('page', $page));
    $form->addElement(new \XoopsFormHidden('id', $id));
    $form->addElement(new \XoopsFormButton('', 'submit', _SUBMIT, 'submit'));
    //$form->addElement(new \XoopsFormText(_MD_GWIKI_TITLE, "title", 40, 250, $title));
    //$form->addElement(new \XoopsFormTextArea(_MD_GWIKI_BODY, 'body', $body, 20, 80));
    //$var_name = strtotime($var_name['date']) + $var_name['time'];

    adminTableStart(_AD_GWIKI_PAGETOOLS, 1);
    echo '<tr><td width="100%" >';
    echo '<div style="width: 94%; margin: 2em;">';
    echo '<p style="padding-bottom: 2px; border-bottom: 1px solid #000000;">' . _MD_GWIKI_PAGE . ": <strong>{$page}</strong> - " . _MD_GWIKI_LASTMODIFIED . ' <i>' . date($helper->getConfig('date_format'), $wikiPage->lastmodified) . '</i> ' . _MD_GWIKI_BY . ' <i>' . $wikiPage->getUserName(
            $wikiPage->uid
        ) . '</i></p>';
    echo $form->render();
    echo '<br><div id="wikipage" style="height: 120px; overflow: auto;" ><h1 class="wikititle" id="toc0">' . htmlspecialchars($wikiPage->title, ENT_QUOTES | ENT_HTML5) . '</h1>';
    echo $wikiPage->renderPage();
    echo '</div>';

    echo '</div>';
    echo '</td></tr>';
    adminTableEnd(
        [
            _BACK             => "pages.php?page={$page}&op=history",
            _AD_GWIKI_RESTORE => "javascript:restoreRevision('{$id}');",
            _AD_GWIKI_FIX     => "pages.php?page={$page}&op=fix&id={$id}",
        ]
    );
}

/**
 * @param $page
 * @param $id
 *
 * @return mixed
 */
function pageToolUpdate($page, $id)
{
    global $xoopsDB;

    if (Request::hasVar('uid', 'POST')) {
        $uid = Request::getInt('uid', 0, 'POST');
    }
    if (Request::hasVar('lastmodified', 'POST')) {
        $modified = $_POST['lastmodified'];
    }
    if (empty($uid) || empty($modified)) {
        return false;
    }
    $lastmodified = strtotime($modified['date']) + $modified['time'];
    //print_r($modified);
    $sql    = 'UPDATE ' . $xoopsDB->prefix('gwiki_pages') . " SET uid = {$uid}, lastmodified = {$lastmodified}  WHERE keyword='{$page}' AND gwiki_id='{$id}'";
    $result = $xoopsDB->query($sql);

    return $result;
}

/**
 * @param        $action
 * @param string $keyword
 * @param        $id
 */
function confirmAction($action, $keyword = '', $id = -1)
{
    adminTableStart(_AD_GWIKI_CONFIRM, 1);
    echo '<tr><td width="100%" >';
    echo '<div class="confirmMsg">';
    echo '<form method="post" action="pages.php">';

    switch ($action) {
        case 'clean':
            echo '<input type="hidden" name="op" value="cleanit">';
            $confMsg = _AD_GWIKI_CONFIRM_CLEAN;
            break;
        case 'delete':
            echo '<input type="hidden" name="page" value="' . $keyword . '">';
            echo '<input type="hidden" id="op" name="op" value="deleteit">';
            $confMsg = sprintf(_AD_GWIKI_CONFIRM_DEL, $keyword);
            break;
        case 'fix':
            echo '<input type="hidden" name="page" value="' . $keyword . '">';
            echo '<input type="hidden" id="id" name="id" value="' . $id . '">
                <input type="hidden" id="op" name="op" value="fixit">';
            $confMsg = sprintf(_AD_GWIKI_CONFIRM_FIX, $keyword);
            break;
        case 'lock':
            echo '<input type="hidden" name="page" value="' . $keyword . '">';
            echo '<input type="hidden" id="op" name="op" value="lockit">';
            $confMsg = sprintf(_AD_GWIKI_CONFIRM_LOCK, $keyword);
            break;
        case 'unlock':
            echo '<input type="hidden" name="page" value="' . $keyword . '">';
            echo '<input type="hidden" id="op" name="op" value="unlockit">';
            $confMsg = sprintf(_AD_GWIKI_CONFIRM_UNLOCK, $keyword);
            break;
        case 'partition':
            //          echo '<input type="hidden" name="page" value="'.$keyword.'">';
            echo '<input type="hidden" id="op" name="op" value="partitionit">';
            $confMsg = _AD_GWIKI_CONFIRM_PARTITION;
            break;
        case 'addhelp':
            //          echo '<input type="hidden" name="page" value="'.$keyword.'">';
            echo '<input type="hidden" id="op" name="op" value="addhelpit">';
            $confMsg = _AD_GWIKI_CONFIRM_ADD_HELP;
            break;
    }

    echo '<p align="center">' . $confMsg . '<br><br>
        <input type="submit" value="' . _YES . '">
        <input type="button" onclick="history.back();" value="' . _NO . '"></p></form></div>';
    echo '</td></tr>';
    adminTableEnd([_BACK => 'pages.php?op=manage']);
}

/**
 * @param $page
 * @param $id
 *
 * @return mixed
 */
function getRevision($page, $id)
{
    global $xoopsDB;

    $sql    = 'SELECT title, body, lastmodified, uid FROM ' . $xoopsDB->prefix('gwiki_pages') . " WHERE gwiki_id='{$id}' AND keyword='{$page}'";
    $result = $xoopsDB->query($sql);

    return $xoopsDB->fetchRow($result);
}

/**
 * @param $page
 * @param $id
 *
 * @return mixed
 */
function fixRevision($page, $id)
{
    global $xoopsDB, $wikiPage;

    $result = $wikiPage->setRevision($page, $id);
    if ($result) {
        $sql    = 'DELETE FROM ' . $xoopsDB->prefix('gwiki_pages') . " WHERE keyword='{$page}' AND active=0 ";
        $result = $xoopsDB->query($sql);
    }

    return $result;
}

/**
 * @return bool
 */
function checkForPartitions()
{
    global $xoopsDB;

    $sql        = 'SELECT PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = \'' . XOOPS_DB_NAME . '\' AND TABLE_NAME  = \'' . $xoopsDB->prefix('gwiki_pages') . '\'';
    $result     = $xoopsDB->query($sql);
    $partitions = $xoopsDB->getRowsNum($result);

    return $partitions > 1;
}

/**
 * @return string
 */
function createPartitions()
{
    global $xoopsDB;

    if (checkForPartitions()) {
        $message = _AD_GWIKI_PARTITION_ALREADY;
    } else {
        $tablename = $xoopsDB->prefix('gwiki_pages');
        $sql       = 'ALTER TABLE ' . $tablename . ' PARTITION BY LIST (active) ';
        $sql       .= '(PARTITION ' . $tablename . '_inactive VALUES IN (0), ';
        $sql       .= ' PARTITION ' . $tablename . '_active VALUES IN (1) )';
        $result    = $xoopsDB->query($sql);
        $message   = _AD_GWIKI_PARTITION_FAILED;
        if ($result) {
            $message = _AD_GWIKI_PARTITION_OK;
        }
    }

    return $message;
}

/**
 * @return string
 */
function createHelpPages()
{
    global $xoopsDB;

    $countPages = TableLoad::loadTableFromYamlFile('gwiki_pages', __DIR__ . '/../sql/helppages.yml');
    $countLinks = TableLoad::loadTableFromYamlFile('gwiki_pageids', __DIR__ . '/../sql/helplinks.yml');

    $message = _AD_GWIKI_ADD_HELP_FAILED;
    //    if ($result) {
    //        $message = _AD_GWIKI_ADD_HELP_OK;
    //    }

    if ($countPages > 0 && $countLinks > 0) {
        $message = _AD_GWIKI_ADD_HELP_OK;
    }

    return $message;
}

/**
 * @param $page
 */
function allowRestoration($page)
{
    echo '<script type="text/javascript">
    <!--
        function restoreRevision(id)
        {
            document.restore.id.value = id;
            document.restore.submit();
        }
    // -->
    </script>
    <form id="restore" name="restore" action="pages.php" method="post">
    <input type="hidden" id="op" name="op" value="restore">
    <input type="hidden" id="page" name="page" value="' . $page . '">
    <input type="hidden" id="id" name="id" value="">
    </form>';
}

// page, op, id
$page = isset($_GET['page']) ? cleaner($_GET['page']) : '';
//$page = makeKeyWord((isset($_GET['page']))?cleaner($_GET['page']):"");
$op = isset($_GET['op']) ? cleaner($_GET['op']) : '';

// $_POST variables we use
if (Request::hasVar('op', 'POST')) {
    $op = cleaner($_POST['op']);
}
if (Request::hasVar('page', 'POST')) {
    $page = cleaner($_POST['page']);
}
if (Request::hasVar('id', 'POST')) {
    $id = Request::getInt('id', 0, 'POST');
}
//if (\Xmf\Request::hasVar('', 'POST')) $ = (int)($_POST['']);

switch ($op) {
    case 'history':
        showHistory($page);
        break;
    case 'display':
        $id = null;
        if (Request::hasVar('id', 'GET')) {
            $id = Request::getInt('id', 0, 'GET');
        }
        showPage($page, $id);
        break;
    case 'restore':
        $success = $wikiPage->setRevision($page, $id);
        redirect_header('pages.php?page=' . $page . '&op=history', 2, $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT);
        break;
    case 'fix':
        confirmAction('fix', $page, Request::getInt('id', 0, 'GET'));
        break;
    case 'fixit':
        $success = fixRevision($page, $id);
        redirect_header('pages.php?page=' . $page . '&op=history', 2, $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT);
        break;
    case 'tool':
        showPageTool($page, Request::getInt('id', 0, 'GET'));
        break;
    case 'toolupdate':
        $success = pageToolUpdate($page, $id);
        $message = $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT;
        $op      = '';
        showPages($message);
        break;
    case 'delete':
        confirmAction('delete', $page);
        break;
    case 'deleteit':
        //  mark all versions inactive -- these will disappear as they age and the database is cleaned
        $sql = 'UPDATE ' . $xoopsDB->prefix('gwiki_pages') . " SET active = 0 WHERE keyword='{$page}' ";

        $success = $xoopsDB->query($sql);
        redirect_header('pages.php?op=manage', 2, $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT);
        break;
    case 'clean':
        confirmAction('clean');
        break;
    case 'cleanit':
        // delete inactive pages older than config option retain_days
        $retaindays = (int)$helper->getConfig('retain_days');
        if ($retaindays > 0) {
            $dir    = \basename(\dirname(__DIR__));
            $url    = XOOPS_URL . '/modules/' . $dir . '/cleanit.php';
            $params = ['check' => $retaindays];
            post_clean_request($url, $params);
            $message = _MD_GWIKI_CLEAN_STARTED;
        } else {
            $message = _MD_GWIKI_CLEAN_DISABLED;
        }
        $op = '';
        showPages($message);
        break;
    case 'lock':
        confirmAction('lock', $page);
        break;
    case 'lockit':
        $sql = 'UPDATE ' . $xoopsDB->prefix('gwiki_pages') . " SET admin_lock = 1 WHERE keyword='{$page}' ";

        $success = $xoopsDB->query($sql);
        redirect_header('pages.php?op=manage', 2, $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT);
        break;
    case 'unlock':
        confirmAction('unlock', $page);
        break;
    case 'unlockit':
        $sql = 'UPDATE ' . $xoopsDB->prefix('gwiki_pages') . " SET admin_lock = 0 WHERE keyword='{$page}' ";

        $success = $xoopsDB->query($sql);
        redirect_header('pages.php?op=manage', 2, $success ? _MD_GWIKI_DBUPDATED : _MD_GWIKI_ERRORINSERT);
        break;
    case 'partition':
        if (checkForPartitions()) {
            showPages(_AD_GWIKI_PARTITION_ALREADY);
        } else {
            confirmAction('partition', '');
        }
        break;
    case 'partitionit':
        $message = createPartitions();
        showPages($message);
        break;
    case 'addhelp':
        confirmAction('addhelp', '');
        break;
    case 'addhelpit':
        $message = createHelpPages();
        showPages($message);
        break;
    case 'manage':
    default:
        showPages();
        break;
}

require_once __DIR__ . '/footer.php';