<?php

# PLUGIN PREVIEW BY TEXTPATTERN.INFO


/*
    adi_form_links - Admin-side form links

    Written by Adi Gilbert

    Released under the GNU General Public License

    Version history:
    0.4        - refixes for TXP 4.6
    0.3.1    - fix: cope with default page not being called "default" in 4.6 (thanks jpdupont)
    0.3        - fixes: to back up the wild claim made about TXP 4.6 in version 0.2
            - code tidy up
    0.2        - ignore invalid form names
            - blacklist
            - tested on TXP 4.6
    0.1        - initial release (from an idea by Edoardo @wornout & thoroughly tested by Uli)

*/

global $event,$step,$adi_form_links_debug;

if (@
txpinterface == 'admin') {

    
$adi_form_links_debug 0;

    
adi_form_links_init($event,$step);

}

function 
adi_form_links_init($event,$step) {
    global 
$prefs,$textarray,$adi_form_links_debug,$adi_form_links_url,$adi_form_links_prefs,$adi_form_links_blacklist,$adi_form_links_newname,$adi_form_links_txp460;

    
$adi_form_links_txp460 = (version_compare(txp_version,'4.6-dev','>='));

    
$adi_form_links_blacklist[] = 'smd_wrap,transform';
//     $adi_form_links_blacklist[] = 'another_plugin,another_attribute';

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

    
// plugin lifecycle
    
register_callback('adi_form_links_lifecycle','plugin_lifecycle.adi_form_links');

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

    
// Textpack
    
$adi_form_links_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_form_links',
    );
    if (
strpos($prefs['plugin_cache_dir'],'adi') !== FALSE// use Adi's local version
        
$adi_form_links_url['textpack'] = $prefs['plugin_cache_dir'].'/adi_textpack.txt';

# --- BEGIN PLUGIN TEXTPACK ---
    
$adi_form_links_gtxt = array(
        
'adi_edit_form' => 'Edit form',
        
'adi_forms_referenced' => 'Forms referenced',
        
'adi_forms_used' => 'Forms used',
        
'adi_link_list' => 'Link list',
        
'adi_list_format' => 'List format',
        
'adi_none_found' => 'None found',
        
'adi_pref_update_fail' => 'Preference update failed',
        
'adi_textpack_fail' => 'Textpack installation failed',
        
'adi_textpack_feedback' => 'Textpack feedback',
        
'adi_textpack_online' => 'Textpack also available online',
        
'adi_update_prefs' => 'Update preferences',
    );
# --- END PLUGIN TEXTPACK ---

    // update $textarray
    
$textarray += $adi_form_links_gtxt;

    
// preferences & defaults
    
$adi_form_links_prefs = array(
        
'adi_form_links_type'        => array('value' => 'list''input' => 'radio'), // 'list' or 'popup'
    
);
    foreach (
$adi_form_links_prefs as $adi_form_links_pref => $this_pref) {
        
$get_value get_pref($adi_form_links_pref,'?'); // returns '?' if not set (but beware of cacheing)
        
if ($get_value != '?')
            
$adi_form_links_prefs[$adi_form_links_pref]['value'] = $get_value;
    }

    
// some action
    
if (($event == "page") || ($event == 'form')) { // 'ere we go

        // inject markup
        
if ($adi_form_links_txp460)
            
register_callback('adi_form_links_markup_46','admin_side','footer'); // markup in the footer, shifted by jQuery
        
else {
            
// callbacks - inject markup into Pages/Forms tab
            
register_callback('adi_form_links_list','page','',1);
            
register_callback('adi_form_links_list','form','',1);
        }

        
// script
        
register_callback('adi_form_links_script','admin_side','head_end');

        
// new form link clicked in TXP 4.6?
        
$adi_form_links_newname gps('adi_form_links_newname');
        if (
$adi_form_links_newname)
            
register_callback('adi_form_links_script2','admin_side','head_end');
        if (
$adi_form_links_debug) {
            echo 
'Event='.$event.',Step='.$step.br.br;
            echo 
'$_GET=';
            
dmp($_GET);
            echo 
'$_POST=';
            
dmp($_POST);
        }

        
// style
        
register_callback('adi_form_links_style','admin_side','head_end');
    }
}

