2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Used to render the footer of PMA's pages
8 declare(strict_types
=1);
15 * Class used to output the footer
29 * Whether we are servicing an ajax request.
36 * Whether to only close the BODY and HTML tags
37 * or also include scripts, errors and links
44 * Whether to display anything
62 * Creates a new class instance
64 public function __construct()
66 $this->template
= new Template();
67 $this->_isEnabled
= true;
68 $this->_scripts
= new Scripts();
69 $this->_isMinimal
= false;
70 $this->relation
= new Relation($GLOBALS['dbi']);
74 * Returns the message for demo server to error messages
78 private function _getDemoMessage(): string
80 $message = '<a href="/">' . __('phpMyAdmin Demo Server') . '</a>: ';
81 if (@file_exists
(ROOT_PATH
. 'revision-info.php')) {
82 include ROOT_PATH
. 'revision-info.php';
84 __('Currently running Git revision %1$s from the %2$s branch.'),
85 '<a target="_blank" rel="noopener noreferrer" href="' . $repobase . $fullrevision . '">'
87 '<a target="_blank" rel="noopener noreferrer" href="' . $repobranchbase . $branch . '">'
91 $message .= __('Git information missing!');
94 return Message
::notice($message)->getDisplay();
98 * Remove recursions and iterator objects from an object
100 * @param object|array $object Object to clean
101 * @param array $stack Stack used to keep track of recursion,
102 * need not be passed for the first time
104 * @return object Reference passed object
106 private static function _removeRecursion(&$object, array $stack = [])
108 if ((is_object($object) ||
is_array($object)) && $object) {
109 if ($object instanceof Traversable
) {
110 $object = "***ITERATOR***";
111 } elseif (! in_array($object, $stack, true)) {
113 foreach ($object as &$subobject) {
114 self
::_removeRecursion($subobject, $stack);
117 $object = "***RECURSION***";
124 * Renders the debug messages
128 public function getDebugMessage(): string
130 $retval = '\'null\'';
131 if ($GLOBALS['cfg']['DBG']['sql']
132 && empty($_REQUEST['no_debug'])
133 && ! empty($_SESSION['debug'])
135 // Remove recursions and iterators from $_SESSION['debug']
136 self
::_removeRecursion($_SESSION['debug']);
138 $retval = json_encode($_SESSION['debug']);
139 $_SESSION['debug'] = [];
140 return json_last_error() ?
'\'false\'' : $retval;
142 $_SESSION['debug'] = [];
147 * Returns the url of the current page
151 public function getSelfUrl(): string
153 $db = isset($GLOBALS['db']) && strlen($GLOBALS['db']) ?
$GLOBALS['db'] : '';
154 $table = isset($GLOBALS['table']) && strlen($GLOBALS['table']) ?
$GLOBALS['table'] : '';
155 $target = isset($_REQUEST['target']) && strlen($_REQUEST['target']) ?
$_REQUEST['target'] : '';
159 'server' => $GLOBALS['server'],
162 // needed for server privileges tabs
163 if (isset($_GET['viewing_mode'])
164 && in_array($_GET['viewing_mode'], ['server', 'db', 'table'])
166 $params['viewing_mode'] = $_GET['viewing_mode'];
169 * @todo coming from /server/privileges, here $db is not set,
170 * add the following condition below when that is fixed
171 * && $_GET['checkprivsdb'] == $db
173 if (isset($_GET['checkprivsdb'])
175 $params['checkprivsdb'] = $_GET['checkprivsdb'];
178 * @todo coming from /server/privileges, here $table is not set,
179 * add the following condition below when that is fixed
180 * && $_REQUEST['checkprivstable'] == $table
182 if (isset($_GET['checkprivstable'])
184 $params['checkprivstable'] = $_GET['checkprivstable'];
186 if (isset($_REQUEST['single_table'])
187 && in_array($_REQUEST['single_table'], [true, false])
189 $params['single_table'] = $_REQUEST['single_table'];
191 return basename(Core
::getenv('SCRIPT_NAME')) . Url
::getCommonRaw($params);
195 * Renders the link to open a new page
197 * @param string $url The url of the page
201 private function _getSelfLink(string $url): string
204 $retval .= '<div id="selflink" class="print_ignore">';
205 $retval .= '<a href="' . htmlspecialchars($url) . '"'
206 . ' title="' . __('Open new phpMyAdmin window') . '" target="_blank" rel="noopener noreferrer">';
207 if (Util
::showIcons('TabsMode')) {
208 $retval .= Util
::getImage(
210 __('Open new phpMyAdmin window')
213 $retval .= __('Open new phpMyAdmin window');
221 * Renders the link to open a new page
225 public function getErrorMessages(): string
228 if ($GLOBALS['error_handler']->hasDisplayErrors()) {
229 $retval .= $GLOBALS['error_handler']->getDispErrors();
235 $GLOBALS['error_handler']->reportErrors();
241 * Saves query in history
245 private function _setHistory(): void
247 if (! Core
::isValid($_REQUEST['no_history'])
248 && empty($GLOBALS['error_message'])
249 && ! empty($GLOBALS['sql_query'])
250 && isset($GLOBALS['dbi'])
251 && $GLOBALS['dbi']->isUserType('logged')
253 $this->relation
->setHistory(
254 Core
::ifSetOr($GLOBALS['db'], ''),
255 Core
::ifSetOr($GLOBALS['table'], ''),
256 $GLOBALS['cfg']['Server']['user'],
257 $GLOBALS['sql_query']
263 * Disables the rendering of the footer
267 public function disable(): void
269 $this->_isEnabled
= false;
273 * Set the ajax flag to indicate whether
274 * we are servicing an ajax request
276 * @param bool $isAjax Whether we are servicing an ajax request
280 public function setAjax(bool $isAjax): void
282 $this->_isAjax
= $isAjax;
286 * Turn on minimal display mode
290 public function setMinimal(): void
292 $this->_isMinimal
= true;
296 * Returns the Scripts object
298 * @return Scripts object
300 public function getScripts(): Scripts
302 return $this->_scripts
;
310 public function getDisplay(): string
312 $this->_setHistory();
313 if ($this->_isEnabled
) {
314 if (! $this->_isAjax
&& ! $this->_isMinimal
) {
315 if (Core
::getenv('SCRIPT_NAME')
319 $url = $this->getSelfUrl();
320 $header = Response
::getInstance()->getHeader();
321 $scripts = $header->getScripts()->getFiles();
322 $menuHash = $header->getMenu()->getHash();
323 // prime the client-side cache
324 $this->_scripts
->addCode(
326 'if (! (history && history.pushState)) '
327 . 'MicroHistory.primer = {'
332 Sanitize
::escapeJsString($url),
333 json_encode($scripts),
334 Sanitize
::escapeJsString($menuHash)
338 if (Core
::getenv('SCRIPT_NAME')
341 $url = $this->getSelfUrl();
342 $selfLink = $this->_getSelfLink($url);
344 $this->_scripts
->addCode(
345 'var debugSQLInfo = ' . $this->getDebugMessage() . ';'
348 $errorMessages = $this->getErrorMessages();
349 $scripts = $this->_scripts
->getDisplay();
351 if ($GLOBALS['cfg']['DBG']['demo']) {
352 $demoMessage = $this->_getDemoMessage();
355 $footer = Config
::renderFooter();
357 return $this->template
->render('footer', [
358 'is_ajax' => $this->_isAjax
,
359 'is_minimal' => $this->_isMinimal
,
360 'self_link' => $selfLink ??
'',
361 'error_messages' => $errorMessages ??
'',
362 'scripts' => $scripts ??
'',
363 'is_demo' => $GLOBALS['cfg']['DBG']['demo'],
364 'demo_message' => $demoMessage ??
'',
365 'footer' => $footer ??
'',