[Tͪ#n$;<:a4sX[o-s4>fLumUwЇvDi aSGUֺ0 Z'ue.uj>y٪Qc׵:wW$KPqVJ-!+ySq#n]6!^O^KF%	b3o͖,do5{,e򿥅w)I$%a20UAϺLFFkr)ǠWH+RMk/V.PbFR2ӿF 4i.8}0ݶ0~³u/+CwWthD+E*4rAjuphx`#miqh) 'd8E""4c3$~	?°AW;~fm DD,X՝ -vDW?S P܀#W>w[ ?AlVkV*7P%@%4?R GPE{mo4frHztw3jH^]DaHt~`<Ufm DD,X՝ -vDW?n-aXENw~{^NF;QY܏>tч<U)A)WH%PMG^8sSq`]v>ȦgDsx?0`C0L0ix^o|}#I2>	~p
3&ҭ	n`at{[cD/&K@aFx"߈G\U>tkH']լ iI 
"hy@q+(%TfdM~IERE)nS!3LVl<MUm]E6 ܂o*ݏc@_pmSUt3}m]?HxC93!ё$Yb[~j#LTDBoE(sPMq6FSmi(=Hn[t`Nr$xD NcW冗	&	Gkj\vhOStUwtn<?A/\щ[ Xsqh "-V,ŌZ*~wiu;8l,{6/w~75f ?3p&݆=}ʯ@!,(^(8"\2-Z($Р^;& rSל3-QReח9W}V3 ?3m81D/;8دar[!PnHb_뮭mVtj<Ӵx_n<g퍷@CdeǁNd#,Iޜۚa5FI
Ia%wbI-ĚNO#>

^Ң!Y-	w<!RO>J,Xv}4L`Nsڏ!B=4r9mly1(=5W!lr-+z>Cİ rd yi^2YEE01\Ie:͠|̈́]kͽslM5ntQH̝ayu\QZ|9';G >;eAA-D1~vϥQ3by
c6[\`#(>#d]f+V&$?oը"縪ĳam+"E=4gn#8s	sQ{'Mxo5OSU&dpw=!tg;qjA=ٖfy;pCs@^O6M;|h793"}cP/0f&JYMQoS7;cx(~0΋;md8cp.@t؏uM9y1;[0Ij}^m>ӏ\FrReX"v]%wqx$e#_J6vso^y@A?D9<p}N^ވf_ƗD
7Ⱦ  H>ИlCkwJD(*q}yS?o װ7)tzڒbL8K4П(ȂC fuz.Φ})y: :8=A/$Xp%Tr{I{Np`/)9+COJfk;qC+#%7wd(jeUȈ}	gʊmpJ#UQ؀I?DVgxj,YpzsM.So
+mfnHMQb̞4'*;d}QԥK2 2MH#,dQ2S$˛Ӌ,Q"'7~gy0_iI8b1hP^_U,${4{/EH9 ю Ý8^'SHz+b=@`DOY&X"z10cEYkRlp+c[9Ovx:w n&"ii:}~UZj&_gʬ
y-(r<Rb:du@N~P\fu/ZN-=ݢ?	cxAג|s#.n<%8{[x8;ejmC7k{7C۶{-K~|8^GP]Ǚ`ݖ>hO5U^LAg򠁽c֓q=dKHWi4F߳o4~sMvMT1cRiZ6Y-$ToQWTt%/>`Q&
[$Rк=Fz@I{0>DU/eSp(PB=~3FL}ѥZ/cGB^V.YҰ$a@Ty9Z֊Tf\}&ޢSL-DjfX3Nᾣ1#Ɏzx8|`)U{x]lKVLTQyM8I`^Le/(S{srM66H@4,AI̸A8sZi\3?ODArƨ/fz%|{1:eUyiF|q3j<HtޠN$Z O9vKxǊQՈ""
R C`.ϳ޻zIHT~Ӽ+7tŻQ`'ر7}SZHlvvzh颊Y!.s4ghNM>NZ71P2ܙx?EB'^h{ALdJ,8UaLC@e5nc7}zn@	6ZTGQdgˬX`+cw^2qe%-
`>XZioL\d[-]7:!&4ހfsb.]$E{qA t.Zhkx|ʱ#%ף)Hv	ڥ:D,`K|W71&Fɷʟ|\pL!BpY0D\f[å-O?`cgwT_	.duV)]!8::靖	wn-)&
Vo/unkG\B7BPG#=@4qEO/(S{؟PbaafON5G"N#̍b4C,^dr:֙:k+D<R;GINCҸs_.j1dn$Z]2`XV#u3u"k&at]{]1(!4F@VՏ[r|%9B[+C7a7^.wvG	xH`zIGE(p"醎3hIW&rZFE.16N_D~f/NumFavoriteTables configuration.
     *
     * @return boolean True if trimming occurred
     */
    public function trim()
    {
        $max = max(
            $GLOBALS['cfg']['Num' . ucfirst($this->_tableType) . 'Tables'], 0
        );
        $trimming_occurred = count($this->_tables) > $max;
        while (count($this->_tables) > $max) {
            array_pop($this->_tables);
        }
        return $trimming_occurred;
    }

    /**
     * Return HTML ul.
     *
     * @return string
     */
    public function getHtmlList()
    {
        $html = '';
        if (count($this->_tables)) {
            if ($this->_tableType == 'recent') {
                foreach ($this->_tables as $table) {
                    $html .= '<li class="warp_link">';
                    $recent_params = array(
                        'db'    => $table['db'],
                        'table' => $table['table']
                    );
                    $recent_url = 'tbl_recent_favorite.php'
                        . PMA_URL_getCommon($recent_params);
                    $html .= '<a href="' . $recent_url . '">`'
                          . htmlspecialchars($table['db']) . '`.`'
                          . htmlspecialchars($table['table']) . '`</a>';
                    $html .= '</li>';
                }
            } else {
                foreach ($this->_tables as $table) {
                    $html .= '<li class="warp_link">';

                    $html .= '<a class="ajax favorite_table_anchor" ';
                    $fav_params = array(
                        'db'              => $table['db'],
                        'ajax_request'    => true,
                        'favorite_table'  => $table['table'],
                        'remove_favorite' => true
                    );
                    $fav_rm_url = 'db_structure.php'
                        . PMA_URL_getCommon($fav_params);
                    $html .= 'href="' . $fav_rm_url
                        . '" title="' . __("Remove from Favorites")
                        . '" data-favtargetn="'
                        . md5($table['db'] . "." . $table['table'])
                        . '" >'
                        . Util::getIcon('b_favorite.png')
                        . '</a>';

                    $fav_params = array(
                        'db'    => $table['db'],
                        'table' => $table['table']
                    );
                    $table_url = 'tbl_recent_favorite.php'
                        . PMA_URL_getCommon($fav_params);
                    $html .= '<a href="' . $table_url . '">`'
                        . htmlspecialchars($table['db']) . '`.`'
                        . htmlspecialchars($table['table']) . '`</a>';
                    $html .= '</li>';
                }
            }
        } else {
            $html .= '<li class="warp_link">'
                  . ($this->_tableType == 'recent'
                    ?__('There are no recent tables.')
                    :__('There are no favorite tables.'))
                  . '</li>';
        }
        return $html;
    }

    /**
     * Return HTML.
     *
     * @return string
     */
    public function getHtml()
    {
        $html  = '<div class="drop_list">';
        if ($this->_tableType == 'recent') {
            $html .= '<span title="' . __('Recent tables')
                . '" class="drop_button">'
                . __('Recent') . '</span><ul id="pma_recent_list">';
        } else {
            $html .= '<span title="' . __('Favorite tables')
                . '" class="drop_button">'
                . __('Favorites') . '</span><ul id="pma_favorite_list">';
        }
        $html .= $this->getHtmlList();
        $html .= '</ul></div>';
        return $html;
    }

    /**
     * Add recently used or favorite tables.
     *
     * @param string $db    database name where the table is located
     * @param string $table table name
     *
     * @return true|Message True if success, Message if not
     */
    public function add($db, $table)
    {
        // If table does not exist, do not add._getPmaTable()
        if (! $GLOBALS['dbi']->getColumns($db, $table)) {
            return true;
        }

        $table_arr = array();
        $table_arr['db'] = $db;
        $table_arr['table'] = $table;

        // add only if this is new table
        if (! isset($this->_tables[0]) || $this->_tables[0] != $table_arr) {
            array_unshift($this->_tables, $table_arr);
            $this->_tables = array_merge(array_unique($this->_tables, SORT_REGULAR));
            $this->trim();
            if ($this->_getPmaTable()) {
                return $this->saveToDb();
            }
        }
        return true;
    }

    /**
     * Removes recent/favorite tables that don't exist.
     *
     * @param string $db    database
     * @param string $table table
     *
     * @return boolean|Message True if invalid and removed, False if not invalid,
     *                            Message if error while removing
     */
    public function removeIfInvalid($db, $table)
    {
        foreach ($this->_tables as $tbl) {
            if ($tbl['db'] == $db && $tbl['table'] == $table) {
                // TODO Figure out a better way to find the existence of a table
                if (! $GLOBALS['dbi']->getColumns($tbl['db'], $tbl['table'])) {
                    return $this->remove($tbl['db'], $tbl['table']);
                }
            }
        }
        return false;
    }

    /**
     * Remove favorite tables.
     *
     * @param string $db    database name where the table is located
     * @param string $table table name
     *
     * @return true|Message True if success, Message if not
     */
    public function remove($db, $table)
    {
        $table_arr = array();
        $table_arr['db'] = $db;
        $table_arr['table'] = $table;
        foreach ($this->_tables as $key => $value) {
            if ($value['db'] == $db && $value['table'] == $table) {
                unset($this->_tables[$key]);
            }
        }
        if ($this->_getPmaTable()) {
            return $this->saveToDb();
        }
        return true;
    }

    /**
     * Generate Html for sync Favorite tables anchor. (from localStorage to pmadb)
     *
     * @return string
     */
    public function getHtmlSyncFavoriteTables()
    {
        $retval = '';
        $server_id = $GLOBALS['server'];
        if ($server_id == 0) {
            return '';
        }
        // Not to show this once list is synchronized.
        $is_synced = isset($_SESSION['tmpval']['favorites_synced'][$server_id]) ?
            true : false;
        if (!$is_synced) {
            $params  = array('ajax_request' => true, 'favorite_table' => true,
                'sync_favorite_tables' => true);
            $url     = 'db_structure.php' . PMA_URL_getCommon($params);
            $retval  = '<a class="hide" id="sync_favorite_tables"';
            $retval .= ' href="' . $url . '"></a>';
        }
        return $retval;
    }

    /**
     * Generate Html to update recent tables.
     *
     * @return string html
     */
    public static function getHtmlUpdateRecentTables()
    {
        $params  = array('ajax_request' => true, 'recent_table' => true);
        $url     = 'index.php' . PMA_URL_getCommon($params);
        $retval  = '<a class="hide" id="update_recent_tables"';
        $retval .= ' href="' . $url . '"></a>';
        return $retval;
    }

    /**
     * Reutrn the name of the configuration storage table
     *
     * @return string pma table name
     */
    private function _getPmaTable()
    {
        $cfgRelation = PMA_getRelationsParam();
        if (! empty($cfgRelation['db'])
            && ! empty($cfgRelation[$this->_tableType])
        ) {
            return Util::backquote($cfgRelation['db']) . "."
                . Util::backquote($cfgRelation[$this->_tableType]);
        }
        return null;
    }
}
