<?php

# PLUGIN PREVIEW BY TEXTPATTERN.INFO


/*
    adi_recent_tab - Recent Items Tab

    Written by Adi Gilbert

    Released under the GNU General Public License

    Version history:
    0.6        - refixed for critical, admin interface killing, bug in TXP 4.6
            - responsive layout & styling for recent items tab
            - fix: recognises "upload file from existing"
            - enhancement: pref for image alt text (for Uli)
    0.5        - change: IDs display switched on by default
            - change: articles heading link now goes to Articles (list) tab rather than Write
            - fix: error when reordering images/files in list
            - fix: error when changing number of items per page
            - fix: error when file upload failed (e.g. file too big/file already exists)
            - fix: article titles etc that are blank with multiple spaces are treated as Untitled
            - fix: unslashed quotes in DB queries
            - fix: tabs no longer listed if user lacks privs
            - fix: upload thumbnail now ignored
            - fix: all new section names sanitised & recognised
            - enhancement: plugin privs
            - code tidy up (thanks gocom)
            - TXP 4.5+
            - tested & fixed for TXP 4.6
    0.4        - TXP 4.5-ified (particularly to cope with new Sections tab & new-style Links tab)
            - fix: record new links properly
            - fix: losing image (file) name if both alt & caption blank
    0.3        - style improvements to cope with long titles
            - fix: style for latest version of Hive theme (thanks Uli)
            - fix: error message in images & files search result page (thanks Uli)
    0.2        - fix: cope with image replace & file replace properly
            - fix: cope with style create/save/delete properly
            - new pref: include article/image/link/file IDs
    0.1        - initial release

*/

if (@txpinterface == 'admin') {

    global 
$adi_recent_tab_debug;

    
$adi_recent_tab_debug 0;

    if (!
version_compare(txp_version,'4.5.0','>=')) return;

    
adi_recent_tab_init();

}

function 
adi_recent_tab_init() {
    global 
$event,$step,$textarray,$txp_user,$prefs,$adi_recent_tab_outlaws,$adi_recent_tab_url,$adi_recent_tab_plugin_status,$adi_recent_tab_event_gtxt,$adi_recent_tab_include,$adi_recent_tab_exclude_combo,$adi_recent_tab_include_combo,$adi_recent_tab_prefs,$adi_recent_tab_debug,$adi_recent_tab_txp460;

    
// meet the new boss?
    
$adi_recent_tab_txp460 = (version_compare(txp_version,'4.6-dev','>='));

    
// plugin lifecycle
    
register_callback('adi_recent_tab_lifecycle','plugin_lifecycle.adi_recent_tab');

    
// Textpack
    
$adi_recent_tab_url = array(
        
'textpack' => 'http://www.greatoceanmedia.com.au/files/adi_textpack.txt',
        
'textpack_download' => 'http://www.greatoceanmedia.com.au/textpack/download',
        
'textpack_feedback' => 'http://www.greatoceanmedia.com.au/textpack/?plugin=adi_recent_tab',
    );
    if (
strpos($prefs['plugin_cache_dir'],'adi') !== FALSE// use Adi's local version
        
$adi_recent_tab_url['textpack'] = $prefs['plugin_cache_dir'].'/adi_textpack.txt';

# --- BEGIN PLUGIN TEXTPACK ---
    
$adi_recent_tab_gtxt = array(
        
'adi_include' => 'Include:',
        
'adi_include_ids' => 'Include IDs',
        
'adi_install_fail' => 'Unable to install',
        
'adi_installed' => 'Installed',
        
'adi_pref_update_fail' => 'Preference update failed',
        
'adi_recent_items' => 'Recent items',
        
'adi_recent_tab' => 'Recent',
        
'adi_recent_tab_max_items' => 'Maximum number of items',
        
'adi_tab' => 'Tab',
        
'adi_textpack' => 'Textpack',
        
'adi_textpack_fail' => 'Textpack installation failed',
        
'adi_textpack_feedback' => 'Textpack feedback',
        
'adi_textpack_online' => 'Textpack also available online',
        
'adi_uninstall' => 'Uninstall',
        
'adi_uninstall_fail' => 'Unable to uninstall',
        
'adi_uninstalled' => 'Uninstalled',
        
'adi_update_prefs' => 'Update preferences',
    );
# --- END PLUGIN TEXTPACK ---

    // update $textarray
    
$textarray += $adi_recent_tab_gtxt;

    
/*
        Events & Steps - A minefield of inconsistencies ...

                        Step            other vars
    Event=article
        Write            create            -            (empty create tab)
        Edit            edit            ID
        Save            edit            ID
        Publish            create -> edit    $GLOBALS['ID']

    Event=image
        Images list        -
            (search)    image_list
            (sort)        list
            (paging)    image_change_pageby
        Image upload    image_insert    $GLOBALS['ID']
        Image edit        image_edit        id
        Image save        image_edit        id
        Image replace    image_replace    id
        Thumbnail upld    thumbnail_insert

    Event=page
        Pages/default    -
        Page edit        -                name
        Save            page_save        name
        Copy            page_save        name, newname
        Create page        page_save        newname

    Event=form
        Forms/default    -
        Form edit        form_edit        name
        Form save        form_save

    Event=link
        Links list        - -> link_edit
            (search)    link_list
            (sort)        list
            (paging)    link_change_pageby
        Link edit        link_edit        id
        Link save        link_save        id
        Link create        link_post        $GLOBALS['ID']    (pre-4.5.0)
        Link create        link_save        $GLOBALS['ID']    (post-4.5.0)

    Event=file
        Files list        -
            (search)    file_list
            (sort)        list
            (paging)    file_change_pageby
        Upload            file_insert        $GLOBALS['ID']
        Save            file_save        ?
        File edit        file_edit        id
        File replace    file_replace    id
        From existing    file_create        name

    Event=css
        Style/default    -
        Style edit        -                name
        Save            css_save        name
        New style        pour            newname
        Copy style        css_save        name

    Event=section
        Section list    -
            (search)    sec_section_list
            (sort)        list
            (paging)    section_change_pageby
        Section edit    section_edit    name
        Section create    section_edit    -        (empty create tab)
        Section save    section_save    name
        Section create    section_save    newname    (post-4.5.0)
    */

    // the privileged few ...
    
$adi_recent_tab_include = array('article','image','page','form','link','file','css','section'); // if you're not on the list, you're not getting in

    // privileges for the privileged
    
$adi_recent_tab_include_privs = array(
        
'article' => 'list',
        
'image' => 'image',
        
'page' => 'page',
        
'form' => 'form',
        
'link' => 'link',
        
'file' => 'file',
        
'css' => 'css',
        
'section' => 'section',
    );

    if (
$adi_recent_tab_debug)
        foreach (
$adi_recent_tab_include as $index => $tab)
            if (
has_privs($adi_recent_tab_include_privs[$tab]))
                echo 
$tab.sp.'- has privs'.br;
            else
                echo 
$tab.sp.'- no privs'.br;

    
// weed out the unworthy
    
foreach ($adi_recent_tab_include as $index => $tab)
        if (!
has_privs($adi_recent_tab_include_privs[$tab]))
            unset(
$adi_recent_tab_include[$index]);

    
// it's what we call 'em
    
$adi_recent_tab_event_gtxt = array(
        
'article'    => 'tab_list',
        
'css'        => 'tab_style',
        
'file'        => 'tab_file',
        
'form'        => 'tab_forms',
        
'image'        => 'tab_image',
        
'link'        => 'tab_link',
        
'page'        => 'tab_pages',
        
'section'    => 'tab_sections',
    );

    
// not so fast ...
    
$adi_recent_tab_exclude_combo[] = array('event' => '^article$''step' => '^$'); // empty create article tab - event="article", step=blank
    
$adi_recent_tab_exclude_combo[] = array('event' => '^image$''step' => '^$'); // image list tab - event="image", step=blank
    
$adi_recent_tab_exclude_combo[] = array('event' => '^image$''step' => 'image_multi_edit'); // image list multi-edit - event="image", step contains image_multi_edit
    
$adi_recent_tab_exclude_combo[] = array('event' => '^image$''step' => 'image_replace'); // image replace - event="image", step contains image_multi_edit
    
$adi_recent_tab_exclude_combo[] = array('event' => '^image$''step' => 'list'); // image list - event="image", step contains list (search results=image_list,sort=list)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^image$''step' => '^thumbnail_insert$'); // thumbnail upload - event="image", step=thumbnail_insert
    
$adi_recent_tab_exclude_combo[] = array('event' => '^page$''step' => 'page_new'); // new page tab - event="page", step contains page_new
    
$adi_recent_tab_exclude_combo[] = array('event' => '^form$''step' => 'form_multi_edit'); // form list multi-edit - event="form", step contains form_multi_edit
    
$adi_recent_tab_exclude_combo[] = array('event' => '^link$''step' => 'link_edit''id' => '^$'); // link list tab
    
$adi_recent_tab_exclude_combo[] = array('event' => '^link$''id' => '^$'); // TXP 4.5 link list tab
    
$adi_recent_tab_exclude_combo[] = array('event' => '^link$''step' => 'link_multi_edit'); // link list tab - event="link", step contains link_multi_edit
    
$adi_recent_tab_exclude_combo[] = array('event' => '^file$''step' => '^$'); // file list tab - event="file", step=blank
    
$adi_recent_tab_exclude_combo[] = array('event' => '^file$''step' => 'file_replace'); // file replace - event="file", step contains file_replace
    
$adi_recent_tab_exclude_combo[] = array('event' => '^file$''step' => 'list'); // file list - event="file", step contains list (search results=file_list,sort=list)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^css$''step' => 'pour'); // style list tab - event="css", step=pour (create style)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^section$''step' => 'section_edit''name' => '^$'); // empty section create tab (TXP 4.5.0)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^section$''step' => 'list'); // section list - event="section", step contains list (search results=sec_section_list,sort=list)
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'save'); // any step containing "save" (e.g. page_save, form_save, link_save)
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'create'); // any step containing "create" (e.g. new article create, form create)
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'apply'); // any step containing "apply" - just in case!
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'update'); // any step containing "update" - just in case!
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'delete'); // any step containing "delete" - just in case!
    
