<?php

/*
** Fishlib - a collection of utilities for db-driven applications in PHP
** Copyright (C) 2002  LTWD, LLC DBA The Madfish Group
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

require_once('fishargs.class.php');
require_once(
'fishutil.class.php');
require_once(
'fisherror.class.php');

class 
FishTable
{
    function 
form()
    {
        static 
$_defaults = array(
            
'class' => NULL
            
'order_field' => NULL
            
'pretty_tablename' => NULL
            
'classfile' => NULL
            
'header' => 'Table Manager'
            
'idfields' => NULL
        
);
        static 
$_simple = array('class','order_field','pretty_tablename');
        
$args func_get_args();
        
$params FishArgs::parse_arguments($args$_simple$_defaults);
        unset(
$params['_defaults']);
        unset(
$params['_simple']);
        
extract($params);

        if (empty(
$class))
        {
            print 
"<li>{__CLASS__}::{__FUNCTION__}: No class name supplied\n";
            return 
FALSE;
        }
        if (!
class_exists($class))
        {
            if (empty(
$classfile))
            {
                print 
"<li>{__CLASS__}::{__FUNCTION__}: Class '$class' is not defined and no class file name supplied\n";
                return 
FALSE;
            }
            require_once(
$classfile);
        }

// this file wants these vars: $class
// it will also accept $order_field (for sorting) and $pretty_tablename (for the header on the first screen)
// it also needs you to include the relevant classfile(s)

        
$vh = new $class;
        
$vh->dbh();
        
$button_text 'Search';
        
$submit FishUtil::array_key_value($_REQUEST'submit');
        
$rows = array();
        if (empty(
$header))
            
$header 'Table Manager';
        if (empty(
$pretty_tablename))
            
$pretty_tablename ucfirst($vh->table);
        
$header .= ": $pretty_tablename";

        switch (
$submit)
        {
            case 
'display':
                
$vh->build($_REQUEST);
                
$vh->fetch_from_db();
                
$button_text 'Save Changes';
                
$header .= ': Edit Record';
                break;

            case 
'new':
                
$button_text 'Save New Record';
                
$header .= ': Create New Record';
                break;

            case 
'Save Changes':
            case 
'Save New Record':
                
$vh->build($_POST);
                
$vh->write_to_db();
                unset(
$vh);
                
$vh = new $class;
                
$vh->dbh();
                
$header .= ': Record Saved';
                break;

            case 
'Search':
                
$header .= ': Search Results';
                
$vh->build($_POST);
                
$wheres = array();
                
$bind = array();
                
$not_numeric array_diff($vh->fields$vh->numeric_fields);
                foreach (
$not_numeric as $f)
                {
                    
$v $vh->$f;
                    if (
$v !== NULL && $v !== '')
                    {
                        
$wheres[] = " lower($f::text) like ? ";
                        
$bind[] = strtolower("%{$v}%");
                    }
                }
                foreach (
$vh->numeric_fields as $f)
                {
                    
$v $vh->$f;
                    if (
$v !== NULL && $v !== '')
                    {
                        
$wheres[] = " $f = ? ";
                        
$bind[] = $v;
                    }
                }
                
$query $vh->fetch_simple_query();
                if (
count($wheres) > 0)
                {
                    
$query .= ' where '.implode(' and '$wheres);
                }

                if (!empty(
$order_field))
                    
$query .= "order by $order_field";

                
$rows $vh->dbh->getAll($query$bind);
                break;

            case 
'delete':
            case 
'Delete This Record':
                
$vh->build($_REQUEST);
                
$vh->delete_from_db();
                unset(
$vh);
                
$vh = new $class;
                
$vh->dbh();
                
$header .= ': Record Deleted';
                break;
        }

        
$info $vh->tableinfo();
        print <<<EOT

<h2>
{$header}</h2>
 <a href="javascript:history.go(-1)">Go Back</a> &nbsp; &nbsp; &bull; &nbsp;
 <a href="
{$_SERVER['PHP_SELF']}">Start Over</a> &nbsp; &bull; &nbsp;
 <a href="
{$_SERVER['PHP_SELF']}?submit=new">Create New Record</a><br><br>

EOT;

        
$i 0;
        
$maxcol 5;
        foreach (
$rows as $row)
        {
            if (
$i == 0)
            {
                
$maxcol min($maxcolcount($row));
                print 
"<table>\n";
                
$col 0;
                foreach (
$row as $f => $v)
                {
                    if (
$col $maxcol == 0)
                    {
                        if (
$col 0)
                        {
                            print 
"  <td align=left valign=top>&nbsp;</td>\n";
                            print 
" </tr>\n";
                        }
                        print 
" <tr>\n";
                        print 
"  <td align=left valign=top>&nbsp;</td>\n";
                    }
                    
$col++;
                    
$fl ucwords(str_replace('_'' '$f));
                    print 
" <td align=left valign=top><b>$fl</b></td>\n";
                }
                if (
$col 0)
                {
                    print 
"  <td align=left valign=top>&nbsp;</td>\n";
                    print 
" </tr>\n";
                }
            }
            
$idurls = array();
            if (empty(
$idfields))
                
$idfields $vh->idfields;
            foreach (
$idfields as $f)
            {
                
$v rawurlencode($row[$f]);
                
$idurls[] = "$f=$v";
            }
            
$therest implode('&'$idurls);
            
$here $_SERVER['SCRIPT_NAME'];
            
$url "{$here}?submit=display&{$therest}";
            
$durl "{$here}?submit=delete&{$therest}";
            
$col 0;
            foreach (
$row as $f => $v)
            {
                if (
strpos($f'_dt') !== FALSE)
                    
$v preg_replace('/\..*/'''$v);
                if (
$col $maxcol == 0)
                {
                    if (
$col 0)
                    {
                        if (
$col == $maxcol)
                            print 
"  <td align=left valign=top><a href='$durl'>Delete</a></td>\n";
                        else
                            print 
"<td>&nbsp;</td>";
                        print 
" </tr>\n";
                    }
                    print 
" <tr>\n";
                    if (
$col == 0)
                        print 
"  <td align=left valign=top><a href='$url'>Edit</a></td>\n";
                    else
                        print 
"<td>&nbsp;</td>";
                }
                
$col++;
                print 
"  <td align=left valign=top>$v</td>\n";
            }
            if (
$col 0)
            {
                if (
$col == $maxcol)
                    print 
"  <td align=left valign=top><a href='$durl'>Delete</a></td>\n";
                else
                    print 
"<td>&nbsp;</td>";
                print 
" </tr>\n";
            }
            if (
$col $maxcol)
            {
                print 
"<tr><td></td><td colspan=$maxcol><hr></td><td></td></tr>\n";
            }
            
$i++;
        }
        if (
$i 0)
        {
            print 
"</table>\n";
        }
        elseif (!
strcmp($submit,'Search'))
        {
            print 
'<span>No Matches Found<br></span>';
        }

        print <<<EOT

<hr width="60%" align="left">
<h3>Search</h3>
<form action="
{$_SERVER['PHP_SELF']}" method="POST">
<table border=0 cellpadding=6 cellspacing=0>

EOT;
        foreach (
$info['order'] as $f => $i)
        {
            
$ucf ucfirst($f);
            print <<<EOT

 <tr>
  <td><b>
{$ucf}</b></td><td>

EOT;
            if (
in_array($f,$vh->index_fields()) and ($submit == 'display'))
            {
                print <<<EOT
        {$vh->$f}
        <input type="hidden" name="$f" value="
{$vh->$f}">

EOT;
            }
            elseif (
in_array($f,$vh->index_fields()) and ($submit == 'new'))
            {
                print 
'<i>(assigned by db)</i>';
            }
            else
            {
                print <<<EOT
  <input type="text" name="$f" value="{$vh->$f}">

EOT;
            }

            print <<<EOT
  </td>
 </tr>

EOT;
        }
        print <<<EOT
 <tr>
  <td colspan="2" align="right">
   <input type="submit" name="submit" value="
{$button_text}">
  </td>
 </tr>

EOT;
        if (
$button_text === 'Save Changes')
        {
            print <<<EOT
 <tr>
  <td colspan="2" align="left">
   <input type="submit" name="submit" value="Delete This Record">
  </td>
 </tr>

EOT;
        }
        print <<<EOT
</table>
</form>

EOT;
    }

    function 
makeclass()
    {
        static 
$params = array(
            array(
'name'=>'parent','prompt'=>'parent class','required'=>TRUE)
            , array(
'name'=>'table','prompt'=>'table name','required'=>TRUE)
            , array(
'name'=>'what','prompt'=>'what is it?','required'=>FALSE)
            , array(
'name'=>'class','prompt'=>'class name','required'=>FALSE)
            , array(
'name'=>'history','prompt'=>'use history?[y/n]','required'=>FALSE)
            , array(
'name'=>'file','prompt'=>'output file','required'=>FALSE)
        );
        global 
$argc;
        global 
$argv;

        foreach (
$params as $j => $row)
        {
            
$i $j 1;
            if (empty(
$row))
                continue;
            if (isset(
$argv[$i]))
            {
                $
$row['name'] = $argv[$i];
            }
            else
            {
                echo 
$row['prompt'], ' : ';
                $
$row['name'] = trim(fgets(STDIN1024));
                if (empty($
$row['name']) && $row['required'])
                    exit;
            }
        }
        
$parent_file strtolower($parent.'.class.php');
        require_once(
$parent_file);
        
FishError::set_handler(E_USER_ERRORH_DEBUG);
        
FishError::set_handler(E_ERRORH_DEBUG);
        eval(
'$eh = new '.$parent.';');
        
$eh->dbh();
        
$eh->table $table;
        if (
$eh->is_view())
            
$output FishTable::make_view_class($eh$parent$table$what$class);
        else
            
$output FishTable::make_table_class($eh$parent$table$what$class$history);

        if (!empty(
$file) && $file != 'stdout')
        {
            
$fh fopen($file'w');
            
fwrite($fh$output);
            
fclose($fh);
        }
        else
        {
            print 
$output;
        }
    }

    function 
make_table_class(&$eh$parent$table$what$class$history)
    {
        
$parent_file strtolower($parent.'.class.php');
        
$info $eh->tableinfo();
        
$field_array "'".implode("','"array_keys($info['order']))."'";
        
$field_vars '';
        
$dollar '$';
        if (empty(
$what))
        {
            
$what substr($tablestrlen($eh->prefix));
            
$what preg_replace('/s$/',''$what);
        }
        if (empty(
$class))
        {
            
$class ucfirst($what);
        }
        
$num_fields = array();
        
$num_types = array('int','real','int2','int4','numeric');
        
$date_fields = array();
        
$date_types = array('date','time','timestamp');
        foreach (
$info['order'] as $name => $index)
        {
            
$field_vars .= "\tvar {$dollar}{$name} = NULL;\n";
            
$type $info[$index]['type'];
            
// fputs(STDERR, "type=($type)\n");
            
if (in_array($type$num_types))
                
$num_fields[] = $name;
            elseif (
in_array($type$date_types))
                
$date_fields[] = $name;
            elseif (
$info[$index]['len'] > 0)
                
fputs(STDERR"name=$name index=$index len={$info[$index]['len']} type={$info[$index]['type']} \n");
            
// fputs(STDERR, "name=$name index=$index:\n");
            // foreach ($info[$index] as $fk => $fv) { fputs(STDERR, "\t$fk => $fv\n"); }
        
}
        
$numeric_fields_def '';
        if (
count($num_fields) > 0)
        {
            
$numeric_fields_def "'".implode("','"$num_fields)."'";
        }
        
fputs(STDERR"table=($table) history=($history)\n");
    
        
$idfields $eh->index_fields($table);
        
$idfield_def 'NULL';
        
$sequence_def 'NULL';
        if (
count($idfields) > 0)
        {
            
$idfield_def "array('".implode("','"$idfields)."')";
            if (
count($idfields) == 1)
            {
                
$sequence_def "'{$table}_{$what}_id_seq'";
            }
        }
    
        
$history_vars '';
        if (
strpos(strtolower($history),'y') === 0)
        {
            
$history_vars = <<<EOT

    var 
{$dollar}history = array(
        'table' => '
{$table}_h'
        , 'query' => ', ! as save_dt, ! as save_by '
        , 'bind' => array('now()','current_user')
    );

EOT;
        }

        
$qmark '?';
        
$sq "'";
        
$current_db $eh->dbh->getOne('select current_database()');
        
$output = <<<EOT
<{$qmark}php

// auto-generated class for db: 
{$current_db} table: {$table}

require_once(
{$sq}{$parent_file}{$sq});

class $class extends 
{$parent}
{
    var 
{$dollar}table = {$sq}{$table}{$sq};
    var 
{$dollar}what = {$sq}{$what}{$sq};
    var 
{$dollar}idfields = {$idfield_def};
    var 
{$dollar}sequence = {$sequence_def};

    var 
{$dollar}fields = array({$field_array});

    var 
{$dollar}numeric_fields = array({$numeric_fields_def});

{$history_vars}
{$field_vars}

    function 
{$class}()
    {
        
{$dollar}args = func_get_args();
        
{$dollar}this->constructor({$dollar}args);
    }
}

{$qmark}>

EOT;
        return 
$output;
    }

    function 
make_view_class(&$eh$parent$table$what$class)
    {
        
$info $eh->tableinfo();
        if (empty(
$class))
        {
            if (empty(
$what))
            {
                
$what substr($tablestrlen($eh->prefix));
                
$what preg_replace('/s$/',''$what);
            }
            
$class ucfirst($what);
        }
        
$dollar '$';
        
$field_vars '';
        foreach (
$info['order'] as $name => $index)
        {
            
$field_vars .= "\tvar {$dollar}{$name} = NULL;\n";
        }
        
fputs(STDERR"view=($table)\n");

        
$qmark '?';
        
$sq "'";
        
$parent_file strtolower($parent.'.class.php');
        
$output = <<<EOT
<{$qmark}php

require_once(
{$sq}{$parent_file}{$sq});

class $class extends 
{$parent}
{
    // view atts
{$field_vars}

    function 
{$class}()
    {
        
{$dollar}args = func_get_args();
        
{$dollar}this->constructor({$dollar}args);
    }

    function fetch_simple_query()
    {
        return 
{$sq}select * from $table {$sq};
    }
}

{$qmark}>

EOT;
        return 
$output;
    }
}
?>