/** * Test for Tracker::isActive() * * @return void * @test */ public function testIsActive() { $attr = new \ReflectionProperty('PMA\\libraries\\Tracker', 'enabled'); $attr->setAccessible(true); $attr->setValue(false); $this->assertFalse(Tracker::isActive()); Tracker::enable(); $_SESSION['relation'][$GLOBALS['server']] = array('PMA_VERSION' => PMA_VERSION, 'trackingwork' => false); $this->assertFalse(Tracker::isActive()); $_SESSION['relation'][$GLOBALS['server']] = array('PMA_VERSION' => PMA_VERSION, 'trackingwork' => true, 'db' => 'pmadb', 'tracking' => 'tracking'); $this->assertTrue(Tracker::isActive()); }
/** * Returns the tracking icon if the table is tracked * * @param string $table table name * * @return string HTML for tracking icon */ protected function getTrackingIcon($table) { $tracking_icon = ''; if (Tracker::isActive()) { $is_tracked = Tracker::isTracked($GLOBALS["db"], $table); if ($is_tracked || Tracker::getVersion($GLOBALS["db"], $table) > 0) { $tracking_icon = Template::get('database/structure/tracking_icon')->render(array('url_query' => $this->_url_query, 'truename' => $table, 'is_tracked' => $is_tracked)); } } return $tracking_icon; }
/** * runs a query and returns the result * * @param string $query query to run * @param object $link mysql link resource * @param integer $options query options * @param bool $cache_affected_rows whether to cache affected row * * @return mixed */ public function tryQuery($query, $link = null, $options = 0, $cache_affected_rows = true) { $link = $this->getLink($link); if ($link === false) { return false; } if ($GLOBALS['cfg']['DBG']['sql']) { $time = microtime(true); } $result = $this->_extension->realQuery($query, $link, $options); if ($cache_affected_rows) { $GLOBALS['cached_affected_rows'] = $this->affectedRows($link, false); } if ($GLOBALS['cfg']['DBG']['sql']) { $time = microtime(true) - $time; $this->_dbgQuery($query, $link, $result, $time); } if (!empty($result) && Tracker::isActive()) { Tracker::handleQuery($query); } return $result; }
require_once './libraries/common.inc.php'; require_once './libraries/tracking.lib.php'; //Get some js files needed for Ajax requests $response = Response::getInstance(); $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('jquery/jquery.tablesorter.js'); $scripts->addFile('tbl_tracking.js'); define('TABLE_MAY_BE_ABSENT', true); require './libraries/tbl_common.inc.php'; if (Tracker::isActive() && Tracker::isTracked($GLOBALS["db"], $GLOBALS["table"]) && ! (isset($_REQUEST['toggle_activation']) && $_REQUEST['toggle_activation'] == 'deactivate_now') && ! (isset($_REQUEST['report_export']) && $_REQUEST['export_type'] == 'sqldumpfile') ) { $msg = PMA\libraries\Message::notice( sprintf( __('Tracking of %s is activated.'), htmlspecialchars($GLOBALS["db"] . '.' . $GLOBALS["table"]) ) ); $response->addHTML($msg->getDisplay()); }
/** * Returns the db tabs as an array * * @return array Data for generating db tabs */ private function _getDbTabs() { $db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db); $num_tables = count($GLOBALS['dbi']->getTables($this->_db)); $is_superuser = $GLOBALS['dbi']->isSuperuser(); $isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant') || $GLOBALS['dbi']->isUserType('create'); /** * Gets the relation settings */ $cfgRelation = PMA_getRelationsParam(); $tabs = array(); $tabs['structure']['link'] = 'db_structure.php'; $tabs['structure']['text'] = __('Structure'); $tabs['structure']['icon'] = 'b_props.png'; $tabs['sql']['link'] = 'db_sql.php'; $tabs['sql']['text'] = __('SQL'); $tabs['sql']['icon'] = 'b_sql.png'; $tabs['search']['text'] = __('Search'); $tabs['search']['icon'] = 'b_search.png'; $tabs['search']['link'] = 'db_search.php'; if ($num_tables == 0) { $tabs['search']['warning'] = __('Database seems to be empty!'); } $tabs['qbe']['text'] = __('Query'); $tabs['qbe']['icon'] = 's_db.png'; $tabs['qbe']['link'] = 'db_qbe.php'; if ($num_tables == 0) { $tabs['qbe']['warning'] = __('Database seems to be empty!'); } $tabs['export']['text'] = __('Export'); $tabs['export']['icon'] = 'b_export.png'; $tabs['export']['link'] = 'db_export.php'; if ($num_tables == 0) { $tabs['export']['warning'] = __('Database seems to be empty!'); } if (!$db_is_system_schema) { $tabs['import']['link'] = 'db_import.php'; $tabs['import']['text'] = __('Import'); $tabs['import']['icon'] = 'b_import.png'; $tabs['operation']['link'] = 'db_operations.php'; $tabs['operation']['text'] = __('Operations'); $tabs['operation']['icon'] = 'b_tblops.png'; if ($is_superuser || $isCreateOrGrantUser) { $tabs['privileges']['link'] = 'server_privileges.php'; $tabs['privileges']['args']['checkprivsdb'] = $this->_db; // stay on database view $tabs['privileges']['args']['viewing_mode'] = 'db'; $tabs['privileges']['text'] = __('Privileges'); $tabs['privileges']['icon'] = 's_rights.png'; } $tabs['routines']['link'] = 'db_routines.php'; $tabs['routines']['text'] = __('Routines'); $tabs['routines']['icon'] = 'b_routines.png'; if (Util::currentUserHasPrivilege('EVENT', $this->_db)) { $tabs['events']['link'] = 'db_events.php'; $tabs['events']['text'] = __('Events'); $tabs['events']['icon'] = 'b_events.png'; } if (Util::currentUserHasPrivilege('TRIGGER', $this->_db)) { $tabs['triggers']['link'] = 'db_triggers.php'; $tabs['triggers']['text'] = __('Triggers'); $tabs['triggers']['icon'] = 'b_triggers.png'; } } if (Tracker::isActive() && !$db_is_system_schema) { $tabs['tracking']['text'] = __('Tracking'); $tabs['tracking']['icon'] = 'eye.png'; $tabs['tracking']['link'] = 'db_tracking.php'; } if (!$db_is_system_schema) { $tabs['designer']['text'] = __('Designer'); $tabs['designer']['icon'] = 'b_relations.png'; $tabs['designer']['link'] = 'db_designer.php'; $tabs['designer']['id'] = 'designer_tab'; } if (!$db_is_system_schema && $cfgRelation['centralcolumnswork']) { $tabs['central_columns']['text'] = __('Central columns'); $tabs['central_columns']['icon'] = 'centralColumns.png'; $tabs['central_columns']['link'] = 'db_central_columns.php'; } return $tabs; }
/** * Index action * * @return void */ public function indexAction() { // Add/Remove favorite tables using Ajax request. if ($GLOBALS['is_ajax_request'] && !empty($_REQUEST['favorite_table'])) { $this->addRemoveFavoriteTablesAction(); return; } $this->response->getHeader()->getScripts()->addFiles(array('db_structure.js', 'tbl_change.js', 'jquery/jquery-ui-timepicker-addon.js')); // Drops/deletes/etc. multiple tables if required if (!empty($_POST['submit_mult']) && isset($_POST['selected_tbl']) || isset($_POST['mult_btn'])) { $action = 'db_structure.php'; $err_url = 'db_structure.php' . PMA_URL_getCommon(array('db' => $this->db)); // see bug #2794840; in this case, code path is: // db_structure.php -> libraries/mult_submits.inc.php -> sql.php // -> db_structure.php and if we got an error on the multi submit, // we must display it here and not call again mult_submits.inc.php if (!isset($_POST['error']) || false === $_POST['error']) { include 'libraries/mult_submits.inc.php'; } if (empty($_POST['message'])) { $_POST['message'] = Message::success(); } } $this->_url_query .= '&goto=db_structure.php'; // Gets the database structure $sub_part = '_structure'; list($tables, $num_tables, $total_num_tables, , $is_show_stats, $db_is_system_schema, $tooltip_truename, $tooltip_aliasname, $pos) = Util::getDbInfo($GLOBALS['db'], isset($sub_part) ? $sub_part : ''); $this->_tables = $tables; // updating $tables seems enough for #11376, but updating other // variables too in case they may cause some other problem. $this->_num_tables = $num_tables; $this->_pos = $pos; $this->_db_is_system_schema = $db_is_system_schema; $this->_total_num_tables = $total_num_tables; $this->_is_show_stats = $is_show_stats; // If there is an Ajax request for real row count of a table. if ($GLOBALS['is_ajax_request'] && isset($_REQUEST['real_row_count']) && $_REQUEST['real_row_count'] == true) { $this->handleRealRowCountRequestAction(); return; } include_once 'libraries/replication.inc.php'; PageSettings::showGroup('DbStructure'); $db_collation = PMA_getDbCollation($this->db); $titles = Util::buildActionTitles(); // 1. No tables if ($this->_num_tables == 0) { $this->response->addHTML(Message::notice(__('No tables found in database.'))); if (empty($db_is_system_schema)) { $this->response->addHTML(PMA_getHtmlForCreateTable($this->db)); } return; } // else // 2. Shows table information /** * Displays the tables list */ $this->response->addHTML('<div id="tableslistcontainer">'); $_url_params = array('pos' => $this->_pos, 'db' => $this->db); // Add the sort options if they exists if (isset($_REQUEST['sort'])) { $_url_params['sort'] = $_REQUEST['sort']; } if (isset($_REQUEST['sort_order'])) { $_url_params['sort_order'] = $_REQUEST['sort_order']; } $this->response->addHTML(Util::getListNavigator($this->_total_num_tables, $this->_pos, $_url_params, 'db_structure.php', 'frame_content', $GLOBALS['cfg']['MaxTableList'])); // table form $this->response->addHTML(Template::get('database/structure/table_header')->render(array('db' => $this->db, 'db_is_system_schema' => $this->_db_is_system_schema, 'replication' => $GLOBALS['replication_info']['slave']['status']))); $i = $sum_entries = 0; $overhead_check = ''; $create_time_all = ''; $update_time_all = ''; $check_time_all = ''; $num_columns = $GLOBALS['cfg']['PropertiesNumColumns'] > 1 ? ceil($this->_num_tables / $GLOBALS['cfg']['PropertiesNumColumns']) + 1 : 0; $row_count = 0; $sum_size = (double) 0; $overhead_size = (double) 0; $hidden_fields = array(); $odd_row = true; $overall_approx_rows = false; // Instance of RecentFavoriteTable class. $fav_instance = RecentFavoriteTable::getInstance('favorite'); foreach ($this->_tables as $keyname => $current_table) { // Get valid statistics whatever is the table type $drop_query = ''; $drop_message = ''; $overhead = ''; $table_is_view = false; $table_encoded = urlencode($current_table['TABLE_NAME']); // Sets parameters for links $tbl_url_query = $this->_url_query . '&table=' . $table_encoded; // do not list the previous table's size info for a view list($current_table, $formatted_size, $unit, $formatted_overhead, $overhead_unit, $overhead_size, $table_is_view, $sum_size) = $this->getStuffForEngineTypeTable($current_table, $sum_size, $overhead_size); $curTable = $this->dbi->getTable($this->db, $current_table['TABLE_NAME']); if (!$curTable->isMerge()) { $sum_entries += $current_table['TABLE_ROWS']; } if (isset($current_table['Collation'])) { $collation = '<dfn title="' . PMA_getCollationDescr($current_table['Collation']) . '">' . $current_table['Collation'] . '</dfn>'; } else { $collation = '---'; } if ($this->_is_show_stats) { if ($formatted_overhead != '') { $overhead = '<a href="tbl_structure.php' . $tbl_url_query . '#showusage">' . '<span>' . $formatted_overhead . '</span> ' . '<span class="unit">' . $overhead_unit . '</span>' . '</a>' . "\n"; $overhead_check .= "markAllRows('row_tbl_" . ($i + 1) . "');"; } else { $overhead = '-'; } } // end if $showtable = $this->dbi->getTable($this->db, $current_table['TABLE_NAME'])->getStatusInfo(null, true); if ($GLOBALS['cfg']['ShowDbStructureCreation']) { $create_time = isset($showtable['Create_time']) ? $showtable['Create_time'] : ''; if ($create_time && (!$create_time_all || $create_time < $create_time_all)) { $create_time_all = $create_time; } } if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) { // $showtable might already be set from ShowDbStructureCreation, // see above $update_time = isset($showtable['Update_time']) ? $showtable['Update_time'] : ''; if ($update_time && (!$update_time_all || $update_time < $update_time_all)) { $update_time_all = $update_time; } } if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) { // $showtable might already be set from ShowDbStructureCreation, // see above $check_time = isset($showtable['Check_time']) ? $showtable['Check_time'] : ''; if ($check_time && (!$check_time_all || $check_time < $check_time_all)) { $check_time_all = $check_time; } } $truename = htmlspecialchars(!empty($tooltip_truename) && isset($tooltip_truename[$current_table['TABLE_NAME']]) ? $tooltip_truename[$current_table['TABLE_NAME']] : $current_table['TABLE_NAME']); $truename = str_replace(' ', ' ', $truename); $i++; $row_count++; if ($table_is_view) { $hidden_fields[] = '<input type="hidden" name="views[]" value="' . htmlspecialchars($current_table['TABLE_NAME']) . '" />'; } /* * Always activate links for Browse, Search and Empty, even if * the icons are greyed, because * 1. for views, we don't know the number of rows at this point * 2. for tables, another source could have populated them since the * page was generated * * I could have used the PHP ternary conditional operator but I find * the code easier to read without this operator. */ $may_have_rows = $current_table['TABLE_ROWS'] > 0 || $table_is_view; $browse_table = Template::get('database/structure/browse_table')->render(array('tbl_url_query' => $tbl_url_query, 'title' => $may_have_rows ? $titles['Browse'] : $titles['NoBrowse'])); $search_table = Template::get('database/structure/search_table')->render(array('tbl_url_query' => $tbl_url_query, 'title' => $may_have_rows ? $titles['Search'] : $titles['NoSearch'])); $browse_table_label = Template::get('database/structure/browse_table_label')->render(array('tbl_url_query' => $tbl_url_query, 'title' => htmlspecialchars($current_table['TABLE_COMMENT']), 'truename' => $truename)); $empty_table = ''; if (!$this->_db_is_system_schema) { $empty_table = ' '; if (!$table_is_view) { $empty_table = Template::get('database/structure/empty_table')->render(array('tbl_url_query' => $tbl_url_query, 'sql_query' => urlencode('TRUNCATE ' . Util::backquote($current_table['TABLE_NAME'])), 'message_to_show' => urlencode(sprintf(__('Table %s has been emptied.'), htmlspecialchars($current_table['TABLE_NAME']))), 'title' => $may_have_rows ? $titles['Empty'] : $titles['NoEmpty'])); } $drop_query = sprintf('DROP %s %s', $table_is_view || $current_table['ENGINE'] == null ? 'VIEW' : 'TABLE', Util::backquote($current_table['TABLE_NAME'])); $drop_message = sprintf($table_is_view || $current_table['ENGINE'] == null ? __('View %s has been dropped.') : __('Table %s has been dropped.'), str_replace(' ', ' ', htmlspecialchars($current_table['TABLE_NAME']))); } $tracking_icon = ''; if (Tracker::isActive()) { $is_tracked = Tracker::isTracked($GLOBALS["db"], $truename); if ($is_tracked || Tracker::getVersion($GLOBALS["db"], $truename) > 0) { $tracking_icon = Template::get('database/structure/tracking_icon')->render(array('url_query' => $this->_url_query, 'truename' => $truename, 'is_tracked' => $is_tracked)); } } if ($num_columns > 0 && $this->_num_tables > $num_columns && $row_count % $num_columns == 0) { $row_count = 1; $odd_row = true; $this->response->addHTML('</tr></tbody></table>'); $this->response->addHTML(Template::get('database/structure/table_header')->render(array('db' => $this->db, 'db_is_system_schema' => $this->_db_is_system_schema, 'replication' => $GLOBALS['replication_info']['slave']['status']))); } $do = $ignored = false; if ($GLOBALS['replication_info']['slave']['status']) { $nbServSlaveDoDb = count($GLOBALS['replication_info']['slave']['Do_DB']); $nbServSlaveIgnoreDb = count($GLOBALS['replication_info']['slave']['Ignore_DB']); $searchDoDBInTruename = array_search($truename, $GLOBALS['replication_info']['slave']['Do_DB']); $searchDoDBInDB = array_search($this->db, $GLOBALS['replication_info']['slave']['Do_DB']); $do = strlen($searchDoDBInTruename) > 0 || strlen($searchDoDBInDB) > 0 || $nbServSlaveDoDb == 1 && $nbServSlaveIgnoreDb == 1 || $this->hasTable($GLOBALS['replication_info']['slave']['Wild_Do_Table'], $truename); $searchDb = array_search($this->db, $GLOBALS['replication_info']['slave']['Ignore_DB']); $searchTable = array_search($truename, $GLOBALS['replication_info']['slave']['Ignore_Table']); $ignored = strlen($searchTable) > 0 || strlen($searchDb) > 0 || $this->hasTable($GLOBALS['replication_info']['slave']['Wild_Ignore_Table'], $truename); } // Handle favorite table list. ----START---- $already_favorite = $this->checkFavoriteTable($current_table['TABLE_NAME']); if (isset($_REQUEST['remove_favorite'])) { if ($already_favorite) { // If already in favorite list, remove it. $favorite_table = $_REQUEST['favorite_table']; $fav_instance->remove($this->db, $favorite_table); } } if (isset($_REQUEST['add_favorite'])) { if (!$already_favorite) { // Otherwise add to favorite list. $favorite_table = $_REQUEST['favorite_table']; $fav_instance->add($this->db, $favorite_table); } } // Handle favorite table list. ----ENDS---- $show_superscript = ''; // there is a null value in the ENGINE // - when the table needs to be repaired, or // - when it's a view // so ensure that we'll display "in use" below for a table // that needs to be repaired $approx_rows = false; if (isset($current_table['TABLE_ROWS']) && ($current_table['ENGINE'] != null || $table_is_view)) { // InnoDB table: we did not get an accurate row count $approx_rows = !$table_is_view && $current_table['ENGINE'] == 'InnoDB' && !$current_table['COUNTED']; } $this->response->addHTML(Template::get('database/structure/structure_table_row')->render(array('db' => $this->db, 'curr' => $i, 'odd_row' => $odd_row, 'table_is_view' => $table_is_view, 'current_table' => $current_table, 'browse_table_label' => $browse_table_label, 'tracking_icon' => $tracking_icon, 'server_slave_status' => $GLOBALS['replication_info']['slave']['status'], 'browse_table' => $browse_table, 'tbl_url_query' => $tbl_url_query, 'search_table' => $search_table, 'db_is_system_schema' => $this->_db_is_system_schema, 'titles' => $titles, 'empty_table' => $empty_table, 'drop_query' => $drop_query, 'drop_message' => $drop_message, 'collation' => $collation, 'formatted_size' => $formatted_size, 'unit' => $unit, 'overhead' => $overhead, 'create_time' => isset($create_time) ? $create_time : '', 'update_time' => isset($update_time) ? $update_time : '', 'check_time' => isset($check_time) ? $check_time : '', 'is_show_stats' => $this->_is_show_stats, 'ignored' => $ignored, 'do' => $do, 'colspan_for_structure' => $GLOBALS['colspan_for_structure'], 'approx_rows' => $approx_rows, 'show_superscript' => $show_superscript, 'already_favorite' => $this->checkFavoriteTable($current_table['TABLE_NAME'])))); $odd_row = !$odd_row; $overall_approx_rows = $overall_approx_rows || $approx_rows; } // end foreach // Show Summary $this->response->addHTML('</tbody>'); $this->response->addHTML(Template::get('database/structure/body_for_table_summary')->render(array('num_tables' => $this->_num_tables, 'server_slave_status' => $GLOBALS['replication_info']['slave']['status'], 'db_is_system_schema' => $this->_db_is_system_schema, 'sum_entries' => $sum_entries, 'db_collation' => $db_collation, 'is_show_stats' => $this->_is_show_stats, 'sum_size' => $sum_size, 'overhead_size' => $overhead_size, 'create_time_all' => $create_time_all, 'update_time_all' => $update_time_all, 'check_time_all' => $check_time_all, 'approx_rows' => $overall_approx_rows))); $this->response->addHTML('</table>'); //check all $this->response->addHTML(Template::get('database/structure/check_all_tables')->render(array('pmaThemeImage' => $GLOBALS['pmaThemeImage'], 'text_dir' => $GLOBALS['text_dir'], 'overhead_check' => $overhead_check, 'db_is_system_schema' => $this->_db_is_system_schema, 'hidden_fields' => $hidden_fields))); $this->response->addHTML('</form>'); //end of form // display again the table list navigator $this->response->addHTML(Util::getListNavigator($this->_total_num_tables, $this->_pos, $_url_params, 'db_structure.php', 'frame_content', $GLOBALS['cfg']['MaxTableList'])); $this->response->addHTML('</div><hr />'); /** * Work on the database */ /* DATABASE WORK */ /* Printable view of a table */ $this->response->addHTML(Template::get('database/structure/print_view_data_dictionary_link')->render(array('url_query' => $this->_url_query))); if (empty($db_is_system_schema)) { $this->response->addHTML(PMA_getHtmlForCreateTable($this->db)); } }
* * @package PhpMyAdmin */ // Run common work use PMA\libraries\Tracker; require_once './libraries/common.inc.php'; require_once './libraries/tracking.lib.php'; //Get some js files needed for Ajax requests $response = PMA\libraries\Response::getInstance(); $header = $response->getHeader(); $scripts = $header->getScripts(); $scripts->addFile('jquery/jquery.tablesorter.js'); $scripts->addFile('tbl_tracking.js'); define('TABLE_MAY_BE_ABSENT', true); require './libraries/tbl_common.inc.php'; if (Tracker::isActive() && Tracker::isTracked($GLOBALS["db"], $GLOBALS["table"]) && !(isset($_REQUEST['toggle_activation']) && $_REQUEST['toggle_activation'] == 'deactivate_now') && !(isset($_REQUEST['report_export']) && $_REQUEST['export_type'] == 'sqldumpfile')) { $msg = PMA\libraries\Message::notice(sprintf(__('Tracking of %s is activated.'), htmlspecialchars($GLOBALS["db"] . '.' . $GLOBALS["table"]))); PMA\libraries\Response::getInstance()->addHTML($msg->getDisplay()); } $url_query .= '&goto=tbl_tracking.php&back=tbl_tracking.php'; $url_params['goto'] = 'tbl_tracking.php'; $url_params['back'] = 'tbl_tracking.php'; // Init vars for tracking report if (isset($_REQUEST['report']) || isset($_REQUEST['report_export'])) { $data = Tracker::getTrackedData($_REQUEST['db'], $_REQUEST['table'], $_REQUEST['version']); $selection_schema = false; $selection_data = false; $selection_both = false; if (!isset($_REQUEST['logtype'])) { $_REQUEST['logtype'] = 'schema_and_data'; }
/** * runs a query and returns the result * * @param string $query query to run * @param object $link mysql link resource * @param integer $options query options * @param bool $cache_affected_rows whether to cache affected row * * @return mixed */ public function tryQuery($query, $link = null, $options = 0, $cache_affected_rows = true) { $debug = $GLOBALS['cfg']['DBG']['sql']; $link = $this->getLink($link); if ($link === false) { return false; } if ($debug) { $time = microtime(true); } $result = $this->_extension->realQuery($query, $link, $options); if ($cache_affected_rows) { $GLOBALS['cached_affected_rows'] = $this->affectedRows($link, false); } if ($debug) { $time = microtime(true) - $time; $this->_dbgQuery($query, $link, $result, $time); if ($GLOBALS['cfg']['DBG']['sqllog']) { openlog('phpMyAdmin', LOG_NDELAY | LOG_PID, LOG_USER); syslog(LOG_INFO, 'SQL[' . basename($_SERVER['SCRIPT_NAME']) . ']: ' . sprintf('%0.3f', $time) . ' > ' . $query); } } if (!empty($result) && Tracker::isActive()) { Tracker::handleQuery($query); } return $result; }