$adi_recent_tab_exclude_combo[] = array('event' => '.*''step' => 'change_pageby'); // any step containing "change_pageby", e.g. image_change_pageby, when changing # per page
    // don't log initial page/form/style tab visit (i.e. default by default)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^page$''step' => '^$''name' => '^$'); // default page tab (i.e. edit default)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^form$''step' => '^$''name' => '^$'); // default form tab (i.e. edit default)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^css$''step' => '^$''name' => '^$'); // default style tab (i.e. edit default)
    
$adi_recent_tab_exclude_combo[] = array('event' => '^section$''step' => '^$''name' => '^$'); // default section list tab (TXP 4.5.0)

    // oh, go on then ...
    
$adi_recent_tab_include_combo[] = array('event' => 'page''step' => 'page_save'); // create new page
    
$adi_recent_tab_include_combo[] = array('event' => 'form''step' => 'form_save'); // create new form
    
$adi_recent_tab_include_combo[] = array('event' => 'css''step' => 'css_save'); // create new form
    
$adi_recent_tab_include_combo[] = array('event' => 'file''step' => 'file_create'); // create file from existing
    
$adi_recent_tab_include_combo[] = array('event' => 'link''step' => 'link_post'); // create new link (pre-4.5.0)
    
$adi_recent_tab_include_combo[] = array('event' => 'link''step' => 'link_save'); // create new link (post-4.5.0)
    
$adi_recent_tab_include_combo[] = array('event' => 'section''step' => 'section_save'); // create new section (TXP 4.5.0+)

    // preferences & defaults
    
$adi_recent_tab_prefs = array(
        
'adi_recent_tab_privs' => array('value' => '1,2,3,4,5,6''blank' => 1'private' => 0'input' => 'custom''label' => 'adi_plugin_privs''tab' => 'options'), // allowed to use plugin
        
'adi_recent_tab_list' => array('value' => implode(',',$adi_recent_tab_include), 'blank' => 0'private' => 1'input' => 'custom''label' => 'adi_include''tab' => 'admin'),
        
'adi_recent_tab_max_items' => array('value' => '5''blank' => 0'private' => 1'input' => 'text_input''label' => 'adi_recent_tab_max_items''tab' => 'admin'),
        
'adi_recent_tab_ids' => array('value' => '1''blank' => 1'private' => 1'input' => 'yesnoradio''label' => 'adi_include_ids''tab' => 'admin'),
        
'adi_recent_tab_img_alt' => array('value' => '1''blank' => 1'private' => 1'input' => 'yesnoradio''label' => 'alt_text''tab' => 'admin'),
    );

    
// plugin privs to be excluded
    