function 
adi_form_links_style() {
// practical & stylish
    
echo
        
'<style type="text/css">
            #adi_form_links { margin-top:1em }
            #adi_form_links label { width:auto; float:left; margin:0 }
            #adi_form_links select { float:left; margin:0 }
            #adi_form_links input.smallerbox { margin:0 0 0 0.5em }
            #adi_form_links .adi_form_links_disabled { color:#777 } /* explicitly grey out disabled options (for IE6/7) - still no good for iOS Safari NOW REDUNDANT? */
            #adi_form_links p { margin:0 }
            #adi_form_links ul { list-style:none; margin:0.5em 0 0; padding:0 0 1em }
            #adi_form_links li { margin:0; padding:0 }
            #adi_form_links li.adi_form_links_new a,
            #adi_form_links option.adi_form_links_new { color:#777 }
            /* TXP 4.6 */
            @media (max-width: 47em) {
                #adi_form_links label { float:none; display:block }
                #adi_form_links select { float:none; margin:0.5em 0 1em }
                #adi_form_links input.smallerbox { display:block; margin:0 }
            }
        </style>'
;
}

function 
adi_form_links_options($event,$step) {
// plugin options page
    
global $adi_form_links_debug,$adi_form_links_url,$textarray,$adi_form_links_prefs;

    
$message '';

    
// step-tastic
    
if ($step == 'textpack') {
        if (
function_exists('install_textpack')) {
            
$adi_textpack file_get_contents($adi_form_links_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 gTxt('adi_textpack_fail');
        }
    }
    if (
$step == 'update_prefs') {
        
$result adi_form_links_update_prefs();
        
$result $message gTxt('preferences_saved') : $message gTxt('adi_pref_update_fail');
    }

    
// generate page
    
if (!empty($message))
        
$message '<strong>'.$message.'</strong>';

    
pagetop('adi_form_links '.gTxt('plugin_prefs'),$message);

    
// options
    
echo tag(
        
tag('adi_form_links '.gTxt('plugin_prefs'),'h2')
         
// preferences
           
.form(
            
tag(gTxt('edit_preferences'),'h3')
            .
graf(
                
tag(gTxt('adi_list_format'),'label',' for="adi_form_links_type"')
                .
sp.sp
                
.tag(
                    
radio('adi_form_links_type','list',($adi_form_links_prefs['adi_form_links_type']['value'] == 'list'))
                    .
sp
                    
.gTxt('adi_link_list')
                    ,
'label'
                
)
                .
sp.sp
                
.tag(
                    
radio('adi_form_links_type','popup',($adi_form_links_prefs['adi_form_links_type']['value'] == 'popup'))
                    .
sp
                    
.gTxt('tag_popup')
                    ,
'label'
                
)
            )
            .
graf(fInput("submit","do_something",gTxt('adi_update_prefs'),"smallerbox"))
            .
eInput($event)
            .
sInput("update_prefs")
        )
        
// textpack links
        
.graf(href(gTxt('install_textpack'),'?event='.$event.'&amp;step=textpack'),' style="margin-top:3em"')
        .
graf(href(gTxt('adi_textpack_online'),$adi_form_links_url['textpack_download']))
        .
graf(href(gTxt('adi_textpack_feedback'),$adi_form_links_url['textpack_feedback']))
        ,
'div'
        
,' style="text-align:center; margin-bottom:3em"'
    
);

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

}

function 
adi_form_links_lifecycle($event,$step) {
// from cradle to grave
// $event:    "plugin_lifecycle.adi_form_links"
// $step:    "installed", "enabled", disabled", "deleted"
    
global $adi_form_links_debug,$adi_form_links_prefs;

    
$result '?';
    if (
$step == 'deleted') {
        
// delete preferences
        
$res TRUE;
        foreach (
$adi_form_links_prefs as $this_pref => $value)
            
$res $res && safe_delete('txp_prefs',"name = '$this_pref'",$adi_form_links_debug);
        
$result $res;
    }
    if (
$adi_form_links_debug)
        echo 
"Event=$event Step=$step Result=$result";
}

function 
adi_form_links_update_prefs() {
// trawl $_POST & update adi_form_links preferences
    
global $adi_form_links_prefs;

    
$per_user_prefs TRUE;

    
$res TRUE;
    foreach (
$adi_form_links_prefs as $adi_form_links_pref => $this_pref) {
        if (
array_key_exists($adi_form_links_pref,$_POST))
            
$new_value $_POST[$adi_form_links_pref];
        else
            
$new_value '';
        
$res $res && set_pref($adi_form_links_pref,$new_value,'adi_form_links',2,$adi_form_links_prefs[$adi_form_links_pref]['input'],0,$per_user_prefs);
        
$adi_form_links_prefs[$adi_form_links_pref]['value'] = $new_value;
    }
    return 
$res;
}

function 
adi_form_links_forms($name) {
// find the forms & generate the markup
    
global $event,$step,$adi_form_links_debug,$adi_form_links_prefs,$adi_form_links_blacklist,$adi_form_links_txp460;

    
$debug '';
    if (
$adi_form_links_debug$debug.= "FORM NAME:".br."supplied=$name";

    if (
$event == 'page') {
        
/*                            $step        $name        $newname
            Initial page tab visit:    -            -            -            (the "default" page is the one linked to section 'default' - which may not be called 'default' in 4.6)
            Edit page:                -            abc            -
            Save page:                page_save    abc            -
            Create page:            page_new    -            -
            Save new page:            page_save    -            abc
            Delete page:            page_delete    abc            -
            Copy/Duplicate page*:    page_save    abc            xyz            (4.6: $newname contains old name if user doesn't enter new one, even though name field contains "abc_copy")
                *with/without modifications on the way
            Rename page:                                                (there is no rename page functionality)
        */
        
if (empty($step) && empty($name)) // initial page tab visit
            
$name safe_field('page','txp_section',"name='default'"); // get $name from page assigned to section "default"
        
if ($step == 'page_new')
            return 
''// otherwise it'll list default's form
        
$newname gps('newname');
        if (
$step == 'page_save') { // save, add, copy or duplicate page
            
if (empty($name)) // add new page
                
$name gps('newname');
            if (
$newname// 4.6: duplicate page, need to retrieve new oage (user may have modified it before hitting duplicate)
                
$name gps('newname');
        }
        if (
$step == 'page_delete'// page delete, so default to default
            
$name safe_field('page','txp_section',"name='default'"); // get $name from page assigned to section "default"
        // retrieve page contents from DB
        
$row safe_row('user_html','txp_page'," name='".$name."'");
        
$data $row['user_html'];
    }
    else if (
$event == 'form') {
        
/*                            $step            $name        $oldname (4.5)    $newname (4.6)
            Initial form tab visit:    -                -            -                -                (== default)
            Edit form:                form_edit        abc            -                -
            Save form:                form_save        abc            abc                abc
            Create form:            form_create        -            -                -
            Save new form:            form_save        abc*        -                abc                (* 4.6: $name empty)
            Delete form:            form_multi_edit    -            -                -
            Rename form*:            form_save        xyc*        abc                xyz                (* 4.6: $name contains old name)
                *with/without modifications on the way
        */
        
if (empty($step) && empty($name)) // initial form tab visit
            
$name 'default';
        if (
$step == 'form_multi_edit'// form delete, so default to default
            
$name 'default';
        
$newname gps('newname');
        if (
$newname// TXP 4.6 - save new or rename
            
$name $newname;
        
// retrieve form contents from DB
        
$row safe_row('Form','txp_form'," name='".$name."'");
        if (
$row)
            
$data $row['Form'];
        else
            
$data '';
    }
    if (
$adi_form_links_debug$debug.= ", deduced=$name".br;

    
// get all tags from current page/form
    
$all_tags adi_form_links_parse($data);

    
// sort out wheat from chaff
    
$forms = array();
    
$debug .= 'BLACKLIST:'.br;
    
$debug .= implode(br,$adi_form_links_blacklist);
    
$debug .= br.'TAGS, ATTS & VALUES (** is a pass):'.br;
    foreach (
$all_tags as $taginfo) {
        
$atts adi_form_links_splat($taginfo['atts']); // get array of atts & values
        
if ($atts)
            foreach (
$atts as $att => $value) {
                
$this_tag = array();
                if (
preg_match("/.*form$/i",$att)) { // * "[something]form" attribute is a good start
                    
$debug .= '*';
                    if (!
preg_match("/[<>]/i",$value)) { // ** no embedded tags is the business
                        
$pattern '/[<>&"\']/';
                        
// officially: anything goes as long as it's a string, and with out <>&"\'
                        // unofficially: Holy Cr@p! (fixed in 4.6)
                        
if (trim($value) && is_string($value) && !preg_match($pattern,$value)) { // check valid name: basic format, but not blanks or single zero
                            
$debug .= '*';
                            
$this_tag['tag'] = $taginfo['tag'];
                            
$this_tag['att'] = $att;
                            
$this_tag['form'] = htmlentities($value);
                            if (
array_search($this_tag['tag'].','.$this_tag['att'],$adi_form_links_blacklist) === FALSE)
                                
$forms[] = $this_tag;
                            else
                                
$debug .= ' (blacklisted) ';
                        }
                        else
                            
$debug .= ' (invalid form name) ';
                    }
                }
                
$debug .= ' [tag:'.$taginfo['tag'].', attr:'.$att.', form name:'.htmlentities($value).']'.br;
            }
        else 
// no attributes
            
$debug .= $taginfo['tag'].br;
    }

    if (!
$adi_form_links_debug$debug '';

    
// generate select list & link list markup
    
$select_list '';
    
$link_list '<ul>';
    foreach (
$forms as $this_tag) {
        
$link_text $this_tag['form'];
        if (
safe_row('name','txp_form'," name='".$this_tag['form']."'",$adi_form_links_debug)) { // existing form
            
$option_class '';
            
$link_list .= '<li>'.elink('form','form_edit','name',$this_tag['form'],$link_text).' ('.$this_tag['tag'].')'.'</li>';
        }
        else { 
// form doesn't exist
            
$option_class ' class="adi_form_links_new"';
            if (
$adi_form_links_txp460// "name" var causes TXP 4.6 to go into form edit mode rather than form create, so jQuery will come into play
                
$link_list .= '<li class="adi_form_links_new">'.elink('form','form_create','adi_form_links_newname',$this_tag['form'],$link_text).' ('.$this_tag['tag'].')'.'</li>';
            else
                
$link_list .= '<li class="adi_form_links_new">'.elink('form','form_create','name',$this_tag['form'],$link_text).' ('.$this_tag['tag'].')'.'</li>';
        }
        
$select_list .= '<option'.$option_class.' value="'.$this_tag['form'].'">'.$this_tag['form'].' ('.$this_tag['tag'].')</option>';
    }
    
$link_list .= '</ul>';

    if (
$forms)
        if (
$adi_form_links_prefs['adi_form_links_type']['value'] == 'list')
            return 
$debug.$link_list;
        else 
// popup
            
return $debug.tag('<option value="">&nbsp;</option>'.$select_list,'select',' id="adi_form_links_forms" name="name"');
    else
        return 
$debug;
}

function 
adi_form_links_parse($thing) {
// get all tags & their attributes
// ripped off (& modified) from publish.php

    
$f '@(</?txp:\w+(?:\s+\w+\s*=\s*(?:"(?:[^"]|"")*"|\'(?:[^\']|\'\')*\'|[^\s\'"/>]+))*\s*/?'.chr(62).')@s';
    
$t '@:(\w+)(.*?)/?.$@s';

    
$parsed preg_split($f$thing, -1PREG_SPLIT_DELIM_CAPTURE);

    
$level  0;
    
$out    = array();
    
$inside '';
    
$istag  FALSE;

    foreach (
$parsed as $chunk)
    {
        if (
$istag)
        {
            if (
$level === 0) {
                
preg_match($t$chunk$tag);

                if (
substr($chunk, -21) === '/')
                { 
# self closing
                    
TRUE// do nothing but keep for reference
                
}
                else
                { 
# opening
                    
$level++;
                }
                
// $tag[1] = the tag, $tag[2] = the attributes
                
$out[] = array('tag' => trim($tag[1]), 'atts' => trim($tag[2]));
                
$out array_merge($out,adi_form_links_parse($tag[2])); // parse tags within tags
            
}
            else
            {
                if (
substr($chunk11) === '/')
                { 
# closing
                    
if (--$level === 0)
                    {
                        
$out array_merge($out,adi_form_links_parse($inside)); // parse contained tags
                        
$inside '';
                    }
                    else
                    {
                        
$inside .= $chunk;
                    }
                }
                elseif (
substr($chunk, -21) !== '/')
                { 
# opening inside open
                    
++$level;
                    
$inside .= $chunk;
                }
                else
                {
                    
$inside .= $chunk;
                }
            }
        }
        else
        {
            if (
$level)
            {
                
$inside .= $chunk;
            }
        }

        
$istag = !$istag;
    }

    return 
$out;
}

function 
adi_form_links_splat($text) {
// get tag attributes
// ripped off (& modified) from txplib_misc.php
    
$atts  = array();

    if (
preg_match_all('@(\w+)\s*=\s*(?:"((?:[^"]|"")*)"|\'((?:[^\']|\'\')*)\'|([^\s\'"/>]+))@s'$text$matchPREG_SET_ORDER))
    {
        foreach (
$match as $m)
        {
            switch (
count($m))
            {
                case 
3:
                    
$val str_replace('""''"'$m[2]);
                    break;
                case 
4:
                    
$val str_replace("''""'"$m[3]);
                    break;
                case 
5:
                    
$val $m[4];
                    break;
            }

            
$atts[strtolower($m[1])] = $val;
        }

    }

    return 
$atts;
}

function 
adi_form_links_list() {
// arcane magic that gets adi_form_links's list into standard TXP tabs
    
ob_start('adi_form_links_inject');
}

function 
adi_form_links_inject($buffer) {
// another bit of the magic that gets adi_form_links's section popup into standard TXP tabs
    
global $DB,$event;

    if(!isset(
$DB)) $DB = new db;
    if (
$event == 'page')
        
$pattern '#id="page_form".*</form>#sU';
    else if (
$event == 'form')
        
$pattern '#id="form_form".*</form>#sU';
    else
        return 
'';
    
$insert 'adi_form_links_markup';
    
$buffer preg_replace_callback($pattern$insert$buffer);
    return 
$buffer;
}

function 
adi_form_links_markup($matches) {
// generate markup
    
global $adi_form_links_prefs;

    
$name gps('name');

    
$forms_found adi_form_links_forms($name);

    if (
$forms_found)
        if (
$adi_form_links_prefs['adi_form_links_type']['value'] == 'list'// link list
            
$markup graf(strong(gTxt('adi_forms_referenced'))).$forms_found;
        else 
// popup
            
$markup =
                
form(
                    
tag(
                        
tag(strong(gTxt('adi_forms_referenced')),'label',' for="adi_form_links_forms"')
                        .
$forms_found
                        
.fInput("submit","edit_form",gTxt('adi_edit_form'),"smallerbox")
                        .
eInput("form")
                        .
sInput("form_edit")
                    ,
'p')
                );
    else 
// none found
        
$markup strong(gTxt('adi_forms_referenced')).br.gTxt('adi_none_found');

    return 
$matches[0// the admin page chunk, plus:
        
.tag(
            
$markup
            
,'div'
            
,' id="adi_form_links"'
        
);
}

function 
adi_form_links_markup_46($matches) {
// generate markup
    
global $adi_form_links_prefs;

    
$name gps('name');

    
$forms_found adi_form_links_forms($name);

    if (
$forms_found)
        if (
$adi_form_links_prefs['adi_form_links_type']['value'] == 'list'// link list
            
$markup graf(strong(gTxt('adi_forms_referenced'))).$forms_found;
        else 
// popup
            
$markup =
                
form(
                    
tag(
                        
tag(strong(gTxt('adi_forms_referenced')),'label',' for="adi_form_links_forms"')
                        .
br
                        
.$forms_found
                        
.fInput("submit","edit_form",gTxt('adi_edit_form'),"smallerbox")
                        .
eInput("form")
                        .
sInput("form_edit")
                    ,
'p')
                );
    else 
// none found
        
$markup strong(gTxt('adi_forms_referenced')).br.gTxt('adi_none_found');

    echo 
tag(
        
$markup
        
,'div'
        
,' id="adi_form_links"'
    
);
}

function 
adi_form_links_script() {
// jQuery-ism
    
global $adi_form_links_debug,$adi_form_links_newname;

    
// markup shifty
    
echo <<<END_SCRIPT
<script type="text/javascript">
    $(function() {
        // adi_form_links
        $("div#adi_form_links").appendTo($("#main_content")); // shift form links markup from footer
    });
</script>
END_SCRIPT;

}


function 
adi_form_links_script2() {
// jQuery-ism
    
global $adi_form_links_debug,$adi_form_links_newname;

    
// new form name field inject for TXP 4.6
    
if ($adi_form_links_debug) echo "adi_form_links_newname=$adi_form_links_newname".n;

    if (
$adi_form_links_newname)
        echo <<<END_SCRIPT
<script type="text/javascript">
    // adi_form_links
       $().ready(function() {
           console.log("
$adi_form_links_newname");
        $("input#new_form").val("
$adi_form_links_newname");
    });
</script>
END_SCRIPT;

}