$adi_recent_tab_outlaws = array(0);

    
// who's playing today?
    
add_privs('adi_recent_tab',adi_recent_tab_pref('adi_recent_tab_privs')); // recent items tab
    
add_privs('tab.recent',adi_recent_tab_pref('adi_recent_tab_privs')); // recent items menu

    // do the business
    
if (adi_recent_tab_installed() && has_privs('adi_recent_tab')) {
        
// menu style for all
        
register_callback('adi_recent_tab_menu_style','admin_side','head_end');
        
// tab style for tab only
        
if ($event == "adi_recent_tab")
            
register_callback('adi_recent_tab_style','admin_side','head_end');
        
// adi_recent_tab tab
        
register_callback("adi_recent_tab","adi_recent_tab");
        
$textarray['tab_recent'] = gTxt('adi_recent_tab'); // to get something meaningful into tab
        // put logger in the footer - to catch the elusive newly created article/image IDs etc
        
register_callback('adi_recent_tab_logger','admin_side','footer');
        
// TXP 4.5: recent tab under recent items menu; TXP 4.6: recent tab under extensions menu (due to lack of top-level click-through)
        
if ($adi_recent_tab_txp460) {
            
// recent items tab under extensions
            
register_tab('extensions','adi_recent_tab',gTxt('adi_recent_items'));
            
// separate recent items menu
            
add_privs('adi_recent_tab_menu',adi_recent_tab_pref('adi_recent_tab_privs')); // recent items tab
            
register_tab('recent','adi_recent_tab_menu',gTxt('adi_recent_items'));
            
register_callback('adi_recent_tab_menu','adi_recent_tab_menu');
            
// inject markup to create recent items menu
            
register_callback('adi_recent_tab_menu_markup_mega','admin_side','footer'); // markup in the footer, shifted by jQuery
        
}
        else {
            
// recent items tab under separate recent items menu
            
register_tab('recent','adi_recent_tab',gTxt('adi_recent_items'));
            
// inject markup to create recent items menu
            
adi_recent_tab_menu_ob();
        }
    }

    
// script
    
if ($adi_recent_tab_txp460)
        
register_callback('adi_recent_tab_script','admin_side','head_end');

    
// plugin options
    
$adi_recent_tab_plugin_status fetch('status','txp_plugin','name','adi_recent_tab');
    if (
$adi_recent_tab_plugin_status) { // proper install - options under Plugins tab
        
add_privs('plugin_prefs.adi_recent_tab','1,2,6');
        
register_callback('adi_recent_tab_options','plugin_prefs.adi_recent_tab');
    }
    else { 
// txpdev - options under Extensions tab
        
add_privs('adi_recent_tab_options','1,2,6');
        
register_tab('extensions','adi_recent_tab_options','adi_recent_tab options');
        
register_callback('adi_recent_tab_options','adi_recent_tab_options');
    }
}

function 
adi_recent_tab_style() {
// style for tab
    
echo
        
'<style type="text/css">
            /* adi_recent_tab */
            #adi_recent_tab_tab, #adi_recent_tab_tab ul { overflow:hidden; list-style:none; margin:0; padding:0 }
            #adi_recent_tab_tab li { list-style:none; margin:0; padding:0 }
            #adi_recent_tab_tab > li { float:left; width:47%; margin:0 6% 1% 0 }
            #adi_recent_tab_tab > li:nth-child(2n) { margin-right:0 }
            #adi_recent_tab .adi_recent_tab_prefs { margin:4em 0 2em; border-top:1px solid #ccc }
            #adi_recent_tab input.adi_recent_tab_max_items { width:3em }
            /* responsive */
            @media (max-width: 47em) {
                #adi_recent_tab_tab > li { float:none; width:100% }
                .adi_recent_tab_prefs p.adi_recent_tab_list label { display:block; margin-top:0.5em }
            }
            /* TXP 4.5 */
            div.txp-body h1, div.txp-body h2 { font-weight:bold }
            div.txp-body .adi_recent_tab_prefs h2 { margin-top:0.5em }
            /* Hive TXP 4.5 adjustments - recent tab page given class="recent" which is Hive styling for Recent Articles! */
            .txp-nav li { margin-left:0 }
        </style>'
;
}

function 
adi_recent_tab_menu_style() {
// style for dropdown menu
    
echo
        
'<style type="text/css">
            /* adi_recent_tab */
            /* TXP 4.5 Remora */
            #nav .adi_recent_tab_menu_title { font-weight:bold }
            #nav a[href="?event=adi_recent_tab"] + ul { width:25em; padding-top:0.5em; padding-bottom:0.5em }
            #nav a[href="?event=adi_recent_tab"] + ul li { width:auto; height:auto }
            #nav a[href="?event=adi_recent_tab"] + ul li:first-child { display:none }
            #nav a[href="?event=adi_recent_tab"] + ul li a { width:23em; height:auto; line-height:1.2; padding-top:0.3em; padding-bottom:0.3em }
            #nav a[href="?event=adi_recent_tab"] + ul li a span { font-weight:bold }
            .txp-header #nav a[href="?event=adi_recent_tab"] + ul { z-index:9999 }
            /* TXP 4.5 Hive */
            div.txp-nav .adi_recent_tab_menu_title { font-weight:bold }
            div.txp-nav a[href="?event=adi_recent_tab"] + ul { padding-bottom:0.5em }
            div.txp-nav a[href="?event=adi_recent_tab"] + ul { width:25em }
            div.txp-nav a[href="?event=adi_recent_tab"] + ul > li { float:none; width:auto }
            div.txp-nav a[href="?event=adi_recent_tab"] + ul > li:hover { background-color:#ffefaf }
            /* TXP 4.6 Hive */
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul > li:first-child { display:none }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul { width:50em }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul > li { float:left; width:50% }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul > li:hover { background-color:transparent }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul > li:nth-child(2n) { clear:left }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul li h2 { margin:0.5em 0 0; font-size:1em }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul li h2:hover { background-color:#ffefaf }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul li a { width:auto; padding-top:0.3em; padding-bottom:0.3em; word-wrap:break-word }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul ul { width:auto }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul { left:-20em; border-radius:0.5em }
            nav.txp-nav a[href="?event=adi_recent_tab"] + ul:before { left:18em } /* the pointy bit */
            /* bot_write_tab_customize tab overrides */
            body#page-bot_wtc_tab .txp-nav a[href="?event=adi_recent_tab"] + ul li h2 { margin:0.5em 0 0; padding:0; text-align:left }
            /* responsive */
            @media (max-width: 47em) {
                nav.txp-nav a[href="?event=adi_recent_tab"] + ul { width:auto }
                nav.txp-nav a[href="?event=adi_recent_tab"] + ul li a { width:auto; padding-top:0.5em; padding-bottom:0.5em }
            }
        </style>'
;
}

function 
adi_recent_tab_script() {
// scriptimus

    
echo <<<END_SCRIPT
<script type="text/javascript">
    $(function() {
        // adi_recent_tab menu
        var closest_ul = $('a[href="?event=adi_recent_tab_menu"]').closest("ul"); // find (grand)parent ul
        var menu_id = $(closest_ul).attr('id'); // i.e. "#txp-nav-dropX-menu"
        $("ul#adi_recent_tab_inject > li").insertAfter($("ul#" + menu_id + " li")); // shift recent menu items from footer
        $("ul#adi_recent_tab_inject").remove(); // footer housekeeping
        var top_link = $(closest_ul).prev(); // get top level menu item link
        $(top_link).attr("href","?event=adi_recent_tab"); // restore click-through to recent_tab tab (also allows some styles to kick in)
    });
</script>
END_SCRIPT;
}

function 
adi_recent_tab_logger() {
// monitor each TXP admin page visit & decide what's to be recorded by adi_recent_tab
    
global $DB,$adi_recent_tab_debug,$event,$step,$txp_user,$adi_recent_tab_include,$adi_recent_tab_exclude_combo,$adi_recent_tab_include_combo,$adi_recent_tab_txp460;

    if (!
adi_recent_tab_installed()) // in case it's just been uninstalled
        
return;

    
$id gps('id'); // image id
    
$name gps('name'); // section/page/form/image name

    
if ($adi_recent_tab_debug) {
        echo 
'Event='.$event.', Final Step='.$step.', supplied id='.$id.', supplied name='.$name.'<br/>';
        echo 
'Include event list:';
        
dmp($adi_recent_tab_include);
        echo 
'Exclude combo list:';
        
dmp($adi_recent_tab_exclude_combo);
        echo 
'Include combo list:';
        
dmp($adi_recent_tab_include_combo);
    }

    
// process included & excluded events/steps
    // events of interest
    
$exclude array_search($event,$adi_recent_tab_include) === FALSE;
    if (
$adi_recent_tab_debug && $exclude)
        echo 
'($adi_recent_tab_include) EXCLUDE EVENT: '.$event.'<br/>';
    
// sort the men from the boys
    
if (!$exclude) {
        
// event/step combos to be discounted
        
$exclude adi_recent_tab_filter($adi_recent_tab_exclude_combo,$event,$step,$id,$name);
        if (
$adi_recent_tab_debug && $exclude)
            echo 
'($adi_recent_tab_exclude_combo) '."EXCLUDED EVENT/STEP/ID/NAME: $event,$step,$id,$name<br/>";

        
// explicitly include these combos
        
$include adi_recent_tab_filter($adi_recent_tab_include_combo,$event,$step,$id,$name);
        if (
$adi_recent_tab_debug && $include)
            echo 
'($adi_recent_tab_include_combo) '."INCLUDED EVENT/STEP/ID/NAME: $event,$step,$id,$name<br/>";
        if (
$include)
            
$exclude FALSE;
    }

    if (!
$exclude) { // massage stuff
        // ID
        
if (empty($id)) // try finding an article ID
            
$id gps('ID');
        if (isset(
$GLOBALS['ID'])) // set the "newly created" ID to something
            
$globals_id $GLOBALS['ID'];
        else
            
$globals_id '';
        if (empty(
$id) && ($event == 'article')) // i.e. a newly created article
            
$id $globals_id;
        if (empty(
$id) && ($event == 'image')) // i.e. a newly created image
            
$id $globals_id;
        if (empty(
$id) && ($event == 'link')) // i.e. a newly created link
            
$id $globals_id;
        if (empty(
$id) && ($event == 'file')) // i.e. a newly uploaded file
            
$id $globals_id;
        
// NAME
        
if (($event == 'section') && ($step == 'section_save'))
            
$name strtolower(sanitizeForUrl($name)); // sanitise (create/edit) section name (from txp_section.php)
        
if ((($event == 'page') || ($event == 'form')) && empty($name)) // fill in the "default" blank - needed if logging initial page/form tab visit
            
$name 'default';
        if (
$event == 'image'// don't want to store image name coz we've got the ID (& the name might change)
            
$name '';
        
$newname sanitizeForPage(gps('newname')); // sanitise (create/copy) page name
        
if ($newname)
            
$name $newname;
        
// STEP
        
$this_step $step;
        if ((
$event== 'image') && ($step == 'image_insert')) // tweak step - new image
            
$this_step 'image_edit';
        if ((
$event== 'page') && ($step == 'page_save')) // new/save page
            
$this_step '';
        if ((
$event== 'form') && ($step == 'form_save')) // new/save form
            
$this_step 'form_edit';
        if ((
$event== 'css') && ($step == 'css_save')) // new style/save style
            
$this_step '';
        if ((
$event== 'form') && ($step == '')) // tweak step - click between forms
            
$this_step 'form_edit';
        if ((
$event== 'link') && ($step == 'link_post')) // new link (pre-4.5.0)
            
$this_step 'link_edit';
        if ((
$event== 'link') && ($step == 'link_save')) // new link (post-4.5.0)
            
$this_step 'link_edit';
        if ((
$event== 'section') && ($step == 'section_save')) // new section (post-4.5.0)
            
$this_step 'section_edit';
        if ((
$event== 'file') && ($step == 'file_insert')) // new file
            
$this_step 'file_edit';
        if ((
$event== 'file') && ($step == 'file_create')) // new file from existing
            
$this_step 'file_edit';
        if (
$adi_recent_tab_debug)
            echo 
'Event='.$event.', this_step='.$this_step.', massaged id='.$id.', massaged name='.$name.'<br/>';

        if (
$id == '' && (($event == 'article') || ($event == 'image') || ($event == 'link') || ($event == 'file'))) {
            if (
$adi_recent_tab_debug)
                echo 
'No ID, no update!';
        }
        else {
            
// update adi_recent_tab DB table
            
$table 'adi_recent_tab';
            
$set 'timestamp=now(), user="'.doSlash($txp_user).'", event="'.doSlash($event).'", step="'.doSlash($this_step).'", id="'.doSlash($id).'", name="'.doSlash($name).'"';
            
$where 'user="'.$txp_user.'" AND event="'.$event.'" AND step="'.$this_step.'" AND id="'.$id.'" AND name="'.$name.'"';
            
// it's me own safe_upsert ...
            
$r safe_update($table,$set,$where,$adi_recent_tab_debug);
            if (
$adi_recent_tab_txp460) {
                if (!(
$r and (mysqli_affected_rows($DB->link) or safe_count($table,$where,$adi_recent_tab_debug))))
                    
safe_insert($table,$set,$adi_recent_tab_debug);
            }
            else {
                if (!(
$r and (mysql_affected_rows() or safe_count($table,$where,$adi_recent_tab_debug))))
                    
safe_insert($table,$set,$adi_recent_tab_debug);
            }
        }
    }

    
// tidy up
    
adi_recent_tab_housekeeping();
}

function 
adi_recent_tab_filter($pattern_list,$event,$step,$id='',$name='') {
// look for combination matches

    
$match FALSE;
    foreach (
$pattern_list as $pair) {
        
$this_match TRUE;
        foreach (
$pair as $var => $pattern)
            
$this_match $this_match && preg_match('/'.$pattern.'/',$$var);
        
$match $match || $this_match;
    }
    return 
$match;
}

function 
adi_recent_tab_installed($table='adi_recent_tab') {
// test if table is present
    
$rs safe_query("SHOW TABLES LIKE '".safe_pfx($table)."'");
    
$a nextRow($rs);
    if (
$a)
        return 
TRUE;
    else
        return 
FALSE;
}

function 
adi_recent_tab_install() {
// install adi_recent_tab table in database
    
global $adi_recent_tab_debug;

    
$res safe_query(
        
// 'id' is a VARCHAR (rather than an INT) coz I need it to be blank sometimes
        
"CREATE TABLE IF NOT EXISTS ".safe_pfx('adi_recent_tab')
        .
"(    `timestamp` datetime NOT NULL default '0000-00-00 00:00:00',
            `user` VARCHAR(64) NOT NULL DEFAULT '',
            `event` VARCHAR(64) NOT NULL DEFAULT '',
            `step` VARCHAR(64) NOT NULL DEFAULT '',
            `id` VARCHAR(12) NOT NULL DEFAULT '',
            `name` VARCHAR(64) NOT NULL DEFAULT ''
        );"
        
,$adi_recent_tab_debug);
     return 
$res;
}

function 
adi_recent_tab_uninstall() {
// uninstall adi_recent_tab
    
global $adi_recent_tab_debug,$adi_recent_tab_prefs;

    
// delete table
    
$res safe_query("DROP TABLE ".safe_pfx('adi_recent_tab').";",$adi_recent_tab_debug);
    
// delete preferences
    
foreach ($adi_recent_tab_prefs as $this_pref => $value)
        
$res $res && safe_delete('txp_prefs',"name = '$this_pref'",$adi_recent_tab_debug);
    return 
$res;
}

function 
adi_recent_tab_lifecycle($event,$step) {
// a matter of life & death
// $event:    "plugin_lifecycle.adi_recent_tab"
// $step:    "installed", "enabled", disabled", "deleted"
// install/reinstall: "installed"; make active: "enabled"; make inactive: "disabled"; delete: "disabled" then "deleted"
// (as of TXP 4.5, reinstall only triggers "installed" event)
// adi_lifecycle: "installed" -> install() regardless, upgrade() if required; "deleted" -> uninstall(); "enabled" & disabled" -> do nothing
    
global $adi_recent_tab_debug;

    
$result $upgrade_required '?';
    if (
$step == 'installed') {
        
$result adi_recent_tab_install();
//         $upgrade_required = adi_recent_tab_upgrade();
//         if ($upgrade_required)
//             $result &= adi_recent_tab_upgrade(TRUE);
    
}
    if (
$step == 'deleted')
        
$result adi_recent_tab_uninstall();
    if (
$adi_recent_tab_debug)
        echo 
"event=$event,step=$step,result=$result,upgrade_required=$upgrade_required";
}

function 
adi_recent_tab_housekeeping() {
// delete oldest recents that exceed max count; make sure items still exist in DB
    
global $adi_recent_tab_debug,$txp_user,$adi_recent_tab_include,$adi_recent_tab_prefs;

    
$max_recent adi_recent_tab_pref('adi_recent_tab_max_items');

    
$sort ' ORDER BY timestamp desc';
    
$default_where " AND user='$txp_user'";

    if (
$adi_recent_tab_debug)
        echo 
'<br/>Housekeeping (deceased entries):<br/>';

    
// delete entries that don't exist ... the recently deceased
    
foreach ($adi_recent_tab_include as $recent) {
        
$table 'txp_'.$recent;
        if (
$recent == 'article')
            
$table 'textpattern';
        
$rs safe_rows('*','adi_recent_tab',"event='".$recent."'".$default_where.$sort,$adi_recent_tab_debug);
        foreach (
$rs as $index => $row) {
            
extract($row);
            
// "id" entries
            
if (($recent == 'article') || ($recent == 'image') || ($recent == 'link') || ($recent == 'file')) {
                
$row safe_row('*',$table,"id='$id'",$adi_recent_tab_debug);
                if (empty(
$row)) {
                    
$where 'user="'.$txp_user.'" AND event="'.$event.'" AND step="'.$step.'" AND id="'.$id.'" AND name="'.doSlash($name).'"';
                    
safe_delete('adi_recent_tab',$where,$adi_recent_tab_debug);
                }
            }
            
// "name" entries
            
if (($recent == 'page') || ($recent == 'form') || ($recent == 'css') || ($recent == 'section')) {
                
$row safe_row('*',$table,"name='".doSlash($name)."'",$adi_recent_tab_debug);
                if (empty(
$row)) {
                    
$where 'user="'.$txp_user.'" AND event="'.$event.'" AND step="'.$step.'" AND id="'.$id.'" AND name="'.doSlash($name).'"';
                    
safe_delete('adi_recent_tab',$where,$adi_recent_tab_debug);
                }
            }
        }
    }

    if (
$adi_recent_tab_debug)
        echo 
'Housekeeping (remove surplus):<br/>';

    
// lose the surplus
    
foreach ($adi_recent_tab_include as $recent) {
        
$rs safe_rows('*','adi_recent_tab',"event='".$recent."'".$default_where.$sort,$adi_recent_tab_debug);
        if (
count($rs) > $max_recent)
            foreach (
$rs as $index => $row) {
                
extract($row);
                if (!(
$index $max_recent)) {
                    
$where 'user="'.$txp_user.'" AND event="'.$event.'" AND step="'.$step.'" AND id="'.$id.'" AND name="'.doSlash($name).'"'// BIG GLOBAL FOR THIS WHERE???
                    
safe_delete('adi_recent_tab',$where,$adi_recent_tab_debug);
                }
            }
    }
}

function 
adi_recent_tab_links($event,$wrap=TRUE) {
// return a <ul><li> or <li> of all the "recent" links
    
global $adi_recent_tab_debug,$adi_recent_tab_prefs,$txp_user;

//    $sort_method = 'timestamp';
    
$sort_method 'alphanumeric';

    
$default_where " AND user = '$txp_user'";

    if (
$sort_method == 'timestamp') {
        
$sort ' ORDER BY timestamp desc';
        
$rs safe_rows('*','adi_recent_tab',"event = '$event'".$default_where.$sort,$adi_recent_tab_debug);
    }
    else if (
$sort_method == 'alphanumeric') {
        if (
$event == 'article') {
            
$sort ' ORDER BY Title';
            
$rs safe_rows('Title,textpattern.ID,adi_recent_tab.*','textpattern, adi_recent_tab',"event = '$event' AND textpattern.ID = adi_recent_tab.id".$default_where.$sort,$adi_recent_tab_debug);
        }
        else if (
$event == 'image') {
            
$sort ' ORDER BY alt,txp_image.name';
            
// note that actual name is last in list of fields - image name not stored by adi_recent_tab, so don't want blank to override proper name
            
$rs safe_rows('adi_recent_tab.*,alt,txp_image.name','txp_image, adi_recent_tab',"event = '$event' AND txp_image.id = adi_recent_tab.id".$default_where.$sort,$adi_recent_tab_debug);
        }
        else if (
$event == 'file') {
            
$sort ' ORDER BY title,filename';
            
$rs safe_rows('title,filename,adi_recent_tab.*','txp_file, adi_recent_tab',"event = '$event' AND txp_file.id = adi_recent_tab.id".$default_where.$sort,$adi_recent_tab_debug);
        }
        else if (
$event == 'link') {
            
$sort ' ORDER BY linkname,url';
            
$rs safe_rows('linkname,url,adi_recent_tab.*','txp_link, adi_recent_tab',"event = '$event' AND txp_link.id = adi_recent_tab.id".$default_where.$sort,$adi_recent_tab_debug);
        }
        else { 
// page, form, style, section
            
$sort ' ORDER BY name';
            
$rs safe_rows('*','adi_recent_tab',"event='$event'".$default_where.$sort,$adi_recent_tab_debug);
        }
    }

    if (
$adi_recent_tab_debug)
        
dmp($rs);

    
$out '';

    foreach (
$rs as $index => $row) {
        
$item '';
        
extract($row);
        
// link text fiddling
        
if ($event == 'article') { // use article title, or Untitled if empty
            
$Title trim($Title);
            if (empty(
$Title))
                
$link_text gTxt('untitled');
            else
                
$link_text $Title;
        }
        else if (
$event == 'image') { // use alt text, or name if blank
            
$alt trim($alt);
            if (empty(
$alt) || !adi_recent_tab_pref('adi_recent_tab_img_alt'))
                
$link_text $name;
            else
                
$link_text $alt;
        }
        else if (
$event == 'link') { // use link name, or url if blank
            
$linkname trim($linkname);
            if (empty(
$linkname))
                
$link_text $url;
            else
                
$link_text $linkname;
        }
        else if (
$event == 'file') { // use title, or filename if blank
            
$title trim($title);
            if (empty(
$title))
                
$link_text $filename;
            else
                
$link_text $title;
        }
        else if (
$event == 'section'// use name
                
$link_text $name;
        
// include IDs?
        
if (adi_recent_tab_pref('adi_recent_tab_ids') && ($id != ''))
            
$link_text .= ' ('.tag($id,'span').')';
        
// links to items
        
if ($event == 'article')
            
$item .= '<a href="?event='.$event.a.'step='.$step.a.'ID='.$id.'">'.$link_text.'</a>';
        else if ((
$event == 'image') || ($event == 'link') || ($event == 'file'))
            
$item .= '<a href="?event='.$event.a.'step='.$step.a.'id='.$id.'">'.$link_text.'</a>';
        else if (
$event == 'section')
            
$item .= '<a href="?event='.$event.a.'step='.$step.a.'name='.$name.'">'.$link_text.'</a>';
        else
            
$item .= '<a href="?event='.$event.a.'name='.$name.'">'.$name.'</a>';
        
$out .= tag($item,'li',' class="adi_recent_tab_menu_item"').n;
    }

    if (
$wrap)
        return 
tag($out,'ul');
    else
        return 
$out;
}

function 
adi_recent_tab($event,$step) {
// the page that displays all the "recent" links
    
global $adi_recent_tab_debug,$adi_recent_tab_event_gtxt,$adi_recent_tab_include,$adi_recent_tab_prefs,$adi_recent_tab_txp460;

    
$message'';
    if (
$step == 'update_prefs') {
        
$result adi_recent_tab_update_prefs('admin');
        
$result $message gTxt('preferences_saved') : $message = array(gTxt('adi_pref_update_fail'),E_ERROR);
        
adi_recent_tab_housekeeping(); // do extra housekeeping to reflect possible change in max items (habitually done at bottom of page)
    
}

    
// generate page
    
pagetop('adi_recent_tab '.gTxt('adi_recent_tab'),$message);

    echo 
'<div id="adi_recent_tab">';

    echo 
tag(gTxt('adi_recent_items'),'h1');

    
// generate list of recents
    
echo tag(implode(n,adi_recent_tab_list_markup()),'ul',' id="adi_recent_tab_tab"');

    
// preferences
    
echo adi_recent_tab_pref_inputs($event,'admin');

    echo 
'</div>';

    if (
$adi_recent_tab_debug)
        echo 
adi_recent_tab_db_dump();
}

function 
adi_recent_tab_menu_ob() {
// the old-fashioned magic that gets the recent items into adi_recent_tab's menu - TXP 4.5
     
ob_start('adi_recent_tab_menu_inject');
}

function 
adi_recent_tab_menu_inject($buffer) {
// another bit of arcane magic - TXP 4.5
    
global $DB$adi_recent_tab_txp460;

    if(!isset(
$DB)) $DB = new db;

    
$pattern '#'.gTxt('adi_recent_items').'</a></li>#sU';
    
$insert 'adi_recent_tab_menu_markup';
    
$buffer preg_replace_callback($pattern$insert$buffer); // this causes grief in 4.6 (seemingly just for me!)
    
return $buffer;
}

function 
adi_recent_tab_menu_markup($matches) {
// generate markup for adi_recent_tab recent item lists - TXP 4.5
    
global $adi_recent_tab_event_gtxt,$adi_recent_tab_include,$adi_recent_tab_prefs;

    
$out '';
    
$tab_list do_list(adi_recent_tab_pref('adi_recent_tab_list'));
    foreach (
$tab_list as $this_event) {
        
$link_event $this_event;
        if (
$this_event == 'article')
            
$link_event 'list';
        
$out .=
            
'<li><a class="adi_recent_tab_menu_title" href="?event='.$link_event.'">'
            
.gTxt($adi_recent_tab_event_gtxt[$this_event])
            .
'</a></li>'
            
.adi_recent_tab_links($this_event,FALSE);
    }
    return 
$matches[0].$out;
}

function 
adi_recent_tab_list_markup() {
// generate markup for dropdown or tab
// <ul>
//        <li>
//            <h2><a>TAB</a></h2>
//            <a>RECENT LINK 1</a>
//            <a>RECENT LINK 2</a> etc
//        </li>
    
global $adi_recent_tab_event_gtxt,$adi_recent_tab_include,$adi_recent_tab_prefs;
    
$out = array();
    
$tab_list do_list(adi_recent_tab_pref('adi_recent_tab_list'));
    foreach (
$tab_list as $index => $this_event) {
        
$tab_event $this_event;
        if (
$this_event == 'article')
            
$tab_event 'list';
        
$out[] =
            
tag(
                
tag(
                    
'<a href="?event='.$tab_event.'">'.gTxt($adi_recent_tab_event_gtxt[$this_event]).'</a>'
                    
,'h2'
                
)
                .
adi_recent_tab_links($this_event)
                ,
'li'
            
);
    }
    return 
$out;
}

function 
adi_recent_tab_menu_markup_mega() {
// generate mega menu markup - TXP 4.6
    
echo tag(implode(n,adi_recent_tab_list_markup()),'ul',' id="adi_recent_tab_inject"');
}

function 
adi_recent_tab_db_dump($table='adi_recent_tab') {
// print out contents of database table

    
$result mysql_query("SELECT * FROM {$table}");
    
$fields_num mysql_num_fields($result);
    
$out "<br/><table><tr>";
    
// table headers
    
for ($i 0$i $fields_num$i++) {
        
$field mysql_fetch_field($result);
        
$out .= "<td><b>{$field->name}</b>&nbsp;</td>";
    }
    
$out .= "</tr>";
    
// table rows
    
while ($row mysql_fetch_row($result)) {
        
$out .= "<tr>";
        foreach(
$row as $cell)
            
$out .= "<td>$cell&nbsp;</td>";
        
$out .= "</tr>";
    }
    
$out .= '</table><br/>';
    return 
$out;
}

function 
adi_recent_tab_pref($name,$value=NULL,$private=FALSE) {
// read or set pref
    
global $prefs,$adi_recent_tab_prefs;

    if (
$value === NULL)
        return 
get_pref($name,$adi_recent_tab_prefs[$name]['value']);
    else {
        if (
array_key_exists($name,$adi_recent_tab_prefs))
            
$html $adi_recent_tab_prefs[$name]['input'];
        else
            
$html 'text_input';
        
$res set_pref($name,$value,'adi_recent_tab_admin',2,$html,0,$private);
        
$prefs[$name] = get_pref($name,$adi_recent_tab_prefs[$name]['value'],TRUE);
        return 
$res;
    }
}

function 
adi_recent_tab_pref_inputs($event,$tab=NULL) {
// output preference input fields accoring to options/admin setting
    
global $txp_groups,$adi_recent_tab_prefs,$adi_recent_tab_outlaws,$adi_recent_tab_admin_outlaws,$adi_recent_tab_include,$adi_recent_tab_event_gtxt;

    if (
$tab === NULL) return;

    
$out '';

    foreach (
$adi_recent_tab_prefs as $pref_name => $pref_info) {
        if (
$pref_info['tab'] == $tab) {
            switch (
$pref_info['input']) {
                case 
'yesnoradio':
                    
$out .=
                        
graf(
                            
tag(gTxt($pref_info['label']),'label')
                            .
sp.sp
                            
.tag(radio($pref_name,'0',(adi_recent_tab_pref($pref_name) == '0')).sp.gTxt('no'),'label')
                            .
sp.sp
                            
.tag(radio($pref_name,'1',(adi_recent_tab_pref($pref_name) == '1')).sp.gTxt('yes'),'label')
                            ,
' class="'.$pref_name.'"'
                        
);
                    break;
                case 
'custom':
                    
// admin privs
                    
if ($pref_name == 'adi_recent_tab_admin_privs') {
                        
$priv_out gTxt($pref_info['label']);
                        
$admin_privs do_list(adi_recent_tab_pref('adi_recent_tab_admin_privs'));
                        foreach (
$txp_groups as $index => $group)
                            if (
array_search($index,$adi_recent_tab_admin_outlaws) === FALSE// ignore the outlaws
                                
$priv_out .= tag(sp.sp.checkbox2("adi_recent_tab_admin_privs[$index]",(array_search($index,$admin_privs) !== FALSE),'','adi_recent_tab_admin_privs').sp.gTxt($group),'label');
                        
$out .= graf($priv_out,' class="'.$pref_name.'"');
                    }
                    
// plugin privs
                    
if ($pref_name == 'adi_recent_tab_privs') {
                        
$priv_out gTxt($pref_info['label']);
                        
$plugin_privs do_list(adi_recent_tab_pref('adi_recent_tab_privs'));
                        foreach (
$txp_groups as $index => $group)
                            if (
array_search($index,$adi_recent_tab_outlaws) === FALSE// ignore the outlaws
                                
$priv_out .= tag(sp.sp.checkbox2("adi_recent_tab_privs[$index]",(array_search($index,$plugin_privs) !== FALSE),'','adi_recent_tab_privs').sp.gTxt($group),'label');
                        
$out .= graf($priv_out,' class="'.$pref_name.'"');
                    }
                    
// tab visibility
                    
if ($pref_name == 'adi_recent_tab_list') {
                        
$checkboxes gTxt($pref_info['label']);
                        
$tab_list do_list(adi_recent_tab_pref('adi_recent_tab_list'));
                        foreach (
$adi_recent_tab_include as $tab_name) {
                            
$checked array_search($tab_name,$tab_list) !== FALSE;
                            
$checkboxes .=
                                
tag(
                                    
sp.sp
                                    
.checkbox("adi_recent_tab_list[$tab_name]",TRUE,$checked)
                                    .
sp
                                    
.gTxt($adi_recent_tab_event_gtxt[$tab_name])
                                    ,
'label'
                                
);
                        }
                        
$out .= graf($checkboxes,' class="'.$pref_name.'"');
                    }
                    break;
                default: 
// text_input
                    
$out .=
                        
graf(
                            
tag(gTxt($pref_info['label']),'label')
                            .
sp.sp
                            
.finput('text',$pref_name,stripslashes(adi_recent_tab_pref($pref_name)),$pref_name)
                            ,
' class="'.$pref_name.'"'
                        
);
                    break;
            }
        }
    }

    if (
$out)
        return 
form(
            
tag(
                
tag(gTxt('edit_preferences'),'h2')
                .
$out
                
.fInput('submit','do_something',gTxt('adi_update_prefs'),'smallerbox')
                .
eInput($event)
                .
sInput('update_prefs')
                ,
'div'
                
,'  class="adi_recent_tab_prefs"'
            
)
        );
}

function 
adi_recent_tab_update_prefs($tab=NULL) {
// update prefs
    
global $txp_user,$adi_recent_tab_prefs;

    if (
$tab === NULL)
        return 
FALSE;
    else {
        
$result TRUE;
        foreach (
$adi_recent_tab_prefs as $pref_name => $pref_info) {
            if (
$pref_info['tab'] == $tab) { // tab match?
                
if (array_key_exists($pref_name,$_POST))
                    
$value $_POST[$pref_name];
                else if (
$pref_info['input'] == 'yesnoradio')
                    
$value '0';
                else
                    
$value $pref_info['value'];
                if (
is_array($value)) { // string-ify arrays
                    
$values array_keys($value); // need index values not 1s
                    
if ($pref_name == 'adi_recent_tab_admin_privs') {
                        
$user_priv safe_field('privs','txp_users',"name='".doSlash($txp_user)."'");
                        
$values array_unique(array_merge($values,array(1,$user_priv))); // can't kill off Publisher or self
                    
}
                    
$value implode(',',$values);
                }
                
// some values not allowed to be blank, reset to default
                
if ((!$pref_info['blank']) && (trim($value) == ''))
                        
$value $adi_recent_tab_prefs[$pref_name]['value'];
                
// update pref
                
$private = ($pref_info['tab'] == 'options' FALSE $pref_info['private']); // "options" prefs can't be private
                
$result &= adi_recent_tab_pref($pref_name,$value,$private);
            }
        }
        return 
$result;
    }
}

function 
adi_recent_tab_options($event,$step) {
// plugin options page
    
global $adi_recent_tab_debug,$adi_recent_tab_url,$textarray,$adi_recent_tab_prefs,$adi_recent_tab_include,$adi_recent_tab_event_gtxt,$adi_recent_tab_plugin_status;

    
$message '';

    
// step-tastic
    
if ($step == 'textpack') {
        if (
function_exists('install_textpack')) {
            
$adi_textpack file_get_contents($adi_recent_tab_url['textpack']);
            if (
$adi_textpack) {
                
$result install_textpack($adi_textpack);
                
$message gTxt('textpack_strings_installed', array('{count}' => $result));
                
$textarray load_lang(LANG); // load in new strings
            
}
            else
                
$message = array(gTxt('adi_textpack_fail'),E_ERROR);
        }
    }
    else if (
$step == 'install') {
        
$result adi_recent_tab_install();
        
$result $message gTxt('adi_installed') : $message = array(gTxt('adi_install_fail'),E_ERROR);
    }
    else if (
$step == 'uninstall') {
        
$result adi_recent_tab_uninstall();
        
$result $message gTxt('adi_uninstalled') : $message = array(gTxt('adi_uninstall_fail'),E_ERROR);
    }
    else if (
$step == 'update_prefs') {
        
$result adi_recent_tab_update_prefs('options');
        
$result $message gTxt('preferences_saved') : $message = array(gTxt('adi_pref_update_fail'),E_ERROR);
    }

    
// generate page
    
pagetop('adi_recent_tab - '.gTxt('plugin_prefs'),$message);

    
// *nstall buttons
    
$install_button =
        
form(
            
fInput('submit','do_something',gTxt('install'),'publish','',"return verify('".gTxt('are_you_sure')."')")
            .
eInput($event).sInput('install')
        );
    
$uninstall_button =
        
form(
            
fInput('submit','do_something',gTxt('adi_uninstall'),'publish','',"return verify('".gTxt('are_you_sure')."')")
            .
eInput($event).sInput('uninstall')
            ,
'margin-top:3em'
        
);
    if (
$adi_recent_tab_plugin_status// proper plugin install, so lifecycle takes care of install/uninstall
        
$install_button $uninstall_button '';

    
$installed adi_recent_tab_installed();

    
// options
    
echo tag(
        
tag('adi_recent_tab '.gTxt('plugin_prefs'),'h2')
        .( 
$installed ?
            
// link to plugin admin tab
            
graf(href(gTxt('adi_recent_items'),'?event=adi_recent_tab'))
            
// prefs
            
.adi_recent_tab_pref_inputs($event,'options')
            
// textpack links
            
.graf(href(gTxt('install_textpack'),'?event='.$event.a.'step=textpack'),' style="margin-top:3em"')
            .
graf(href(gTxt('adi_textpack_online'),$adi_recent_tab_url['textpack_download']))
            .
graf(href(gTxt('adi_textpack_feedback'),$adi_recent_tab_url['textpack_feedback']))
            .
$uninstall_button
            
$install_button
        
)
        ,
'div'
        
,' style="text-align:center; margin-bottom:3em"'
    
);

    if (
$adi_recent_tab_debug) {
        echo 
'<b>$adi_textpack ('.$adi_recent_tab_url['textpack'].'):</b>';
        
$adi_textpack file_get_contents($adi_recent_tab_url['textpack']);
        
dmp($adi_textpack);
    }
}