forked from extern/egroupware
fixed / added mssql support for egw and fixed some other Windows probs on the way ;-)
- knowledgebase is not working: select distinct is not possible with text-columns - fudforum is not working: is does not use ADOdb and has no own db-layer for mssql - other apps seem to work, everthing needs through testing - incl. our "old" db's
This commit is contained in:
parent
3acc7f3bbe
commit
459a8bd101
929
etemplate/inc/class.soetemplate.inc.php
Normal file
929
etemplate/inc/class.soetemplate.inc.php
Normal file
@ -0,0 +1,929 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - EditableTemplates - Storage Objects *
|
||||
* http://www.egroupware.org *
|
||||
* Written by Ralf Becker <RalfBecker@outdoor-training.de> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*!
|
||||
@class soetemplate
|
||||
@author ralfbecker
|
||||
@abstract Storage Objects: Everything to store and retrive the eTemplates.
|
||||
@discussion eTemplates are stored in the db in table 'phpgw_etemplate' and gets distributed
|
||||
@discussion through the file 'etemplates.inc.php' in the setup dir of each app. That file gets
|
||||
@discussion automatically imported in the db, whenever you show a eTemplate of the app. For
|
||||
@discussion performace reasons the timestamp of the file is stored in the db, so 'new'
|
||||
@discussion eTemplates need to have a newer file. The distribution-file is generated with the
|
||||
@discussion function dump, usually by pressing a button in the editor.
|
||||
@discussion writeLangFile writes an lang-file with all Labels, incorporating an existing one.
|
||||
@discussion Beside a name eTemplates use the following keys to find the most suitable template
|
||||
@discussion for an user (in order of precedence):
|
||||
@discussion 1) User-/Group-Id (not yet implemented)
|
||||
@discussion 2) preferd languages of the user (templates for all langs have $lang='')
|
||||
@discussion 3) selected template: verdilak, ... (the default is called '' in the db, not default)
|
||||
@discussion 4) a version-number of the form, eg: '0.9.13.001' (filled up with 0 same size)
|
||||
*/
|
||||
class soetemplate
|
||||
{
|
||||
var $public_functions = array(
|
||||
'init' => True,
|
||||
'empty_cell' => True,
|
||||
'new_cell' => True,
|
||||
'read' => True,
|
||||
'search' => True,
|
||||
'save' => True,
|
||||
'delete' => True,
|
||||
'dump2setup' => True,
|
||||
'import_dump' => True,
|
||||
'writeLangFile' => True
|
||||
);
|
||||
var $debug; // =1 show some debug-messages, = 'app.name' show messages only for eTemplate 'app.name'
|
||||
var $name; // name of the template, e.g. 'infolog.edit'
|
||||
var $template; // '' = default (not 'default')
|
||||
var $lang; // '' if general template else language short, e.g. 'de'
|
||||
var $group; // 0 = not specific else groupId or if < 0 userId
|
||||
var $version; // like 0.9.13.001
|
||||
var $size; // witdh,height,border of table
|
||||
var $style; // embeded CSS style-sheet
|
||||
var $db,$db_name = 'phpgw_etemplate'; // DB name
|
||||
var $db_key_cols = array(
|
||||
'et_name' => 'name',
|
||||
'et_template' => 'template',
|
||||
'et_lang' => 'lang',
|
||||
'et_group' => 'group',
|
||||
'et_version' => 'version'
|
||||
);
|
||||
var $db_data_cols = array(
|
||||
'et_data' => 'data',
|
||||
'et_size' => 'size',
|
||||
'et_style' => 'style',
|
||||
'et_modified' => 'modified'
|
||||
);
|
||||
var $db_cols;
|
||||
|
||||
/*!
|
||||
@function soetemplate
|
||||
@abstract constructor of the class
|
||||
@syntax soetemplate($name='',$template='',$lang='',$group=0,$version='',$rows=2,$cols=2)
|
||||
@param as read
|
||||
*/
|
||||
function soetemplate($name='',$template='',$lang='',$group=0,$version='',$rows=2,$cols=2)
|
||||
{
|
||||
$this->db = $GLOBALS['phpgw']->db;
|
||||
$this->db_cols = $this->db_key_cols + $this->db_data_cols;
|
||||
|
||||
if (empty($name))
|
||||
{
|
||||
$this->init($name,$template,$lang,$group,$version,$rows,$cols);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->read($name,$template,$lang,$group,$version,$rows,$cols);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function num2chrs
|
||||
@abstract generates column-names from index: 'A', 'B', ..., 'AA', 'AB', ..., 'ZZ' (not more!)
|
||||
@syntax num2chrs($num)
|
||||
@param $num index to generate name from 1 => 'A'
|
||||
@result the name
|
||||
*/
|
||||
function num2chrs($num)
|
||||
{
|
||||
$min = ord('A');
|
||||
$max = ord('Z') - $min + 1;
|
||||
if ($num >= $max)
|
||||
{
|
||||
$chrs = chr(($num / $max) + $min - 1);
|
||||
}
|
||||
$chrs .= chr(($num % $max) + $min);
|
||||
|
||||
return $chrs;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function empty_cell
|
||||
@abstracts constructor for a new / empty cell (nothing fancy so far)
|
||||
@syntax empty_cell()
|
||||
@result the cell
|
||||
*/
|
||||
function empty_cell($type='label',$name='')
|
||||
{
|
||||
return array(
|
||||
'type' => $type,
|
||||
'name' => $name,
|
||||
);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function new_cell
|
||||
@abstract constructs a new cell in a give row or the last row, not existing rows will be created
|
||||
@syntax new_cell( $row=False )
|
||||
@param int $row row-number starting with 1 (!)
|
||||
@param string $type type of the cell
|
||||
@param string $label label for the cell
|
||||
@param string $name name of the cell (index in the content-array)
|
||||
@param array $attributes other attributes for the cell
|
||||
@returns a reference to the new cell, use $new_cell = &$tpl->new_cell(); (!)
|
||||
*/
|
||||
function &new_cell($row=False,$type='label',$label='',$name='',$attributes=False)
|
||||
{
|
||||
$row = $row >= 0 ? intval($row) : 0;
|
||||
if ($row && !isset($this->data[$row]) || !isset($this->data[1])) // new row ?
|
||||
{
|
||||
if (!$row) $row = 1;
|
||||
|
||||
$this->data[$row] = array();
|
||||
}
|
||||
if (!$row) // use last row
|
||||
{
|
||||
$row = count($this->data);
|
||||
while (!isset($this->data[$row]))
|
||||
{
|
||||
--$row;
|
||||
}
|
||||
}
|
||||
$row = &$this->data[$row];
|
||||
$col = $this->num2chrs(count($row));
|
||||
$cell = &$row[$col];
|
||||
$cell = $this->empty_cell($type,$name);
|
||||
if ($label !== '')
|
||||
{
|
||||
$attributes['label'] = $label;
|
||||
}
|
||||
if (is_array($attributes))
|
||||
{
|
||||
foreach($attributes as $name => $value)
|
||||
{
|
||||
$cell[$name] = $value;
|
||||
}
|
||||
}
|
||||
return $cell;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function set_rows_cols()
|
||||
@abstract initialises rows & cols from the size of the data-array
|
||||
@syntax set_rows_cols()
|
||||
*/
|
||||
function set_rows_cols()
|
||||
{
|
||||
$this->rows = count($this->data) - 1;
|
||||
$this->cols = 0;
|
||||
for($r = 1; $r <= $this->rows; ++$r)
|
||||
{
|
||||
$cols = count($this->data[$r]);
|
||||
if ($this->cols < $cols)
|
||||
{
|
||||
$this->cols = $cols;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function init
|
||||
@abstract initialises all internal data-structures of the eTemplate and sets the keys
|
||||
@syntax init($name='',$template='',$lang='',$group=0,$version='',$rows=1,$cols=1)
|
||||
@param $name name of the eTemplate or array with the keys or all data
|
||||
@param $template,$lang,$group,$version see class
|
||||
@param $rows,$cols initial size of the template
|
||||
*/
|
||||
function init($name='',$template='',$lang='',$group=0,$version='',$rows=1,$cols=1)
|
||||
{
|
||||
reset($this->db_cols);
|
||||
while (list($db_col,$col) = each($this->db_cols))
|
||||
{
|
||||
$this->$col = is_array($name) ? $name[$col] : $$col;
|
||||
}
|
||||
if ($this->template == 'default')
|
||||
{
|
||||
$this->template = '';
|
||||
}
|
||||
if ($this->lang == 'default')
|
||||
{
|
||||
$this->lang = '';
|
||||
}
|
||||
$this->tpls_in_file = is_array($name) ? $name['tpls_in_file'] : 0;
|
||||
|
||||
if (is_array($name) && isset($name['data']))
|
||||
{
|
||||
$this->set_rows_cols();
|
||||
return; // data already set
|
||||
}
|
||||
$this->size = $this->style = '';
|
||||
$this->data = array(0 => array());
|
||||
$this->rows = $rows < 0 ? 1 : $rows;
|
||||
$this->cols = $cols < 0 ? 1 : $cols;
|
||||
for ($row = 1; $row <= $rows; ++$row)
|
||||
{
|
||||
for ($col = 0; $col < $cols; ++$col)
|
||||
{
|
||||
$this->data[$row][$this->num2chrs($col)] = $this->empty_cell();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function read
|
||||
@abstract Reads an eTemplate from the database
|
||||
@syntax read($name,$template='default',$lang='default',$group=0,$version='')
|
||||
@param as discripted with the class, with the following exeptions
|
||||
@param $template as '' loads the prefered template 'default' loads the default one '' in the db
|
||||
@param $lang as '' loads the pref. lang 'default' loads the default one '' in the db
|
||||
@param $group is NOT used / implemented yet
|
||||
@result True if a fitting template is found, else False
|
||||
*/
|
||||
function read($name,$template='default',$lang='default',$group=0,$version='')
|
||||
{
|
||||
$this->init($name,$template,$lang,$group,$version);
|
||||
if ($this->debug == 1 || $this->debug == $this->name)
|
||||
{
|
||||
echo "<p>soetemplate::read('$this->name','$this->template','$this->lang',$this->group,'$this->version')</p>\n";
|
||||
}
|
||||
if (($GLOBALS['phpgw_info']['server']['eTemplate-source'] == 'files' ||
|
||||
$GLOBALS['phpgw_info']['server']['eTemplate-source'] == 'xslt') && $this->readfile())
|
||||
{
|
||||
return True;
|
||||
}
|
||||
if ($this->name)
|
||||
{
|
||||
$this->test_import($this->name); // import updates in setup-dir
|
||||
}
|
||||
$pref_lang = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
|
||||
$pref_templ = $GLOBALS['phpgw_info']['server']['template_set'];
|
||||
|
||||
$sql = "SELECT * FROM $this->db_name WHERE et_name='".$this->db->db_addslashes($this->name)."' AND ";
|
||||
if (is_array($name))
|
||||
{
|
||||
$template = $name['template'];
|
||||
}
|
||||
if ($template == 'default')
|
||||
{
|
||||
$sql .= "(et_template='".$this->db->db_addslashes($pref_templ)."' OR et_template='')";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= "et_template='".$this->db->db_addslashes($this->template)."'";
|
||||
}
|
||||
$sql .= ' AND ';
|
||||
if (is_array($name))
|
||||
{
|
||||
$lang = $name['lang'];
|
||||
}
|
||||
if ($lang == 'default' || $name['lang'] == 'default')
|
||||
{
|
||||
$sql .= "(et_lang='".$this->db->db_addslashes($pref_lang)."' OR et_lang='')";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= "et_lang='".$this->db->db_addslashes($this->lang)."'";
|
||||
}
|
||||
if ($this->version != '')
|
||||
{
|
||||
$sql .= "AND et_version='".$this->db->db_addslashes($this->version)."'";
|
||||
}
|
||||
$sql .= " ORDER BY et_lang DESC,et_template DESC,et_version DESC";
|
||||
|
||||
if ($this->debug == $this->name)
|
||||
{
|
||||
echo "<p>soetemplate::read: sql='$sql'</p>\n";
|
||||
}
|
||||
$this->db->query($sql,__LINE__,__FILE__);
|
||||
if (!$this->db->next_record())
|
||||
{
|
||||
$version = $this->version;
|
||||
return $this->readfile() && (empty($version) || $version == $this->version);
|
||||
}
|
||||
$this->db2obj();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function readfile
|
||||
@abstract Reads an eTemplate from the filesystem, the keys are already set by init in read
|
||||
@syntax readfile()
|
||||
@result True if a template is found, else False
|
||||
*/
|
||||
function readfile()
|
||||
{
|
||||
list($app,$name) = split("\.",$this->name,2);
|
||||
$template = $this->template == '' ? 'default' : $this->template;
|
||||
|
||||
if ($this->lang)
|
||||
{
|
||||
$lang = '.' . $this->lang;
|
||||
}
|
||||
$first_try = $ext = $GLOBALS['phpgw_info']['server']['eTemplate-source'] == 'xslt' ? '.xsl' : '.xet';
|
||||
|
||||
while ((!$lang || !@file_exists($file = PHPGW_SERVER_ROOT . "/$app/templates/$template/$name$lang$ext") &&
|
||||
!@file_exists($file = PHPGW_SERVER_ROOT . "/$app/templates/default/$name$lang$ext")) &&
|
||||
!@file_exists($file = PHPGW_SERVER_ROOT . "/$app/templates/$template/$name$ext") &&
|
||||
!@file_exists($file = PHPGW_SERVER_ROOT . "/$app/templates/default/$name$ext"))
|
||||
{
|
||||
if ($ext == $first_try)
|
||||
{
|
||||
$ext = $ext == '.xet' ? '.xsl' : '.xet';
|
||||
|
||||
if ($this->debug == 1 || $this->name != '' && $this->debug == $this->name)
|
||||
{
|
||||
echo "<p>tried '$file' now trying it with extension '$ext' !!!</p>\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->name == '' || $app == '' || $name == '' || !@file_exists($file) || !($f = @fopen($file,'r')))
|
||||
{
|
||||
if ($this->debug == 1 || $this->name != '' && $this->debug == $this->name)
|
||||
{
|
||||
echo "<p>Can't open template '$this->name' / '$file' !!!</p>\n";
|
||||
}
|
||||
return False;
|
||||
}
|
||||
$xml = fread ($f, filesize ($file));
|
||||
fclose($f);
|
||||
|
||||
if ($ext == '.xsl')
|
||||
{
|
||||
$cell = $this->empty_cell();
|
||||
$cell['type'] = 'xslt';
|
||||
$cell['size'] = $this->name;
|
||||
//$cell['xslt'] = &$xml; xslttemplate class cant use it direct at the moment
|
||||
$cell['name'] = '';
|
||||
$this->data = array(0 => array(),1 => array('A' => &$cell));
|
||||
$this->rows = $this->cols = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_object($this->xul_io))
|
||||
{
|
||||
$this->xul_io = CreateObject('etemplate.xul_io');
|
||||
}
|
||||
$loaded = $this->xul_io->import($this,$xml);
|
||||
|
||||
if (!is_array($loaded))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$this->name = $app . '.' . $name; // if template was copied or app was renamed
|
||||
|
||||
$this->tpls_in_file = count($loaded);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function search
|
||||
@syntax search($name,$template='default',$lang='default',$group=0,$version='')
|
||||
@author ralfbecker
|
||||
@abstract Lists the eTemplates matching the given criteria
|
||||
@param as discripted with the class, with the following exeptions
|
||||
@param $template as '' loads the prefered template 'default' loads the default one '' in the db
|
||||
@param $lang as '' loads the pref. lang 'default' loads the default one '' in the db
|
||||
@param $group is NOT used / implemented yet
|
||||
@result array of arrays with the template-params
|
||||
*/
|
||||
function search($name,$template='default',$lang='default',$group=0,$version='')
|
||||
{
|
||||
if ($this->name)
|
||||
{
|
||||
$this->test_import($this->name); // import updates in setup-dir
|
||||
}
|
||||
$pref_lang = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
|
||||
$pref_templ = $GLOBALS['phpgw_info']['server']['template_set'];
|
||||
|
||||
if (is_array($name))
|
||||
{
|
||||
$template = $name['template'];
|
||||
$lang = $name['lang'];
|
||||
$group = $name['group'];
|
||||
$version = $name['version'];
|
||||
$name = $name['name'];
|
||||
}
|
||||
$sql = "SELECT et_name,et_template,et_lang,et_group,et_version FROM $this->db_name WHERE et_name LIKE '".$this->db->db_addslashes($name)."%'";
|
||||
|
||||
if ($template != '' && $template != 'default')
|
||||
{
|
||||
$sql .= " AND et_template LIKE '".$this->db->db_addslashes($template)."%'";
|
||||
}
|
||||
if ($lang != '' && $lang != 'default')
|
||||
{
|
||||
$sql .= " AND et_lang LIKE '".$this->db->db_addslashes($lang)."%'";
|
||||
}
|
||||
if ($this->version != '')
|
||||
{
|
||||
$sql .= " AND et_version LIKE '".$this->db->db_addslashes($version)."%'";
|
||||
}
|
||||
$sql .= " ORDER BY et_name DESC,et_lang DESC,et_template DESC,et_version DESC";
|
||||
|
||||
$tpl = new soetemplate;
|
||||
$tpl->db->query($sql,__LINE__,__FILE__);
|
||||
$result = array();
|
||||
while ($tpl->db->next_record())
|
||||
{
|
||||
if ($tpl->db->f('et_lang') != '##') // exclude or import-time-stamps
|
||||
{
|
||||
$tpl->db2obj();
|
||||
|
||||
$result[] = $tpl->as_array();
|
||||
}
|
||||
}
|
||||
if ($this->debug)
|
||||
{
|
||||
echo "<p>soetemplate::search('$name') sql='$sql'</p>\n<pre>\n";
|
||||
print_r($result);
|
||||
echo "</pre>\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function db2obj
|
||||
@abstract copies all cols into the obj and unserializes the data-array
|
||||
@syntax db2obj()
|
||||
*/
|
||||
function db2obj()
|
||||
{
|
||||
for (reset($this->db_cols); list($db_col,$name) = each($this->db_cols); )
|
||||
{
|
||||
$this->$name = $this->db->f($db_col);
|
||||
}
|
||||
$this->data = unserialize(stripslashes($this->data));
|
||||
if (!is_array($this->data)) $this->data = array();
|
||||
|
||||
if ($this->name[0] != '.')
|
||||
{
|
||||
reset($this->data); each($this->data);
|
||||
while (list($row,$cols) = each($this->data))
|
||||
{
|
||||
while (list($col,$cell) = each($cols))
|
||||
{
|
||||
if (is_array($cell['type']))
|
||||
{
|
||||
$this->data[$row][$col]['type'] = $cell['type'][0];
|
||||
//echo "corrected in $this->name cell $col$row attribute type<br>\n";
|
||||
}
|
||||
if (is_array($cell['align']))
|
||||
{
|
||||
$this->data[$row][$col]['align'] = $cell['align'][0];
|
||||
//echo "corrected in $this->name cell $col$row attribute align<br>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->set_rows_cols();
|
||||
}
|
||||
|
||||
/*!
|
||||
@function compress_array
|
||||
@syntax compress_array( $arr )
|
||||
@author ralfbecker
|
||||
@abstract to save space in the db all empty values in the array got unset
|
||||
@discussion The never-'' type field ensures a cell does not disapear completely.
|
||||
@discussion Calls it self recursivly for arrays / the rows
|
||||
@param $arr the array to compress
|
||||
@result the compressed array
|
||||
*/
|
||||
function compress_array($arr)
|
||||
{
|
||||
if (!is_array($arr))
|
||||
{
|
||||
return $arr;
|
||||
}
|
||||
while (list($key,$val) = each($arr))
|
||||
{
|
||||
if (is_array($val))
|
||||
{
|
||||
$arr[$key] = $this->compress_array($val);
|
||||
}
|
||||
elseif ($val == '')
|
||||
{
|
||||
unset($arr[$key]);
|
||||
}
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function as_array
|
||||
@abstract returns obj-data as array
|
||||
@syntax as_array($data_too=0)
|
||||
@param $data_too 0 = no data array, 1 = data array too, 2 = serialize data array
|
||||
@result the array
|
||||
*/
|
||||
function as_array($data_too=0)
|
||||
{
|
||||
$arr = array();
|
||||
reset($this->db_cols);
|
||||
while (list($db_col,$col) = each($this->db_cols))
|
||||
{
|
||||
if ($col != 'data' || $data_too)
|
||||
{
|
||||
$arr[$col] = $this->$col;
|
||||
}
|
||||
}
|
||||
if ($data_too == 2)
|
||||
{
|
||||
$arr['data'] = serialize($arr['data']);
|
||||
}
|
||||
if ($this->tpls_in_file) {
|
||||
$arr['tpls_in_file'] = $this->tpls_in_file;
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function save
|
||||
@abstract saves eTemplate-object to db, can be used as saveAs by giving keys as params
|
||||
@syntax save($name='',$template='.',$lang='.',$group='',$version='.')
|
||||
@params keys see class
|
||||
@result the number of affected rows, 1 should be ok, 0 somethings wrong
|
||||
*/
|
||||
function save($name='',$template='.',$lang='.',$group='',$version='.')
|
||||
{
|
||||
if (is_array($name))
|
||||
{
|
||||
$template = $name['template'];
|
||||
$lang = $name['lang'];
|
||||
$group = $name['group'];
|
||||
$version = $name['version'];
|
||||
$name = $name['name'];
|
||||
}
|
||||
if ($name != '')
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
if ($lang != '.')
|
||||
{
|
||||
$this->lang = $lang;
|
||||
}
|
||||
if ($template != '.')
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
if ($group != '')
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
if ($version != '.')
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
if ($this->name == '') // name need to be set !!!
|
||||
{
|
||||
return False;
|
||||
}
|
||||
if ($this->debug > 0 || $this->debug == $this->name)
|
||||
{
|
||||
echo "<p>soetemplate::save('$this->name','$this->template','$this->lang',$this->group,'$this->version')</p>\n";
|
||||
}
|
||||
$this->delete(); // so we have always a new insert
|
||||
|
||||
if ($this->name[0] != '.') // correct up old messed up templates
|
||||
{
|
||||
reset($this->data); each($this->data);
|
||||
while (list($row,$cols) = each($this->data))
|
||||
{
|
||||
while (list($col,$cell) = each($cols))
|
||||
{
|
||||
if (is_array($cell['type'])) {
|
||||
$this->data[$row][$col]['type'] = $cell['type'][0];
|
||||
//echo "corrected in $this->name cell $col$row attribute type<br>\n";
|
||||
}
|
||||
if (is_array($cell['align'])) {
|
||||
$this->data[$row][$col]['align'] = $cell['align'][0];
|
||||
//echo "corrected in $this->name cell $col$row attribute align<br>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->modified)
|
||||
{
|
||||
$this->modified = time();
|
||||
}
|
||||
$data = $this->as_array(1);
|
||||
$data['data'] = serialize($this->compress_array($data['data']));
|
||||
|
||||
$sql = "INSERT INTO $this->db_name (";
|
||||
foreach ($this->db_cols as $db_col => $col)
|
||||
{
|
||||
$sql .= $db_col . ',';
|
||||
$vals .= $db_col == 'et_group' ? intval($data[$col]).',' : "'" . $this->db->db_addslashes($data[$col]) . "',";
|
||||
}
|
||||
$sql[strlen($sql)-1] = ')';
|
||||
$sql .= " VALUES ($vals";
|
||||
$sql[strlen($sql)-1] = ')';
|
||||
|
||||
$this->db->query($sql,__LINE__,__FILE__);
|
||||
|
||||
return $this->db->affected_rows();
|
||||
}
|
||||
|
||||
/*!
|
||||
@function delete
|
||||
@abstract Deletes the eTemplate from the db, object itself is unchanged
|
||||
@syntax delete()
|
||||
@result the number of affected rows, 1 should be ok, 0 somethings wrong
|
||||
*/
|
||||
function delete()
|
||||
{
|
||||
foreach ($this->db_key_cols as $db_col => $col)
|
||||
{
|
||||
$vals .= ($vals ? ' AND ' : '') . $db_col . '=' . ($db_col == 'et_group' ? intval($this->$col) : "'".$this->$col."'");
|
||||
}
|
||||
$this->db->query("DELETE FROM $this->db_name WHERE $vals",__LINE__,__FILE__);
|
||||
|
||||
return $this->db->affected_rows();
|
||||
}
|
||||
|
||||
/*!
|
||||
@function dump2setup
|
||||
@abstract dumps all eTemplates to <app>/setup/etemplates.inc.php for distribution
|
||||
@syntax dump2setup($app)
|
||||
@param $app app- or template-name
|
||||
@result the number of templates dumped as message
|
||||
*/
|
||||
function dump2setup($app)
|
||||
{
|
||||
list($app) = explode('.',$app);
|
||||
|
||||
$this->db->query("SELECT * FROM $this->db_name WHERE et_name LIKE '$app%'");
|
||||
|
||||
$dir = PHPGW_SERVER_ROOT . "/$app/setup";
|
||||
if (!is_writeable($dir))
|
||||
{
|
||||
return lang("Error: webserver is not allowed to write into '%1' !!!",$dir);
|
||||
}
|
||||
$file = "$dir/etemplates.inc.php";
|
||||
if (file_exists($file))
|
||||
{
|
||||
$old_file = "$dir/etemplates.old.inc.php";
|
||||
if (file_exists($old_file))
|
||||
{
|
||||
unlink($old_file);
|
||||
}
|
||||
rename($file,$old_file);
|
||||
}
|
||||
|
||||
if (!($f = fopen($file,'w')))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
fwrite($f,"<?php\n// eTemplates for Application '$app', generated by etemplate.dump() ".date('Y-m-d H:i')."\n\n".
|
||||
'/* $'.'Id$ */'."\n\n");
|
||||
|
||||
for ($n = 0; $this->db->next_record(); ++$n)
|
||||
{
|
||||
$str = '$templ_data[] = array(';
|
||||
for (reset($this->db_cols); list($db_col,$name) = each($this->db_cols); )
|
||||
{
|
||||
$str .= "'$name' => '".$this->db->db_addslashes($this->db->f($db_col))."',";
|
||||
}
|
||||
$str .= ");\n\n";
|
||||
fwrite($f,$str);
|
||||
}
|
||||
fclose($f);
|
||||
|
||||
return lang("%1 eTemplates for Application '%2' dumped to '%3'",$n,$app,$file);
|
||||
}
|
||||
|
||||
function getToTranslateCell($cell,&$to_trans)
|
||||
{
|
||||
$strings = explode('|',$cell['help']);
|
||||
|
||||
if ($cell['type'] != 'image')
|
||||
{
|
||||
$strings = array_merge($strings,explode('|',$cell['label']));
|
||||
}
|
||||
list($extra_row) = explode(',',$cell['size']);
|
||||
if (substr($cell['type'],0,6) == 'select' && !empty($extra_row) && !intval($extra_row))
|
||||
{
|
||||
$strings[] = $extra_row;
|
||||
}
|
||||
if (!empty($cell['blur']))
|
||||
{
|
||||
$strings[] = $cell['blur'];
|
||||
}
|
||||
foreach($strings as $str)
|
||||
{
|
||||
if (strlen($str) > 1 && $str[0] != '@')
|
||||
{
|
||||
$to_trans[trim(strtolower($str))] = $str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function getToTranslate
|
||||
@abstract extracts all texts: labels and helptexts from an eTemplate-object
|
||||
@discussion some extensions use a '|' to squezze multiple texts in a label or help field
|
||||
@syntax getToTranslate()
|
||||
@result array with messages as key AND value
|
||||
*/
|
||||
function getToTranslate()
|
||||
{
|
||||
$to_trans = array();
|
||||
|
||||
reset($this->data); each($this->data); // skip width
|
||||
while (list($row,$cols) = each($this->data))
|
||||
{
|
||||
foreach($cols as $col => $cell)
|
||||
{
|
||||
$this->getToTranslateCell($cell,$to_trans);
|
||||
|
||||
if ($cell['type'] == 'vbox' || $cell['type'] == 'hbox')
|
||||
{
|
||||
for ($n = 1; $n <= $cell['size']; ++$n)
|
||||
{
|
||||
$this->getToTranslateCell($cell[$n],$to_trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $to_trans;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function getToTranslateApp
|
||||
@abstract Read all eTemplates of an app an extracts the texts to an array
|
||||
@syntax getToTranslateApp($app)
|
||||
@param $app name of the app
|
||||
@result the array with texts
|
||||
*/
|
||||
function getToTranslateApp($app)
|
||||
{
|
||||
$to_trans = array();
|
||||
|
||||
$tpls = $this->search($app);
|
||||
|
||||
$tpl = new soetemplate; // to not alter our own data
|
||||
|
||||
while (list(,$keys) = each($tpls))
|
||||
{
|
||||
if (($keys['name'] != $last['name'] || // write only newest version
|
||||
$keys['template'] != $last['template']) &&
|
||||
!strstr($keys['name'],'test'))
|
||||
{
|
||||
$tpl->read($keys);
|
||||
$to_trans += $tpl->getToTranslate();
|
||||
$last = $keys;
|
||||
}
|
||||
}
|
||||
return $to_trans;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function writeLangFile
|
||||
@abstract Write new lang-file using the existing one and all text from the eTemplates
|
||||
@syntax writeLangFile($app,$lang='en',$additional='')
|
||||
@param $app app- or template-name
|
||||
@param $lang language the messages in the template are, defaults to 'en'
|
||||
@param $additional extra texts to translate, if you pass here an array with all messages and
|
||||
@param select-options they get writen too (form is <unique key> => <message>)
|
||||
@result message with number of messages written (total and new)
|
||||
*/
|
||||
function writeLangFile($app,$lang='en',$additional='')
|
||||
{
|
||||
if (!$additional)
|
||||
{
|
||||
$addtional = array();
|
||||
}
|
||||
list($app) = explode('.',$app);
|
||||
|
||||
if (!file_exists(PHPGW_SERVER_ROOT.'/developer_tools/inc/class.solangfile.inc.php'))
|
||||
{
|
||||
$solangfile = CreateObject('etemplate.solangfile');
|
||||
}
|
||||
else
|
||||
{
|
||||
$solangfile = CreateObject('developer_tools.solangfile');
|
||||
}
|
||||
$langarr = $solangfile->load_app($app,$lang);
|
||||
if (!is_array($langarr))
|
||||
{
|
||||
$langarr = array();
|
||||
}
|
||||
$commonarr = $solangfile->load_app('phpgwapi',$lang) + $solangfile->load_app('etemplate',$lang);
|
||||
|
||||
$to_trans = $this->getToTranslateApp($app);
|
||||
if (is_array($additional))
|
||||
{
|
||||
//echo "writeLangFile: additional ="; _debug_array($additional);
|
||||
foreach($additional as $msg)
|
||||
{
|
||||
$to_trans[trim(strtolower($msg))] = $msg;
|
||||
}
|
||||
}
|
||||
unset($to_trans['']);
|
||||
|
||||
for ($new = $n = 0; list($message_id,$content) = each($to_trans); ++$n)
|
||||
{
|
||||
if (!isset($langarr[$message_id]) && !isset($commonarr[$message_id]))
|
||||
{
|
||||
if (@isset($langarr[$content])) // caused by not lowercased-message_id's
|
||||
{
|
||||
unset($langarr[$content]);
|
||||
}
|
||||
$langarr[$message_id] = array(
|
||||
'message_id' => $message_id,
|
||||
'app_name' => $app,
|
||||
'content' => $content
|
||||
);
|
||||
++$new;
|
||||
}
|
||||
}
|
||||
ksort($langarr);
|
||||
|
||||
$dir = PHPGW_SERVER_ROOT . "/$app/setup";
|
||||
if (!is_writeable($dir))
|
||||
{
|
||||
return lang("Error: webserver is not allowed to write into '%1' !!!",$dir);
|
||||
}
|
||||
$file = "$dir/phpgw_$lang.lang";
|
||||
if (file_exists($file))
|
||||
{
|
||||
$old_file = "$dir/phpgw_$lang.old.lang";
|
||||
if (file_exists($old_file))
|
||||
{
|
||||
unlink($old_file);
|
||||
}
|
||||
rename($file,$old_file);
|
||||
}
|
||||
$solangfile->write_file($app,$langarr,$lang);
|
||||
$solangfile->loaddb($app,$lang);
|
||||
|
||||
return lang("%1 (%2 new) Messages writen for Application '%3' and Languages '%4'",$n,$new,$app,$lang);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function import_dump
|
||||
@abstract Imports the dump-file /$app/setup/etempplates.inc.php unconditional (!)
|
||||
@syntax import_dump($app)
|
||||
@param $app app name
|
||||
@result message with number of templates imported
|
||||
*/
|
||||
function import_dump($app)
|
||||
{
|
||||
include($path = PHPGW_SERVER_ROOT."/$app/setup/etemplates.inc.php");
|
||||
$templ = new etemplate($app);
|
||||
|
||||
for ($n = 0; isset($templ_data[$n]); ++$n)
|
||||
{
|
||||
for (reset($this->db_cols); list($db_col,$name) = each($this->db_cols); )
|
||||
{
|
||||
$templ->$name = $templ_data[$n][$name];
|
||||
}
|
||||
$templ->data = unserialize(stripslashes($templ->data));
|
||||
if (!$templ->modified)
|
||||
{
|
||||
$templ->modified = filemtime($path);
|
||||
}
|
||||
$templ->save();
|
||||
}
|
||||
return lang("%1 new eTemplates imported for Application '%2'",$n,$app);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function test_import
|
||||
@abstract test if new template-import necessary for app and does the import
|
||||
@discussion Get called on every read of a eTemplate, caches the result in phpgw_info.
|
||||
@discussion The timestamp of the last import for app gets written into the db.
|
||||
@syntax test_import($app)
|
||||
@param $app app- or template-name
|
||||
*/
|
||||
function test_import($app) // should be done from the setup-App
|
||||
{
|
||||
list($app) = explode('.',$app);
|
||||
|
||||
if (!$app || $GLOBALS['phpgw_info']['etemplate']['import_tested'][$app])
|
||||
{
|
||||
return ''; // ensure test is done only once per call and app
|
||||
}
|
||||
$GLOBALS['phpgw_info']['etemplate']['import_tested'][$app] = True; // need to be done before new ...
|
||||
|
||||
$path = PHPGW_SERVER_ROOT."/$app/setup/etemplates.inc.php";
|
||||
|
||||
if ($time = @filemtime($path))
|
||||
{
|
||||
$templ = new soetemplate(".$app",'','##');
|
||||
if ($templ->lang != '##' || $templ->modified < $time) // need to import
|
||||
{
|
||||
$ret = $this->import_dump($app);
|
||||
$templ->modified = $time;
|
||||
$templ->save(".$app",'','##');
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
};
|
578
infolog/inc/class.soinfolog.inc.php
Normal file
578
infolog/inc/class.soinfolog.inc.php
Normal file
@ -0,0 +1,578 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - InfoLog *
|
||||
* http://www.eGroupWare.org *
|
||||
* Written by Ralf Becker <RalfBecker@outdoor-training.de> *
|
||||
* originaly based on todo written by Joseph Engo <jengo@phpgroupware.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*!
|
||||
@class soinfolog
|
||||
@abstract storage object / db-layer for InfoLog
|
||||
@author Ralf Becker
|
||||
@copyright GPL - GNU General Public License
|
||||
@note all values passed to this class are run either through intval or addslashes to prevent query-insertion
|
||||
and for pgSql 7.3 compatibility
|
||||
*/
|
||||
class soinfolog // DB-Layer
|
||||
{
|
||||
var $db,$db2;
|
||||
var $grants;
|
||||
var $data = array( );
|
||||
var $user;
|
||||
|
||||
/*!
|
||||
@function soinfolog
|
||||
@abstract constructor
|
||||
*/
|
||||
function soinfolog( $info_id = 0)
|
||||
{
|
||||
$this->db = $GLOBALS['phpgw']->db;
|
||||
$this->grants = $GLOBALS['phpgw']->acl->get_grants('infolog');
|
||||
$this->user = $GLOBALS['phpgw_info']['user']['account_id'];
|
||||
|
||||
$this->links = CreateObject('infolog.solink');
|
||||
|
||||
$this->tz_offset = $GLOBALS['phpgw_info']['user']['preferences']['common']['tz_offset'];
|
||||
|
||||
$this->read( $info_id );
|
||||
}
|
||||
|
||||
/*!
|
||||
@function check_access
|
||||
@abstract checks if user has the $required_rights to access $info_id (private access is handled too)
|
||||
@syntax check_access( $info_id,$required_rights )
|
||||
@param $info_id Id of InfoLog entry
|
||||
@param $required_rights PHPGW_ACL_xyz anded together
|
||||
@returns True if access is granted else False
|
||||
*/
|
||||
function check_access( $info_id,$required_rights )
|
||||
{
|
||||
if ($info_id != $this->data['info_id']) // already loaded?
|
||||
{
|
||||
// dont change our own internal data,
|
||||
// dont use new as it changes $phpgw->db
|
||||
$private_info = $this;
|
||||
$info = $private_info->read($info_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$info = $this->data;
|
||||
}
|
||||
if (!$info || !$info_id)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$owner = $info['info_owner'];
|
||||
|
||||
$access_ok = $owner == $this->user || // user has all rights
|
||||
// ACL only on public entrys || $owner granted _PRIVATE
|
||||
(!!($this->grants[$owner] & $required_rights) ||
|
||||
// implicite read-rights for responsible user !!!
|
||||
$info['info_responsible'] == $this->user && $required_rights == PHPGW_ACL_READ) &&
|
||||
($info['info_access'] == 'public' ||
|
||||
!!($this->grants[$owner] & PHPGW_ACL_PRIVATE));
|
||||
|
||||
//echo "<p>check_access(info_id=$info_id (owner=$owner, user=$user),required_rights=$required_rights): access".($access_ok?"Ok":"Denied")."</p>\n";
|
||||
return $access_ok;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function aclFilter
|
||||
@abstract generate sql to be AND'ed into a query to ensure ACL is respected (incl. _PRIVATE)
|
||||
@param $filter: none|all - list all entrys user have rights to see<br>
|
||||
private|own - list only his personal entrys (incl. those he is responsible for !!!)
|
||||
@returns the necesary sql
|
||||
*/
|
||||
function aclFilter($filter = False)
|
||||
{
|
||||
preg_match('/(own|privat|all|none|user)([0-9]*)/',$filter_was=$filter,$vars);
|
||||
$filter = $vars[1];
|
||||
$f_user = intval($vars[2]);
|
||||
|
||||
if (isset($this->acl_filter[$filter.$user]))
|
||||
{
|
||||
return $this->acl_filter[$filter.$user]; // used cached filter if found
|
||||
}
|
||||
if (is_array($this->grants))
|
||||
{
|
||||
foreach($this->grants as $user => $grant)
|
||||
{
|
||||
// echo "<p>grants: user=$user, grant=$grant</p>";
|
||||
if ($grant & (PHPGW_ACL_READ|PHPGW_ACL_EDIT))
|
||||
{
|
||||
$public_user_list[] = $user;
|
||||
}
|
||||
if ($grant & PHPGW_ACL_PRIVATE)
|
||||
{
|
||||
$private_user_list[] = $user;
|
||||
}
|
||||
}
|
||||
if (count($private_user_list))
|
||||
{
|
||||
$has_private_access = 'info_owner IN ('.implode(',',$private_user_list).')';
|
||||
}
|
||||
}
|
||||
$filtermethod = " (info_owner=$this->user"; // user has all rights
|
||||
|
||||
// implicit read-rights for responsible user
|
||||
$filtermethod .= " OR (info_responsible=$this->user AND info_access='public')";
|
||||
|
||||
// private: own entries plus the one user is responsible for
|
||||
if ($filter == 'private' || $filter == 'own')
|
||||
{
|
||||
$filtermethod .= " OR (info_responsible=$this->user OR info_status = 'offer')".
|
||||
" AND (info_access='public'".($has_private_access?" OR $has_private_access":'').')';
|
||||
}
|
||||
else // none --> all entrys user has rights to see
|
||||
{
|
||||
if ($has_private_access)
|
||||
{
|
||||
$filtermethod .= " OR $has_private_access";
|
||||
}
|
||||
if (count($public_user_list))
|
||||
{
|
||||
$filtermethod .= " OR (info_access='public' AND info_owner IN(" . implode(',',$public_user_list) . '))';
|
||||
}
|
||||
}
|
||||
$filtermethod .= ') ';
|
||||
|
||||
if ($filter == 'user' && $f_user > 0)
|
||||
{
|
||||
$filtermethod = " ((info_owner=$f_user AND info_responsible=0 OR info_responsible=$f_user) AND $filtermethod)";
|
||||
}
|
||||
//echo "<p>aclFilter(filter='$filter_was',user='$user') = '$filtermethod', privat_user_list=".print_r($privat_user_list,True).", public_user_list=".print_r($public_user_list,True)."</p>\n";
|
||||
return $this->acl_filter[$filter.$user] = $filtermethod; // cache the filter
|
||||
}
|
||||
|
||||
/*!
|
||||
@function statusFilter
|
||||
@abstract generate sql to filter based on the status of the log-entry
|
||||
@syntax statusFilter($filter = '')
|
||||
@param $filter done = done or billed, open = not ()done or billed), offer = offer
|
||||
@returns the necesary sql
|
||||
*/
|
||||
function statusFilter($filter = '')
|
||||
{
|
||||
preg_match('/(done|open|offer)/',$filter,$vars);
|
||||
$filter = $vars[1];
|
||||
|
||||
switch ($filter)
|
||||
{
|
||||
case 'done': return " AND info_status IN ('done','billed')";
|
||||
case 'open': return " AND NOT (info_status IN ('done','billed'))";
|
||||
case 'offer': return " AND info_status = 'offer'";
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/*!
|
||||
@function dateFilter
|
||||
@abstract generate sql to filter based on the start- and enddate of the log-entry
|
||||
@syntax dateFilter($filter = '')
|
||||
@param $filter upcoming = startdate is in the future<br>
|
||||
today startdate < tomorrow<br>
|
||||
overdue enddate < tomorrow<br>
|
||||
limitYYYY/MM/DD not older or open
|
||||
@returns the necesary sql
|
||||
*/
|
||||
function dateFilter($filter = '')
|
||||
{
|
||||
preg_match('/(upcoming|today|overdue|date)([-\\/.0-9]*)/',$filter,$vars);
|
||||
$filter = $vars[1];
|
||||
|
||||
if (isset($vars[2]) && !empty($vars[2]) && ($date = split('[-/.]',$vars[2])))
|
||||
{
|
||||
$today = mktime(-$this->tz_offset,0,0,intval($date[1]),intval($date[2]),intval($date[0]));
|
||||
$tomorrow = mktime(-$this->tz_offset,0,0,intval($date[1]),intval($date[2])+1,intval($date[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
$now = getdate(time()-60*60*$this->tz_offset);
|
||||
$tomorrow = mktime(-$this->tz_offset,0,0,$now['mon'],$now['mday']+1,$now['year']);
|
||||
}
|
||||
switch ($filter)
|
||||
{
|
||||
case 'upcoming':
|
||||
return " AND info_startdate >= '$tomorrow'";
|
||||
case 'today':
|
||||
return " AND info_startdate < '$tomorrow'";
|
||||
case 'overdue':
|
||||
return " AND (info_enddate != 0 AND info_enddate < '$tomorrow')";
|
||||
case 'date':
|
||||
if (!$today || !$tomorrow)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
return " AND ($today <= info_startdate AND info_startdate < $tomorrow)";
|
||||
case 'limit':
|
||||
return " AND (info_modified >= '$today' OR NOT (info_status IN ('done','billed')))";
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/*!
|
||||
@function init
|
||||
@abstract initialise the internal $this->data to be empty
|
||||
@discussion only non-empty values got initialised
|
||||
*/
|
||||
function init()
|
||||
{
|
||||
$this->data = array(
|
||||
'info_owner' => $this->user,
|
||||
'info_pri' => 'normal'
|
||||
);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function db2data
|
||||
@abstract copy data after a query into $data
|
||||
@syntax db2data(&$data)
|
||||
@param $data array to copy the data
|
||||
@description copy only non-numeric keys
|
||||
*/
|
||||
function db2data(&$data)
|
||||
{
|
||||
$data = array();
|
||||
foreach ($this->db->Record as $key => $val)
|
||||
{
|
||||
if (!is_numeric($key))
|
||||
{
|
||||
$data[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function read
|
||||
@abstract read InfoLog entry $info_id
|
||||
@syntax read( $info_id )
|
||||
@param $info_id id of log-entry
|
||||
@description some cacheing is done to prevent multiple reads of the same entry
|
||||
@returns the entry as array
|
||||
*/
|
||||
function read($info_id) // did _not_ ensure ACL
|
||||
{
|
||||
$info_id = intval($info_id);
|
||||
|
||||
if ($info_id <= 0 || $info_id != $this->data['info_id'] &&
|
||||
(!$this->db->query("select * FROM phpgw_infolog WHERE info_id=$info_id",__LINE__,__FILE__) ||
|
||||
!$this->db->next_record()))
|
||||
{
|
||||
$this->init( );
|
||||
return False;
|
||||
}
|
||||
if ($info_id != $this->data['info_id']) // data yet read in
|
||||
{
|
||||
$this->db2data($this->data);
|
||||
|
||||
$this->db->query("SELECT info_extra_name,info_extra_value FROM phpgw_infolog_extra WHERE info_id=$info_id",__LINE__,__FILE__);
|
||||
while ($this->db->next_record())
|
||||
{
|
||||
$this->data['#'.$this->db->f(0)] = $this->db->f(1);
|
||||
}
|
||||
}
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function delete
|
||||
@abstract delete InfoLog entry $info_id AND the links to it
|
||||
@syntax delete( $info_id )
|
||||
@param int $info_id id of log-entry
|
||||
@param bool $delete_children delete the children, if not set there parent-id to $new_parent
|
||||
@param int new_parent new parent-id to set for subs
|
||||
*/
|
||||
function delete($info_id,$delete_children=True,$new_parent=0) // did _not_ ensure ACL
|
||||
{
|
||||
//echo "<p>soinfolog::delete($info_id,'$delete_children',$new_parent)</p>\n";
|
||||
if (($info_id = intval($info_id)) <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
$this->db->query("DELETE FROM phpgw_infolog WHERE info_id=$info_id",__LINE__,__FILE__);
|
||||
$this->db->query("DELETE FROM phpgw_infolog_extra WHERE info_id=$info_id");
|
||||
$this->links->unlink(0,'infolog',$info_id);
|
||||
|
||||
if ($this->data['info_id'] == $info_id)
|
||||
{
|
||||
$this->init( );
|
||||
}
|
||||
// delete children, if they are owned by the user
|
||||
if ($delete_children)
|
||||
{
|
||||
$db2 = $this->db; // we need an extra result-set
|
||||
$db2->query("SELECT info_id FROM phpgw_infolog WHERE info_id_parent=$info_id AND info_owner=$this->user",__LINE__,__FILE__);
|
||||
while ($db2->next_record())
|
||||
{
|
||||
$this->delete($db2->f(0),$delete_children);
|
||||
}
|
||||
}
|
||||
// set parent_id to $new_parent for all not deleted children
|
||||
$new_parent = intval($new_parent);
|
||||
$this->db->query("UPDATE phpgw_infolog SET info_id_parent=$new_parent WHERE info_id_parent=$info_id",__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function change_delete_owner
|
||||
@abstract changes or deletes entries with a spezified owner (for hook_delete_account)
|
||||
@syntax change_delete_owner( $owner,$new_owner=0 )
|
||||
@param $owner old owner
|
||||
@param $new_owner new owner or 0 if entries should be deleted
|
||||
*/
|
||||
function change_delete_owner($owner,$new_owner=0) // new_owner=0 means delete
|
||||
{
|
||||
$owner = intval($owner);
|
||||
if (!($new_owner = intval($new_owner)))
|
||||
{
|
||||
$db2 = $this->db; // we need an extra result-set
|
||||
$db2->query("SELECT info_id FROM phpgw_infolog WHERE info_owner=$owner",__LINE__,__FILE__);
|
||||
while($db2->next_record())
|
||||
{
|
||||
$this->delete($this->db->f(0),False);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->db->query("UPDATE phpgw_infolog SET info_owner=$new_owner WHERE info_owner=$owner",__LINE__,__FILE__);
|
||||
}
|
||||
$this->db->query("UPDATE phpgw_infolog SET info_responsible=$new_owner WHERE info_responsible=$owner",__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function write
|
||||
@abstract writes the given $values to InfoLog, a new entry gets created if info_id is not set or 0
|
||||
@syntax write( $values )
|
||||
@param $values array with the data of the log-entry
|
||||
@return the info_id
|
||||
*/
|
||||
function write($values) // did _not_ ensure ACL
|
||||
{
|
||||
include(PHPGW_SERVER_ROOT.'/infolog/setup/tables_current.inc.php');
|
||||
$db_cols = $phpgw_baseline['phpgw_infolog']['fd'];
|
||||
unset($phpgw_baseline);
|
||||
|
||||
$info_id = intval($values['info_id']) > 0 ? intval($values['info_id']) : 0;
|
||||
|
||||
foreach($values as $key => $val)
|
||||
{
|
||||
if ($key != 'info_id')
|
||||
{
|
||||
if (!isset($db_cols[$key]))
|
||||
{
|
||||
continue; // not in infolog-table
|
||||
}
|
||||
$this->data[$key] = $val; // update internal data
|
||||
|
||||
switch($db_cols[$key]['type']) // protection against query-insertion
|
||||
{
|
||||
case 'int': case 'auto':
|
||||
$val = intval($val);
|
||||
break;
|
||||
default:
|
||||
$val = "'".$this->db->db_addslashes($val)."'";
|
||||
break;
|
||||
}
|
||||
$cols .= (strlen($cols) ? ',' : '').$key;
|
||||
$vals .= (strlen($vals) ? ',' : '').$val;
|
||||
$query .= (strlen($query) ? ',' : '')."$key=$val";
|
||||
}
|
||||
}
|
||||
if (($this->data['info_id'] = $info_id))
|
||||
{
|
||||
$query = "UPDATE phpgw_infolog SET $query WHERE info_id=$info_id";
|
||||
$this->db->query($query,__LINE__,__FILE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = "INSERT INTO phpgw_infolog ($cols) VALUES ($vals)";
|
||||
$this->db->query($query,__LINE__,__FILE__);
|
||||
$this->data['info_id']=$this->db->get_last_insert_id('phpgw_infolog','info_id');
|
||||
}
|
||||
//echo "<p>soinfolog.write values= "; _debug_array($values);
|
||||
|
||||
// write customfields now
|
||||
$existing = array();
|
||||
if ($info_id) // existing entry
|
||||
{
|
||||
$this->db->query("SELECT info_extra_name FROM phpgw_infolog_extra WHERE info_id=$info_id",__LINE__,__FILE__);
|
||||
while($this->db->next_record())
|
||||
{
|
||||
$existing[strtolower($this->db->f(0))] = True;
|
||||
}
|
||||
}
|
||||
foreach($values as $key => $val)
|
||||
{
|
||||
if ($key[0] != '#')
|
||||
{
|
||||
continue; // no customfield
|
||||
}
|
||||
$this->data[$key] = $val; // update internal data
|
||||
|
||||
$val = $this->db->db_addslashes($val);
|
||||
$name = $this->db->db_addslashes($key = substr($key,1));
|
||||
if ($existing[strtolower($key)])
|
||||
{
|
||||
$query = "UPDATE phpgw_infolog_extra SET info_extra_value='$val' WHERE info_id=$info_id AND info_extra_name='$name'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = "INSERT INTO phpgw_infolog_extra (info_id,info_extra_name,info_extra_value) VALUES (".$this->data['info_id'].",'$name','$val')";
|
||||
}
|
||||
$this->db->query($query,__LINE__,__FILE__);
|
||||
}
|
||||
// echo "<p>soinfolog.write this->data= "; _debug_array($this->data);
|
||||
|
||||
return $this->data['info_id'];
|
||||
}
|
||||
|
||||
/*!
|
||||
@function anzSubs
|
||||
@abstract count the sub-entries of $info_id
|
||||
@syntax anzSubs( $info_id )
|
||||
@param $info_id id of log-entry
|
||||
@returns the number of sub-entries
|
||||
*/
|
||||
function anzSubs( $info_id )
|
||||
{
|
||||
if (($info_id = intval($info_id)) <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
$this->db->query($sql="select count(*) FROM phpgw_infolog WHERE info_id_parent=$info_id AND ".$this->aclFilter(),__LINE__,__FILE__);
|
||||
|
||||
$this->db->next_record();
|
||||
//echo "<p>anzSubs($info_id) = ".$this->db->f(0)." ($sql)</p>\n";
|
||||
return $this->db->f(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function search
|
||||
@abstract searches InfoLog for a certain pattern in $query
|
||||
@syntax search( $query )
|
||||
@param $query[order] column-name to sort after
|
||||
@param $query[sort] sort-order DESC or ASC
|
||||
@param $query[filter] string with combination of acl-, date- and status-filters, eg. 'own-open-today' or ''
|
||||
@param $query[cat_id] category to use or 0 or unset
|
||||
@param $query[search] pattern to search, search is done in info_from, info_subject and info_des
|
||||
@param $query[action] / $query[action_id] if only entries linked to a specified app/entry show be used
|
||||
@param &$query[start], &$query[total] nextmatch-parameters will be used and set if query returns less entries
|
||||
@param $query[col_filter] array with column-name - data pairs, data == '' means no filter (!)
|
||||
@returns array with id's as key of the matching log-entries
|
||||
*/
|
||||
function search(&$query)
|
||||
{
|
||||
//echo "<p>soinfolog.search(".print_r($query,True).")</p>\n";
|
||||
$action2app = array(
|
||||
'addr' => 'addressbook',
|
||||
'proj' => 'projects',
|
||||
'event' => 'calendar'
|
||||
);
|
||||
$action = isset($action2app[$query['action']]) ? $action2app[$query['action']] : $query['action'];
|
||||
|
||||
if ($action != '')
|
||||
{
|
||||
$links = $this->links->get_links($action=='sp'?'infolog':$action,$query['action_id'],'infolog');
|
||||
|
||||
if (count($links))
|
||||
{
|
||||
$link_extra = ($action == 'sp' ? 'OR' : 'AND').' phpgw_infolog.info_id IN ('.implode(',',$links).')';
|
||||
}
|
||||
}
|
||||
if (!empty($query['order']) && eregi('^[a-z_0-9, ]+$',$query['order']) && (empty($query['sort']) || eregi('^(DESC|ASC)$',$query['sort'])))
|
||||
{
|
||||
$order = array();
|
||||
foreach(explode(',',$query['order']) as $val)
|
||||
{
|
||||
$val = trim($val);
|
||||
$val = (substr($val,0,5) != 'info_' ? 'info_' : '').$val;
|
||||
if ($val == 'info_des' && $this->db->Type == 'mssql')
|
||||
{
|
||||
$val = "CAST($val AS varchar)";
|
||||
}
|
||||
$order[] = $val;
|
||||
}
|
||||
$ordermethod = 'ORDER BY ' . implode(',',$order) . ' ' . $query['sort'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$ordermethod = 'ORDER BY info_datemodified DESC'; // newest first
|
||||
}
|
||||
$filtermethod = $this->aclFilter($query['filter']);
|
||||
$filtermethod .= $this->statusFilter($query['filter']);
|
||||
$filtermethod .= $this->dateFilter($query['filter']);
|
||||
|
||||
if (is_array($query['col_filter']))
|
||||
{
|
||||
foreach($query['col_filter'] as $col => $data)
|
||||
{
|
||||
$data = $this->db->db_addslashes($data);
|
||||
if (substr($col,0,5) != 'info_') $col = 'info_'.$col;
|
||||
if (!empty($data) && eregi('^[a-z_0-9]+$',$col))
|
||||
{
|
||||
$filtermethod .= " AND $col = '$data'";
|
||||
}
|
||||
}
|
||||
}
|
||||
//echo "<p>filtermethod='$filtermethod'</p>";
|
||||
|
||||
if ((int)$query['cat_id'])
|
||||
{
|
||||
//$filtermethod .= ' AND info_cat='.intval($query['cat_id']).' ';
|
||||
if (!is_object($GLOBALS['phpgw']->categories))
|
||||
{
|
||||
$GLOBALS['phpgw']->categories = CreateObject('phpgwapi.categories');
|
||||
}
|
||||
$cats = $GLOBALS['phpgw']->categories->return_all_children((int)$query['cat_id']);
|
||||
$filtermethod .= ' AND info_cat'.(count($cats)>1? ' IN ('.implode(',',$cats).') ' : '='.(int)$query['cat_id']);
|
||||
}
|
||||
$join = '';
|
||||
if ($query['query']) $query['search'] = $query['query']; // allow both names
|
||||
if ($query['search']) // we search in _from, _subject, _des and _extra_value for $query
|
||||
{
|
||||
$pattern = "'%".$this->db->db_addslashes($query['search'])."%'";
|
||||
$sql_query = "AND (info_from like $pattern OR info_subject LIKE $pattern OR info_des LIKE $pattern OR info_extra_value LIKE $pattern) ";
|
||||
$join = 'LEFT JOIN phpgw_infolog_extra ON phpgw_infolog.info_id=phpgw_infolog_extra.info_id';
|
||||
}
|
||||
$pid = 'AND info_id_parent='.($action == 'sp' ? $query['action_id'] : 0);
|
||||
|
||||
if (!$GLOBALS['phpgw_info']['user']['preferences']['infolog']['listNoSubs'] &&
|
||||
$action != 'sp')
|
||||
{
|
||||
$pid = '';
|
||||
}
|
||||
$ids = array( );
|
||||
if ($action == '' || $action == 'sp' || count($links))
|
||||
{
|
||||
$sql_query = "FROM phpgw_infolog $join WHERE ($filtermethod $pid $sql_query) $link_extra";
|
||||
// mssql cant use DISTICT of text columns (info_des) are involved
|
||||
$distinct = $this->db->Type != 'mssql' ? 'DISTINCT' : '';
|
||||
$this->db->query($sql="SELECT $distinct phpgw_infolog.info_id ".$sql_query,__LINE__,__FILE__);
|
||||
$query['total'] = $this->db->num_rows();
|
||||
|
||||
if (!$query['start'] || $query['start'] > $query['total'])
|
||||
{
|
||||
$query['start'] = 0;
|
||||
}
|
||||
$this->db->limit_query($sql="SELECT $distinct phpgw_infolog.* $sql_query $ordermethod",$query['start'],__LINE__,__FILE__);
|
||||
//echo "<p>sql='$sql'</p>\n";
|
||||
while ($this->db->next_record())
|
||||
{
|
||||
$this->db2data($info);
|
||||
$ids[$info['info_id']] = $info;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$query['start'] = $query['total'] = 0;
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
}
|
824
phpgwapi/inc/class.categories.inc.php
Normal file
824
phpgwapi/inc/class.categories.inc.php
Normal file
@ -0,0 +1,824 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare API - Categories *
|
||||
* This file written by Joseph Engo <jengo@phpgroupware.org> *
|
||||
* and Bettina Gille [ceb@phpgroupware.org] *
|
||||
* Category manager *
|
||||
* Copyright (C) 2000, 2001 Joseph Engo, Bettina Gille *
|
||||
* Copyright (C) 2002, 2003 Bettina Gille *
|
||||
* ------------------------------------------------------------------------ *
|
||||
* This library is part of the eGroupWare API *
|
||||
* http://www.egroupware.org *
|
||||
* ------------------------------------------------------------------------ *
|
||||
* 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 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 *
|
||||
\**************************************************************************/
|
||||
// $Id$
|
||||
// $Source$
|
||||
|
||||
/*!
|
||||
@class categories
|
||||
@abstract class adds ability for applications to make use of categories
|
||||
@discussion examples can be found in notes app
|
||||
*/
|
||||
class categories
|
||||
{
|
||||
var $account_id;
|
||||
var $app_name;
|
||||
var $cats;
|
||||
var $db;
|
||||
var $total_records;
|
||||
var $grants;
|
||||
|
||||
/*!
|
||||
@function categories
|
||||
@abstract constructor for categories class
|
||||
@param $accountid account id
|
||||
@param $app_name app name defaults to current app
|
||||
*/
|
||||
function categories($accountid = '',$app_name = '')
|
||||
{
|
||||
$account_id = get_account_id($accountid);
|
||||
|
||||
if (! $app_name)
|
||||
{
|
||||
$app_name = $GLOBALS['phpgw_info']['flags']['currentapp'];
|
||||
}
|
||||
|
||||
$this->account_id = $account_id;
|
||||
$this->app_name = $GLOBALS['phpgw']->db->db_addslashes($app_name);
|
||||
$this->db = $GLOBALS['phpgw']->db;
|
||||
$this->db2 = $this->db;
|
||||
$this->grants = $GLOBALS['phpgw']->acl->get_grants($app_name);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function filter
|
||||
@abstract ?
|
||||
@param $type string
|
||||
@result string either subs or mains
|
||||
*/
|
||||
function filter($type)
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case 'subs': $s = ' AND cat_parent != 0'; break;
|
||||
case 'mains': $s = ' AND cat_parent = 0'; break;
|
||||
case 'appandmains': $s = " AND cat_appname='" . $this->app_name . "' AND cat_parent =0"; break;
|
||||
case 'appandsubs': $s = " AND cat_appname='" . $this->app_name . "' AND cat_parent !=0"; break;
|
||||
case 'noglobal': $s = " AND cat_appname != '" . $this->app_name . "'"; break;
|
||||
case 'noglobalapp': $s = " AND cat_appname = '" . $this->app_name . "' AND cat_owner != " . $this->account_id; break;
|
||||
default: return False;
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function total
|
||||
@abstract returns the total number of categories for app, subs or mains
|
||||
@param $for one of either 'app' 'subs' or 'mains'
|
||||
@result integer count of categories
|
||||
*/
|
||||
function total($for = 'app')
|
||||
{
|
||||
switch($for)
|
||||
{
|
||||
case 'app': $w = " WHERE cat_appname='" . $this->app_name . "'"; break;
|
||||
case 'appandmains': $w = " WHERE cat_appname='" . $this->app_name . "' AND cat_parent =0"; break;
|
||||
case 'appandsubs': $w = " WHERE cat_appname='" . $this->app_name . "' AND cat_parent !=0"; break;
|
||||
case 'subs': $w = ' WHERE cat_parent != 0'; break;
|
||||
case 'mains': $w = ' WHERE cat_parent = 0'; break;
|
||||
default: return False;
|
||||
}
|
||||
|
||||
$this->db->query("SELECT COUNT(cat_id) FROM phpgw_categories $w",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
return $this->db->f(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
@funtion return_all_children
|
||||
@abstract returns array with id's of all children from $cat_id and $cat_id itself!
|
||||
@param $cat_id integer cat-id to search for
|
||||
@returns array of cat-id's
|
||||
*/
|
||||
function return_all_children($cat_id)
|
||||
{
|
||||
$all_children = array($cat_id);
|
||||
|
||||
$children = $this->return_array('subs',0,False,'','','',True,$cat_id,-1,'id');
|
||||
if (is_array($children) && count($children))
|
||||
{
|
||||
foreach($children as $child)
|
||||
{
|
||||
$all_children = array_merge($all_children,$this->return_all_children($child['id']));
|
||||
}
|
||||
}
|
||||
//echo "<p>categories::return_all_children($cat_id)=(".implode(',',$all_children).")</p>\n";
|
||||
return $all_children;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function return_array
|
||||
@abstract return an array populated with categories
|
||||
@param $type string defaults to 'all'
|
||||
@param $start ?
|
||||
@param $limit ?
|
||||
@param $query string defaults to ''
|
||||
@param $sort string sort order, either defaults to 'ASC'
|
||||
@param $order order by
|
||||
@param $globals True or False, includes the global egroupware categories or not
|
||||
@result $cats array
|
||||
*/
|
||||
function return_array($type,$start,$limit = True,$query = '',$sort = '',$order = '',$globals = False, $parent_id = '', $lastmod = -1, $column = '')
|
||||
{
|
||||
//casting and addslashes for security
|
||||
$start = (int)$start;
|
||||
$parent_id = (int)$parent_id;
|
||||
$query = $this->db->db_addslashes($query);
|
||||
$sort = $this->db->db_addslashes($sort);
|
||||
$order = $this->db->db_addslashes($order);
|
||||
|
||||
if ($globals)
|
||||
{
|
||||
$global_cats = " OR cat_appname='phpgw'";
|
||||
}
|
||||
|
||||
$filter = $this->filter($type);
|
||||
|
||||
if (!$sort)
|
||||
{
|
||||
$sort = 'ASC';
|
||||
}
|
||||
|
||||
if (!empty($order) && preg_match('/^[a-zA-Z_(), ]+$/',$order) && (empty($sort) || preg_match('/^(ASC|DESC|asc|desc)$/',$sort)))
|
||||
{
|
||||
$ordermethod = " ORDER BY $order $sort";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ordermethod = ' ORDER BY cat_main, cat_level, cat_name ASC';
|
||||
}
|
||||
|
||||
if ($this->account_id == '-1')
|
||||
{
|
||||
$grant_cats = ' cat_owner=-1 ';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($this->grants))
|
||||
{
|
||||
$grants = $this->grants;
|
||||
while(list($user) = each($grants))
|
||||
{
|
||||
$public_user_list[] = $user;
|
||||
}
|
||||
reset($public_user_list);
|
||||
$grant_cats = ' (cat_owner=' . $this->account_id . " OR cat_owner=-1 OR cat_access='public' AND cat_owner in(" . implode(',',$public_user_list) . ')) ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$grant_cats = ' cat_owner=' . $this->account_id . ' OR cat_owner=-1 ';
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent_id > 0)
|
||||
{
|
||||
$parent_filter = ' AND cat_parent=' . $parent_id;
|
||||
}
|
||||
|
||||
if ($query)
|
||||
{
|
||||
$querymethod = " AND (cat_name LIKE '%$query%' OR cat_description LIKE '%$query%') ";
|
||||
}
|
||||
|
||||
if($lastmod && $lastmod >= 0)
|
||||
{
|
||||
$querymethod .= ' AND last_mod > ' . (int)$lastmod;
|
||||
}
|
||||
|
||||
if($column)
|
||||
{
|
||||
switch($column)
|
||||
{
|
||||
case 'id': $table_column = ' cat_id '; break;
|
||||
case 'owner': $table_column = ' cat_owner '; break;
|
||||
case 'access': $table_column = ' cat_access '; break;
|
||||
case 'app_name': $table_column = ' cat_appname '; break;
|
||||
case 'main': $table_column = ' cat_main '; break;
|
||||
case 'parent': $table_column = ' cat_parent '; break;
|
||||
case 'name': $table_column = ' cat_name '; break;
|
||||
case 'description': $table_column = ' cat_description '; break;
|
||||
case 'data': $table_column = ' cat_data '; break;
|
||||
case 'last_mod': $table_column = ' last_mod '; break;
|
||||
default: $table_column = ' cat_id '; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$table_column = ' * ';
|
||||
}
|
||||
|
||||
$sql = "SELECT $table_column FROM phpgw_categories WHERE (cat_appname='" . $this->app_name . "' AND" . $grant_cats . $global_cats . ')'
|
||||
. $parent_filter . $querymethod . $filter;
|
||||
|
||||
$this->db2->query($sql,__LINE__,__FILE__);
|
||||
$this->total_records = $this->db2->num_rows();
|
||||
|
||||
if ($limit)
|
||||
{
|
||||
$this->db->limit_query($sql . $ordermethod,$start,__LINE__,__FILE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->db->query($sql . $ordermethod,__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
while ($this->db->next_record())
|
||||
{
|
||||
if ($column)
|
||||
{
|
||||
$cats[] = array
|
||||
(
|
||||
$column => $this->db->f(0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$cats[] = array
|
||||
(
|
||||
'id' => $this->db->f('cat_id'),
|
||||
'owner' => $this->db->f('cat_owner'),
|
||||
'access' => $this->db->f('cat_access'),
|
||||
'app_name' => $this->db->f('cat_appname'),
|
||||
'main' => $this->db->f('cat_main'),
|
||||
'level' => $this->db->f('cat_level'),
|
||||
'parent' => $this->db->f('cat_parent'),
|
||||
'name' => $this->db->f('cat_name'),
|
||||
'description' => $this->db->f('cat_description'),
|
||||
'data' => $this->db->f('cat_data'),
|
||||
'last_mod' => $this->db->f('last_mod')
|
||||
);
|
||||
}
|
||||
}
|
||||
return $cats;
|
||||
}
|
||||
|
||||
function return_sorted_array($start,$limit = True,$query = '',$sort = '',$order = '',$globals = False, $parent_id = '')
|
||||
{
|
||||
//casting and slashes for security
|
||||
$start = (int)$start;
|
||||
$query = $this->db->db_addslashes($query);
|
||||
$sort = $this->db->db_addslashes($sort);
|
||||
$order = $this->db->db_addslashes($order);
|
||||
$parent_id = (int)$parent_id;
|
||||
|
||||
if ($globals)
|
||||
{
|
||||
$global_cats = " OR cat_appname='phpgw'";
|
||||
}
|
||||
|
||||
if (!$sort)
|
||||
{
|
||||
$sort = 'ASC';
|
||||
}
|
||||
|
||||
if (!empty($order) && preg_match('/^[a-zA-Z_, ]+$/',$order) && (empty($sort) || preg_match('/^(ASC|DESC|asc|desc)$/')))
|
||||
{
|
||||
$ordermethod = " ORDER BY $order $sort";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ordermethod = ' ORDER BY cat_name ASC';
|
||||
}
|
||||
|
||||
if ($this->account_id == '-1')
|
||||
{
|
||||
$grant_cats = " cat_owner='-1' ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($this->grants))
|
||||
{
|
||||
$grants = $this->grants;
|
||||
while(list($user) = each($grants))
|
||||
{
|
||||
$public_user_list[] = $user;
|
||||
}
|
||||
reset($public_user_list);
|
||||
$grant_cats = " (cat_owner='" . $this->account_id . "' OR cat_owner='-1' OR cat_access='public' AND cat_owner in(" . implode(',',$public_user_list) . ")) ";
|
||||
}
|
||||
else
|
||||
{
|
||||
$grant_cats = " cat_owner='" . $this->account_id . "' or cat_owner='-1' ";
|
||||
}
|
||||
}
|
||||
|
||||
$parent_select = ' AND cat_parent=' . $parent_id;
|
||||
|
||||
if ($query)
|
||||
{
|
||||
$querymethod = " AND (cat_name LIKE '%$query%' OR cat_description LIKE '%$query%') ";
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM phpgw_categories WHERE (cat_appname='" . $this->app_name . "' AND" . $grant_cats . $global_cats . ")"
|
||||
. $querymethod;
|
||||
|
||||
$this->db2->query($sql . $parent_select,__LINE__,__FILE__);
|
||||
$total = $this->db2->num_rows();
|
||||
|
||||
if ($limit)
|
||||
{
|
||||
$this->db->limit_query($sql . $parent_select . $ordermethod,$start,__LINE__,__FILE__);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->db->query($sql . $parent_select . $ordermethod,__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
while ($this->db->next_record())
|
||||
{
|
||||
$cats[$i]['id'] = (int)$this->db->f('cat_id');
|
||||
$cats[$i]['owner'] = (int)$this->db->f('cat_owner');
|
||||
$cats[$i]['access'] = $this->db->f('cat_access');
|
||||
$cats[$i]['app_name'] = $this->db->f('cat_appname');
|
||||
$cats[$i]['main'] = (int)$this->db->f('cat_main');
|
||||
$cats[$i]['level'] = (int)$this->db->f('cat_level');
|
||||
$cats[$i]['parent'] = (int)$this->db->f('cat_parent');
|
||||
$cats[$i]['name'] = $this->db->f('cat_name');
|
||||
$cats[$i]['description'] = $this->db->f('cat_description');
|
||||
$cats[$i]['data'] = $this->db->f('cat_data');
|
||||
$i++;
|
||||
}
|
||||
|
||||
$num_cats = count($cats);
|
||||
for ($i=0;$i < $num_cats;$i++)
|
||||
{
|
||||
$sub_select = ' AND cat_parent=' . $cats[$i]['id'] . ' AND cat_level=' . ($cats[$i]['level']+1);
|
||||
|
||||
/*$this->db2->query($sql . $sub_select,__LINE__,__FILE__);
|
||||
$total_subs += $this->db2->num_rows();
|
||||
|
||||
if ($limit)
|
||||
{
|
||||
$this->db->limit_query($sql . $sub_select . $ordermethod,$start,__LINE__,__FILE__);
|
||||
}
|
||||
else
|
||||
{*/
|
||||
$this->db->query($sql . $sub_select . $ordermethod,__LINE__,__FILE__);
|
||||
$total += $this->db->num_rows();
|
||||
//}
|
||||
|
||||
$subcats = array();
|
||||
$j = 0;
|
||||
while ($this->db->next_record())
|
||||
{
|
||||
$subcats[$j]['id'] = (int)$this->db->f('cat_id');
|
||||
$subcats[$j]['owner'] = (int)$this->db->f('cat_owner');
|
||||
$subcats[$j]['access'] = $this->db->f('cat_access');
|
||||
$subcats[$j]['app_name'] = $this->db->f('cat_appname');
|
||||
$subcats[$j]['main'] = (int)$this->db->f('cat_main');
|
||||
$subcats[$j]['level'] = (int)$this->db->f('cat_level');
|
||||
$subcats[$j]['parent'] = (int)$this->db->f('cat_parent');
|
||||
$subcats[$j]['name'] = $this->db->f('cat_name');
|
||||
$subcats[$j]['description'] = $this->db->f('cat_description');
|
||||
$subcats[$j]['data'] = $this->db->f('cat_data');
|
||||
$j++;
|
||||
}
|
||||
|
||||
$num_subcats = count($subcats);
|
||||
if ($num_subcats != 0)
|
||||
{
|
||||
$newcats = array();
|
||||
for ($k = 0; $k <= $i; $k++)
|
||||
{
|
||||
$newcats[$k] = $cats[$k];
|
||||
}
|
||||
for ($k = 0; $k < $num_subcats; $k++)
|
||||
{
|
||||
$newcats[$k+$i+1] = $subcats[$k];
|
||||
}
|
||||
for ($k = $i+1; $k < $num_cats; $k++)
|
||||
{
|
||||
$newcats[$k+$num_subcats] = $cats[$k];
|
||||
}
|
||||
$cats = $newcats;
|
||||
$num_cats = count($cats);
|
||||
}
|
||||
}
|
||||
$this->total_records = $total;
|
||||
return $cats;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function return_single
|
||||
@abstract return single
|
||||
@param $id integer id of category
|
||||
@result $cats array populated with
|
||||
*/
|
||||
function return_single($id = '')
|
||||
{
|
||||
$this->db->query('SELECT * FROM phpgw_categories WHERE cat_id=' . (int)$id,__LINE__,__FILE__);
|
||||
|
||||
if ($this->db->next_record())
|
||||
{
|
||||
$cats[0]['id'] = $this->db->f('cat_id');
|
||||
$cats[0]['owner'] = $this->db->f('cat_owner');
|
||||
$cats[0]['access'] = $this->db->f('cat_access');
|
||||
$cats[0]['app_name'] = $this->db->f('cat_appname');
|
||||
$cats[0]['main'] = $this->db->f('cat_main');
|
||||
$cats[0]['level'] = $this->db->f('cat_level');
|
||||
$cats[0]['parent'] = $this->db->f('cat_parent');
|
||||
$cats[0]['name'] = $this->db->f('cat_name');
|
||||
$cats[0]['description'] = $this->db->f('cat_description');
|
||||
$cats[0]['data'] = $this->db->f('cat_data');
|
||||
}
|
||||
return $cats;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function formated_list
|
||||
@abstract return into a select box, list or other formats
|
||||
@param $format currently supports select (select box) or list
|
||||
@param $type string - subs or mains
|
||||
@param $selected - cat_id or array with cat_id values
|
||||
@param $globals True or False, includes the global egroupware categories or not
|
||||
@result $s array - populated with categories
|
||||
*/
|
||||
function formatted_list($format,$type='',$selected = '',$globals = False,$site_link = 'site')
|
||||
{
|
||||
return $this->formated_list($format,$type,$selected,$globals,$site_link);
|
||||
}
|
||||
function formated_list($format,$type='',$selected = '',$globals = False,$site_link = 'site')
|
||||
{
|
||||
if(is_array($format))
|
||||
{
|
||||
$temp_format = $format['format'];
|
||||
$type = ($format['type']?$format['type']:'all');
|
||||
$selected = (isset($format['selected'])?$format['selected']:'');
|
||||
$self = (isset($format['self'])?$format['self']:'');
|
||||
$globals = (isset($format['globals'])?$format['globals']:True);
|
||||
$site_link = (isset($format['site_link'])?$format['site_link']:'site');
|
||||
settype($format,'string');
|
||||
$format = ($temp_format?$temp_format:'select');
|
||||
unset($temp_format);
|
||||
}
|
||||
|
||||
if (!is_array($selected))
|
||||
{
|
||||
$selected = explode(',',$selected);
|
||||
}
|
||||
|
||||
if ($type != 'all')
|
||||
{
|
||||
$cats = $this->return_array($type,$start,False,$query,$sort,$order,$globals);
|
||||
}
|
||||
else
|
||||
{
|
||||
$cats = $this->return_sorted_array($start,False,$query,$sort,$order,$globals);
|
||||
}
|
||||
|
||||
if($self)
|
||||
{
|
||||
for ($i=0;$i<count($cats);$i++)
|
||||
{
|
||||
if ($cats[$i]['id'] == $self)
|
||||
{
|
||||
unset($cats[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($format == 'select')
|
||||
{
|
||||
while (is_array($cats) && list(,$cat) = each($cats))
|
||||
{
|
||||
$s .= '<option value="' . $cat['id'] . '"';
|
||||
if (in_array($cat['id'],$selected))
|
||||
{
|
||||
$s .= ' selected';
|
||||
}
|
||||
$s .= '>';
|
||||
for ($j=0;$j<$cat['level'];$j++)
|
||||
{
|
||||
$s .= ' ';
|
||||
}
|
||||
$s .= $GLOBALS['phpgw']->strip_html($cat['name']);
|
||||
if ($cat['app_name'] == 'phpgw')
|
||||
{
|
||||
$s .= ' <' . lang('Global') . '>';
|
||||
}
|
||||
if ($cat['owner'] == '-1')
|
||||
{
|
||||
$s .= ' <' . lang('Global') . ' ' . lang($this->app_name) . '>';
|
||||
}
|
||||
$s .= '</option>' . "\n";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
if ($format == 'list')
|
||||
{
|
||||
$space = ' ';
|
||||
|
||||
$s = '<table border="0" cellpadding="2" cellspacing="2">' . "\n";
|
||||
|
||||
if ($this->total_records > 0)
|
||||
{
|
||||
for ($i=0;$i<count($cats);$i++)
|
||||
{
|
||||
$image_set = ' ';
|
||||
|
||||
if (in_array($cats[$i]['id'],$selected))
|
||||
{
|
||||
$image_set = '<img src="' . PHPGW_IMAGES_DIR . '/roter_pfeil.gif">';
|
||||
}
|
||||
|
||||
if (($cats[$i]['level'] == 0) && !in_array($cats[$i]['id'],$selected))
|
||||
{
|
||||
$image_set = '<img src="' . PHPGW_IMAGES_DIR . '/grauer_pfeil.gif">';
|
||||
}
|
||||
|
||||
$space_set = str_repeat($space,$cats[$i]['level']);
|
||||
|
||||
$s .= '<tr>' . "\n";
|
||||
$s .= '<td width="8">' . $image_set . '</td>' . "\n";
|
||||
$s .= '<td>' . $space_set . '<a href="' . $GLOBALS['phpgw']->link($site_link,'cat_id=' . $cats[$i]['id']) . '">'
|
||||
. $GLOBALS['phpgw']->strip_html($cats[$i]['name'])
|
||||
. '</a></td>' . "\n"
|
||||
. '</tr>' . "\n";
|
||||
}
|
||||
}
|
||||
$s .= '</table>' . "\n";
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function add
|
||||
@abstract add categories
|
||||
@param $cat_name category name
|
||||
@param $cat_parent category parent
|
||||
@param $cat_description category description defaults to ''
|
||||
@param $cat_data category data defaults to ''
|
||||
*/
|
||||
function add($values)
|
||||
{
|
||||
$values['id'] = (int)$values['id'];
|
||||
$values['parent'] = (int)$values['parent'];
|
||||
|
||||
if ($values['parent'] > 0)
|
||||
{
|
||||
$values['level'] = $this->id2name($values['parent'],'level')+1;
|
||||
$values['main'] = $this->id2name($values['parent'],'main');
|
||||
}
|
||||
|
||||
$values['descr'] = $this->db->db_addslashes($values['descr']);
|
||||
$values['name'] = $this->db->db_addslashes($values['name']);
|
||||
|
||||
if ($values['id'] > 0)
|
||||
{
|
||||
$id_col = 'cat_id,';
|
||||
$id_val = $values['id'] . ',';
|
||||
}
|
||||
|
||||
$this->db->query('INSERT INTO phpgw_categories (' . $id_col . 'cat_parent,cat_owner,cat_access,cat_appname,cat_name,cat_description,cat_data,'
|
||||
. 'cat_main,cat_level, last_mod) VALUES (' . $id_val . (int)$values['parent'] . ',' . $this->account_id . ",'" . $values['access']
|
||||
. "','" . $this->app_name . "','" . $values['name'] . "','" . $values['descr'] . "','" . $values['data']
|
||||
. "'," . (int)$values['main'] . ',' . (int)$values['level'] . ',' . time() . ')',__LINE__,__FILE__);
|
||||
|
||||
if ($values['id'] > 0)
|
||||
{
|
||||
$max = $values['id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$max = $this->db->get_last_insert_id('phpgw_categories','cat_id');
|
||||
}
|
||||
|
||||
$max = (int)$max;
|
||||
if ($values['parent'] == 0)
|
||||
{
|
||||
$this->db->query('UPDATE phpgw_categories SET cat_main=' . $max . ' WHERE cat_id=' . $max,__LINE__,__FILE__);
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function delete
|
||||
@abstract delete category
|
||||
@param $cat_id int - category id
|
||||
*/
|
||||
/*function delete($cat_id,$subs = False)
|
||||
{
|
||||
$cat_id = (int)$cat_id;
|
||||
if ($subs)
|
||||
{
|
||||
$subdelete = ' OR cat_parent=' . $cat_id . ' OR cat_main=' . $cat_id;
|
||||
}
|
||||
|
||||
$this->db->query('DELETE FROM phpgw_categories WHERE cat_id=' . $cat_id . $subdelete . " AND cat_appname='"
|
||||
. $this->app_name . "'",__LINE__,__FILE__);
|
||||
} */
|
||||
|
||||
function delete($cat_id, $drop_subs = False, $modify_subs = False)
|
||||
{
|
||||
$cat_id = (int)$cat_id;
|
||||
if ($drop_subs)
|
||||
{
|
||||
$subdelete = ' OR cat_parent=' . $cat_id . ' OR cat_main=' . $cat_id;
|
||||
}
|
||||
|
||||
if ($modify_subs)
|
||||
{
|
||||
$cats = $this->return_sorted_array('',False,'','','',False, $cat_id);
|
||||
|
||||
$new_parent = $this->id2name($cat_id,'parent');
|
||||
|
||||
for ($i=0;$i<count($cats);$i++)
|
||||
{
|
||||
if ($cats[$i]['level'] == 1)
|
||||
{
|
||||
$this->db->query('UPDATE phpgw_categories set cat_level=0, cat_parent=0, cat_main=' . (int)$cats[$i]['id']
|
||||
. ' WHERE cat_id=' . (int)$cats[$i]['id'] . " AND cat_appname='" . $this->app_name . "'",__LINE__,__FILE__);
|
||||
$new_main = $cats[$i]['id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($new_main)
|
||||
{
|
||||
$update_main = ',cat_main=' . $new_main;
|
||||
}
|
||||
|
||||
if ($cats[$i]['parent'] == $cat_id)
|
||||
{
|
||||
$update_parent = ',cat_parent=' . $new_parent;
|
||||
}
|
||||
|
||||
$this->db->query('UPDATE phpgw_categories set cat_level=' . ($cats[$i]['level']-1) . $update_main . $update_parent
|
||||
. ' WHERE cat_id=' . (int)$cats[$i]['id'] . " AND cat_appname='" . $this->app_name . "'",__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->query('DELETE FROM phpgw_categories WHERE cat_id=' . $cat_id . $subdelete . " AND cat_appname='"
|
||||
. $this->app_name . "'",__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function edit
|
||||
@abstract edit a category
|
||||
@param $cat_id int - category id
|
||||
@param $cat_parent category parent
|
||||
@param $cat_description category description defaults to ''
|
||||
@param $cat_data category data defaults to ''
|
||||
*/
|
||||
function edit($values)
|
||||
{
|
||||
$values['id'] = (int)$values['id'];
|
||||
$values['parent'] = (int)$values['parent'];
|
||||
|
||||
if (isset($values['old_parent']) && (int)$values['old_parent'] != $values['parent'])
|
||||
{
|
||||
$this->delete($values['id'],False,True);
|
||||
return $this->add($values);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($values['parent'] > 0)
|
||||
{
|
||||
$values['main'] = (int)$this->id2name($values['parent'],'main');
|
||||
$values['level'] = (int)$this->id2name($values['parent'],'level') + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['main'] = $values['id'];
|
||||
$values['level'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$values['descr'] = $this->db->db_addslashes($values['descr']);
|
||||
$values['name'] = $this->db->db_addslashes($values['name']);
|
||||
|
||||
$sql = "UPDATE phpgw_categories SET cat_name='" . $values['name'] . "', cat_description='" . $values['descr']
|
||||
. "', cat_data='" . $values['data'] . "', cat_parent=" . $values['parent'] . ", cat_access='"
|
||||
. $values['access'] . "', cat_main=" . $values['main'] . ', cat_level=' . $values['level'] . ',last_mod=' . time()
|
||||
. " WHERE cat_appname='" . $this->app_name . "' AND cat_id=" . $values['id'];
|
||||
|
||||
$this->db->query($sql,__LINE__,__FILE__);
|
||||
return $values['id'];
|
||||
}
|
||||
|
||||
function name2id($cat_name)
|
||||
{
|
||||
$this->db->query("SELECT cat_id FROM phpgw_categories WHERE cat_name='" . $this->db->db_addslashes($cat_name) . "' "
|
||||
."AND cat_appname='" . $this->app_name . "' AND (cat_owner=" . $this->account_id . ' OR cat_owner=-1)',__LINE__,__FILE__);
|
||||
|
||||
if(!$this->db->num_rows())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->db->next_record();
|
||||
|
||||
return $this->db->f('cat_id');
|
||||
}
|
||||
|
||||
function id2name($cat_id = '', $item = 'name')
|
||||
{
|
||||
$cat_id = (int)$cat_id;
|
||||
if($cat_id == 0)
|
||||
{
|
||||
return '--';
|
||||
}
|
||||
switch($item)
|
||||
{
|
||||
case 'owner': $value = 'cat_owner'; break;
|
||||
case 'main': $value = 'cat_main'; break;
|
||||
case 'level': $value = 'cat_level'; break;
|
||||
case 'parent': $value = 'cat_parent'; break;
|
||||
case 'name': $value = 'cat_name'; break;
|
||||
default: $value = 'cat_parent'; break;
|
||||
}
|
||||
|
||||
$this->db->query("SELECT $value FROM phpgw_categories WHERE cat_id=" . $cat_id,__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
|
||||
if ($this->db->f($value))
|
||||
{
|
||||
return $this->db->f($value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($item == 'name')
|
||||
{
|
||||
return '--';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function return_name
|
||||
@abstract return category name given $cat_id
|
||||
@param $cat_id
|
||||
@result cat_name category name
|
||||
*/
|
||||
// NOTE: This is only a temp wrapper, use id2name() to keep things matching across the board. (jengo)
|
||||
function return_name($cat_id)
|
||||
{
|
||||
return $this->id2name($cat_id);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function exists
|
||||
@abstract used for checking if a category name exists
|
||||
@param $type subs or mains
|
||||
@param $cat_name category name
|
||||
@result boolean true or false
|
||||
*/
|
||||
function exists($type,$cat_name = '',$cat_id = '')
|
||||
{
|
||||
$cat_id = (int)$cat_id;
|
||||
$filter = $this->filter($type);
|
||||
|
||||
if ($cat_name)
|
||||
{
|
||||
$cat_exists = " cat_name='" . $this->db->db_addslashes($cat_name) . "' ";
|
||||
}
|
||||
|
||||
if ($cat_id)
|
||||
{
|
||||
$cat_exists = ' cat_parent=' . $cat_id;
|
||||
}
|
||||
|
||||
if ($cat_name && $cat_id)
|
||||
{
|
||||
$cat_exists = " cat_name='" . $this->db->db_addslashes($cat_name) . "' AND cat_id != $cat_id ";
|
||||
}
|
||||
|
||||
$this->db->query("SELECT COUNT(cat_id) FROM phpgw_categories WHERE $cat_exists $filter",__LINE__,__FILE__);
|
||||
|
||||
$this->db->next_record();
|
||||
|
||||
if ($this->db->f(0))
|
||||
{
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -181,6 +181,12 @@
|
||||
|
||||
if (!$this->Link_ID)
|
||||
{
|
||||
foreach(array('Host','Database','User','Password') as $name)
|
||||
{
|
||||
$$name = $this->$name;
|
||||
}
|
||||
$type = $this->Type;
|
||||
|
||||
switch($this->Type) // convert to ADO db-type-names
|
||||
{
|
||||
case 'pgsql':
|
||||
@ -190,13 +196,12 @@
|
||||
" user=$this->User".($this->Password ? " password='".addslashes($this->Password)."'" : '');
|
||||
$User = $Password = $Database = ''; // to indicate $Host is a connection-string
|
||||
break;
|
||||
case 'mssql':
|
||||
if ($this->Port) $Host .= ','.$this->Port;
|
||||
break;
|
||||
default:
|
||||
$Host = $this->Host . ($this->Port ? ':'.$this->Port : '');
|
||||
foreach(array('Database','User','Password') as $name)
|
||||
{
|
||||
$$name = $this->$name;
|
||||
}
|
||||
$type = $this->Type;
|
||||
if ($this->Port) $Host .= ':'.$this->Port;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_object($GLOBALS['phpgw']->ADOdb) || // we have no connection so far
|
||||
@ -228,6 +233,15 @@
|
||||
return 0; // in case error-reporting = 'no'
|
||||
}
|
||||
//echo "new ADOdb connection<pre>".print_r($GLOBALS['phpgw']->ADOdb,True)."</pre>\n";
|
||||
|
||||
if ($this->Type == 'mssql')
|
||||
{
|
||||
// this is the format ADOdb expects
|
||||
$this->Link_ID->Execute('SET DATEFORMAT ymd');
|
||||
// sets the limit to the maximum
|
||||
ini_set('mssql.textlimit',2147483647);
|
||||
ini_set('mssql.sizelimit',2147483647);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -682,7 +696,7 @@
|
||||
function haltmsg($msg)
|
||||
{
|
||||
printf("<p><b>Database error:</b> %s<br>\n", $msg);
|
||||
if ($this->Errno != "0" && $this->Error != "()")
|
||||
if (($this->Errno || $this->Error) && $this->Error != "()")
|
||||
{
|
||||
printf("<b>$this->Type Error</b>: %s (%s)<br>\n",$this->Errno,$this->Error);
|
||||
}
|
||||
@ -943,6 +957,10 @@
|
||||
break; // ADOdb has no BlobEncode for mysql and returns an unquoted string !!!
|
||||
}
|
||||
return "'" . $this->Link_ID->BlobEncode($value) . "'";
|
||||
case 'date':
|
||||
return $this->Link_ID->DBDate($value);
|
||||
case 'timestamp':
|
||||
return $this->Link_ID->DBTimeStamp($value);
|
||||
}
|
||||
return $this->Link_ID->quote($value);
|
||||
}
|
||||
|
1270
phpgwapi/inc/class.preferences.inc.php
Normal file
1270
phpgwapi/inc/class.preferences.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
590
phpgwapi/inc/class.schema_proc.inc.php
Normal file
590
phpgwapi/inc/class.schema_proc.inc.php
Normal file
@ -0,0 +1,590 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Setup *
|
||||
* http://www.egroupware.org *
|
||||
* -------------------------------------------- *
|
||||
* This file written by Michael Dean<mdean@users.sourceforge.net> *
|
||||
* and Miles Lott<milosch@groupwhere.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class schema_proc
|
||||
{
|
||||
var $m_oTranslator;
|
||||
var $m_oDeltaProc;
|
||||
var $m_odb;
|
||||
var $m_aTables;
|
||||
var $m_bDeltaOnly;
|
||||
|
||||
function schema_proc($dbms)
|
||||
{
|
||||
$this->sType = $dbms;
|
||||
$this->m_oTranslator = CreateObject('phpgwapi.schema_proc_' . $dbms);
|
||||
$this->m_oDeltaProc = CreateObject('phpgwapi.schema_proc_array');
|
||||
$this->m_aTables = array();
|
||||
$this->m_bDeltaOnly = False; // Default to false here in case it's just a CreateTable script
|
||||
}
|
||||
|
||||
function GenerateScripts($aTables, $bOutputHTML=False)
|
||||
{
|
||||
if (!is_array($aTables))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$this->m_aTables = $aTables;
|
||||
|
||||
$sAllTableSQL = '';
|
||||
foreach ($this->m_aTables as $sTableName => $aTableDef)
|
||||
{
|
||||
$sSequenceSQL = '';
|
||||
$append_ix = False;
|
||||
if($this->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL,$append_ix))
|
||||
{
|
||||
if($append_ix)
|
||||
{
|
||||
$sTableSQL = "CREATE TABLE $sTableName (\n$sTableSQL\n"
|
||||
. $this->m_oTranslator->m_sStatementTerminator;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTableSQL = "CREATE TABLE $sTableName (\n$sTableSQL\n)"
|
||||
. $this->m_oTranslator->m_sStatementTerminator;
|
||||
}
|
||||
if($sSequenceSQL != '')
|
||||
{
|
||||
$sAllTableSQL .= $sSequenceSQL . "\n";
|
||||
}
|
||||
$sAllTableSQL .= $sTableSQL . "\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
print('<br>Failed generating script for <b>' . $sTableName . '</b><br>');
|
||||
echo '<pre style="text-align: left;">'.$sTableName.' = '; print_r($aTableDef); echo "</pre>\n";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if($bOutputHTML)
|
||||
{
|
||||
print('<pre>' . $sAllTableSQL . '</pre><br><br>');
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function ExecuteScripts($aTables, $bOutputHTML=False)
|
||||
{
|
||||
if(!is_array($aTables) || !IsSet($this->m_odb))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
reset($aTables);
|
||||
$this->m_aTables = $aTables;
|
||||
|
||||
while(list($sTableName, $aTableDef) = each($aTables))
|
||||
{
|
||||
if($this->CreateTable($sTableName, $aTableDef))
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
echo '<br>Create Table <b>' . $sTableName . '</b>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
echo '<br>Create Table Failed For <b>' . $sTableName . '</b>';
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function DropAllTables($aTables, $bOutputHTML=False)
|
||||
{
|
||||
if(!is_array($aTables) || !isset($this->m_odb))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
$this->m_aTables = $aTables;
|
||||
|
||||
reset($this->m_aTables);
|
||||
while(list($sTableName, $aTableDef) = each($this->m_aTables))
|
||||
{
|
||||
if($this->DropTable($sTableName))
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
echo '<br>Drop Table <b>' . $sTableSQL . '</b>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function DropTable($sTableName)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->DropTable($this, $this->m_aTables, $sTableName);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->DropTable($this, $this->m_aTables, $sTableName);
|
||||
}
|
||||
|
||||
function DropColumn($sTableName, $aTableDef, $sColumnName, $bCopyData = true)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->DropColumn($this, $this->m_aTables, $sTableName, $aTableDef, $sColumnName, $bCopyData);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->DropColumn($this, $this->m_aTables, $sTableName, $aTableDef, $sColumnName, $bCopyData);
|
||||
}
|
||||
|
||||
function RenameTable($sOldTableName, $sNewTableName)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->RenameTable($this, $this->m_aTables, $sOldTableName, $sNewTableName);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->RenameTable($this, $this->m_aTables, $sOldTableName, $sNewTableName);
|
||||
}
|
||||
|
||||
function RenameColumn($sTableName, $sOldColumnName, $sNewColumnName, $bCopyData=True)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->RenameColumn($this, $this->m_aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->RenameColumn($this, $this->m_aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData);
|
||||
}
|
||||
|
||||
function AlterColumn($sTableName, $sColumnName, $aColumnDef, $bCopyData=True)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->AlterColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef, $bCopyData);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->AlterColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef, $bCopyData);
|
||||
}
|
||||
|
||||
function AddColumn($sTableName, $sColumnName, $aColumnDef)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->AddColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->AddColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef);
|
||||
}
|
||||
|
||||
function CreateTable($sTableName, $aTableDef)
|
||||
{
|
||||
$retVal = $this->m_oDeltaProc->CreateTable($this, $this->m_aTables, $sTableName, $aTableDef);
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
return $retVal && $this->m_oTranslator->CreateTable($this, $this->m_aTables, $sTableName, $aTableDef);
|
||||
}
|
||||
|
||||
function UpdateSequence($sTableName,$sColumnName)
|
||||
{
|
||||
if (method_exists($this->m_oTranslator,'UpdateSequence'))
|
||||
{
|
||||
return $this->m_oTranslator->UpdateSequence($this->m_odb,$sTableName,$sColumnName);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
// This function manually re-created the table incl. primary key and all other indices
|
||||
// It is meant to use if the primary key, existing indices or column-order changes or
|
||||
// columns are not longer used or new columns need to be created (with there default value or NULL)
|
||||
// Beside the default-value in the schema, one can give extra defaults via $aDefaults to eg. use an
|
||||
// other colum or function to set the value of a new or changed column
|
||||
function RefreshTable($sTableName, $aTableDef, $aDefaults=False)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo "<p>schema_proc::RefreshTable('$sTableName',"._debug_array($aTableDef,False).")<p>m_aTables[$sTableName]="._debug_array($this->m_aTables[$sTableName],False)."\n"; }
|
||||
$old_fd = $this->m_aTables[$sTableName]['fd'];
|
||||
|
||||
$Ok = $this->m_oDeltaProc->RefreshTable($this, $this->m_aTables, $sTableName, $aTableDef);
|
||||
if(!$Ok || $this->m_bDeltaOnly)
|
||||
{
|
||||
return $Ok; // nothing else to do
|
||||
}
|
||||
$tmp_name = 'tmp_'.$sTableName;
|
||||
$this->m_odb->transaction_begin();
|
||||
|
||||
$select = array();
|
||||
foreach($aTableDef['fd'] as $name => $data)
|
||||
{
|
||||
if ($aDefaults && isset($aDefaults[$name])) // use given default
|
||||
{
|
||||
$value = $aDefaults[$name];
|
||||
}
|
||||
elseif (isset($old_fd[$name])) // existing column, use its value => column-name in query
|
||||
{
|
||||
$value = $name;
|
||||
}
|
||||
else // new column => use default value or NULL
|
||||
{
|
||||
if (!isset($data['default']) && (!isset($data['nullable']) || $data['nullable']))
|
||||
{
|
||||
$value = 'NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $this->m_odb->quote(isset($data['default']) ? $data['default'] : '',$data['type']);
|
||||
// fix for postgres error "no '<' operator for type 'unknown'"
|
||||
if ($this->sType == 'pgsql')
|
||||
{
|
||||
$type_translated = $this->m_oTranslator->TranslateType($data['type']);
|
||||
$value = "CAST($value AS $type_translated)";
|
||||
}
|
||||
}
|
||||
}
|
||||
$select[] = $value;
|
||||
}
|
||||
$select = implode(',',$select);
|
||||
|
||||
$Ok = $this->RenameTable($sTableName,$tmp_name) &&
|
||||
$this->CreateTable($sTableName,$aTableDef) &&
|
||||
$this->m_odb->query("INSERT INTO $sTableName SELECT DISTINCT $select FROM $tmp_name",__LINE__,__FILE__);
|
||||
|
||||
if (!$Ok)
|
||||
{
|
||||
$this->m_odb->transaction_abort();
|
||||
return False;
|
||||
}
|
||||
// do we need to update the new sequences value ?
|
||||
if (count($aTableDef['pk']) == 1 && $aTableDef['fd'][$aTableDef['pk'][0]]['type'] == 'auto')
|
||||
{
|
||||
$this->UpdateSequence($sTableName,$aTableDef['pk'][0]);
|
||||
}
|
||||
$this->DropTable($tmp_name);
|
||||
$this->m_odb->transaction_commit();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function f($value)
|
||||
{
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
// Don't care, since we are processing deltas only
|
||||
return False;
|
||||
}
|
||||
|
||||
return $this->m_odb->f($value);
|
||||
}
|
||||
|
||||
function num_rows()
|
||||
{
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
// If not False, we will cause while loops calling us to hang
|
||||
return False;
|
||||
}
|
||||
|
||||
return $this->m_odb->num_rows();
|
||||
}
|
||||
|
||||
function next_record()
|
||||
{
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
// If not False, we will cause while loops calling us to hang
|
||||
return False;
|
||||
}
|
||||
|
||||
return $this->m_odb->next_record();
|
||||
}
|
||||
|
||||
function query($sQuery, $line='', $file='')
|
||||
{
|
||||
if($this->m_bDeltaOnly)
|
||||
{
|
||||
// Don't run this query, since we are processing deltas only
|
||||
return True;
|
||||
}
|
||||
|
||||
return $this->m_odb->query($sQuery, $line, $file);
|
||||
}
|
||||
|
||||
function _GetTableSQL($sTableName, $aTableDef, &$sTableSQL, &$sSequenceSQL,&$append_ix)
|
||||
{
|
||||
if(!is_array($aTableDef))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
$sTableSQL = '';
|
||||
reset($aTableDef['fd']);
|
||||
while(list($sFieldName, $aFieldAttr) = each($aTableDef['fd']))
|
||||
{
|
||||
$sFieldSQL = '';
|
||||
if($this->_GetFieldSQL($aFieldAttr, $sFieldSQL))
|
||||
{
|
||||
if($sTableSQL != '')
|
||||
{
|
||||
$sTableSQL .= ",\n";
|
||||
}
|
||||
|
||||
$sTableSQL .= "$sFieldName $sFieldSQL";
|
||||
|
||||
if($aFieldAttr['type'] == 'auto')
|
||||
{
|
||||
$this->m_oTranslator->GetSequenceSQL($sTableName, $sSequenceSQL);
|
||||
if($sSequenceSQL != '')
|
||||
{
|
||||
$sTableSQL .= sprintf(" DEFAULT nextval('seq_%s')", $sTableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo 'GetFieldSQL failed for ' . $sFieldName; }
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
$sUCSQL = '';
|
||||
$sPKSQL = '';
|
||||
$sIXSQL = '';
|
||||
|
||||
if(count($aTableDef['pk']) > 0)
|
||||
{
|
||||
if(!$this->_GetPK($aTableDef['pk'], $sPKSQL))
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
print('<br>Failed getting primary key<br>');
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if(count($aTableDef['uc']) > 0)
|
||||
{
|
||||
if(!$this->_GetUC($aTableDef['uc'], $sUCSQL))
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
print('<br>Failed getting unique constraint<br>');
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if(count($aTableDef['ix']) > 0)
|
||||
{
|
||||
$append_ix = False;
|
||||
if(!$this->_GetIX($aTableDef['ix'], $sIXSQL,$append_ix,$sTableName))
|
||||
{
|
||||
if($bOutputHTML)
|
||||
{
|
||||
print('<br>Failed getting index<br>');
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
// print('<br>HELLO!: ' . $sIXSQL);
|
||||
}
|
||||
|
||||
if($sPKSQL != '')
|
||||
{
|
||||
$sTableSQL .= ",\n" . $sPKSQL;
|
||||
}
|
||||
|
||||
if($sUCSQL != '')
|
||||
{
|
||||
$sTableSQL .= ",\n" . $sUCSQL;
|
||||
}
|
||||
|
||||
if($sIXSQL != '')
|
||||
{
|
||||
if($append_ix)
|
||||
{
|
||||
$sTableSQL .= ");\n" . $sIXSQL;
|
||||
//pg: CREATE INDEX test1_id_index ON test1 (id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sTableSQL .= ",\n" . $sIXSQL;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
// Get field DDL
|
||||
function _GetFieldSQL($aField, &$sFieldSQL)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo'<br>_GetFieldSQL(): Incoming ARRAY: '; var_dump($aField); }
|
||||
if(!is_array($aField))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sType = '';
|
||||
$iPrecision = 0;
|
||||
$iScale = 0;
|
||||
$bNullable = true;
|
||||
|
||||
reset($aField);
|
||||
while(list($sAttr, $vAttrVal) = each($aField))
|
||||
{
|
||||
switch ($sAttr)
|
||||
{
|
||||
case 'type':
|
||||
$sType = $vAttrVal;
|
||||
break;
|
||||
case 'precision':
|
||||
$iPrecision = (int)$vAttrVal;
|
||||
break;
|
||||
case 'scale':
|
||||
$iScale = (int)$vAttrVal;
|
||||
break;
|
||||
case 'nullable':
|
||||
$bNullable = $vAttrVal;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Translate the type for the DBMS
|
||||
if($sFieldSQL = $this->m_oTranslator->TranslateType($sType, $iPrecision, $iScale))
|
||||
{
|
||||
if(strpos(strtolower($sFieldSQL),'null')===false)
|
||||
{
|
||||
if(!$bNullable)
|
||||
{
|
||||
$sFieldSQL .= ' NOT NULL';
|
||||
}
|
||||
elseif ($this->m_oTranslator->b_needExplicitNULL)
|
||||
{
|
||||
$sFieldSQL .= ' NULL';
|
||||
}
|
||||
}
|
||||
if(isset($aField['default']))
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo'<br>_GetFieldSQL(): Calling TranslateDefault for "' . $aField['default'] . '"'; }
|
||||
// Get default DDL - useful for differences in date defaults (eg, now() vs. getdate())
|
||||
|
||||
$sFieldSQL .= ' DEFAULT ' . (is_numeric($aField['default']) ? $aField['default'] :
|
||||
$this->m_oTranslator->TranslateDefault($aField['default']));
|
||||
}
|
||||
if($GLOBALS['DEBUG']) { echo'<br>_GetFieldSQL(): Outgoing SQL: ' . $sFieldSQL; }
|
||||
return true;
|
||||
}
|
||||
|
||||
if($GLOBALS['DEBUG']) { echo '<br>Failed to translate field: type[' . $sType . '] precision[' . $iPrecision . '] scale[' . $iScale . ']<br>'; }
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
function _GetPK($aFields, &$sPKSQL)
|
||||
{
|
||||
$sPKSQL = '';
|
||||
if(count($aFields) < 1)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
$sPKSQL = $this->m_oTranslator->GetPKSQL(implode(',',$aFields));
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function _GetUC($aFields, &$sUCSQL)
|
||||
{
|
||||
$sUCSQL = '';
|
||||
if(count($aFields) < 1)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
foreach($aFields as $mFields)
|
||||
{
|
||||
$aUCSQL[] = $this->m_oTranslator->GetUCSQL(
|
||||
is_array($mFields) ? implode(',',$mFields) : $mFields);
|
||||
}
|
||||
$sUCSQL = implode(",\n",$aUCSQL);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
function _GetIX($aFields, &$sIXSQL, &$append, $sTableName)
|
||||
{
|
||||
$sUCSQL = '';
|
||||
if(count($aFields) < 1)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
$aIXSQL = array();
|
||||
foreach($aFields as $mFields)
|
||||
{
|
||||
$options = False;
|
||||
if (is_array($mFields))
|
||||
{
|
||||
if (isset($mFields['options'])) // array sets additional options
|
||||
{
|
||||
$options = @$mFields['options'][$this->sType]; // db-specific options, eg. index-type
|
||||
unset($mFields['options']);
|
||||
}
|
||||
if ($options === false)
|
||||
{
|
||||
continue; // dont create index for that db, eg. cant index text
|
||||
}
|
||||
$mFields = implode(',',$mFields);
|
||||
}
|
||||
$aIXSQL[] = $this->m_oTranslator->GetIXSQL($mFields,$append,$options,$sTableName);
|
||||
}
|
||||
if($append)
|
||||
{
|
||||
$sIXSQL = implode("\n",$aIXSQL);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sIXSQL = implode(",\n",$aIXSQL);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
}
|
||||
?>
|
364
phpgwapi/inc/class.schema_proc_mssql.inc.php
Normal file
364
phpgwapi/inc/class.schema_proc_mssql.inc.php
Normal file
@ -0,0 +1,364 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Setup *
|
||||
* http://www.egroupware.org *
|
||||
* -------------------------------------------- *
|
||||
* This file written by Michael Dean<mdean@users.sourceforge.net> *
|
||||
* and Miles Lott<milosch@groupwhere.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class schema_proc_mssql
|
||||
{
|
||||
var $m_sStatementTerminator;
|
||||
/* Following added to convert sql to array */
|
||||
var $sCol = array();
|
||||
var $pk = array();
|
||||
var $fk = array();
|
||||
var $ix = array();
|
||||
var $uc = array();
|
||||
var $b_needExplicitNULL = true; // no definition means NOT NULL for mssql
|
||||
|
||||
function schema_proc_mssql()
|
||||
{
|
||||
$this->m_sStatementTerminator = ';';
|
||||
}
|
||||
|
||||
/* Return a type suitable for DDL */
|
||||
function TranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = '';
|
||||
switch($sType)
|
||||
{
|
||||
case 'auto':
|
||||
$sTranslated = 'int identity(1,1) NOT NULL';
|
||||
break;
|
||||
case 'blob':
|
||||
$sTranslated = 'image'; /* wonder how well PHP will support this??? */
|
||||
break;
|
||||
case 'char':
|
||||
if ($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = sprintf("char(%d)", $iPrecision);
|
||||
}
|
||||
if ($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$sTranslated = 'smalldatetime';
|
||||
break;
|
||||
case 'decimal':
|
||||
$sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale);
|
||||
break;
|
||||
case 'float':
|
||||
switch ($iPrecision)
|
||||
{
|
||||
case 4:
|
||||
$sTranslated = 'float';
|
||||
break;
|
||||
case 8:
|
||||
$sTranslated = 'real';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
switch ($iPrecision)
|
||||
{
|
||||
case 2:
|
||||
$sTranslated = 'smallint';
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
$sTranslated = 'int';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
$sTranslated = 'text';
|
||||
break;
|
||||
case 'timestamp':
|
||||
$sTranslated = 'datetime';
|
||||
break;
|
||||
case 'bool':
|
||||
$sTranslated = 'bit';
|
||||
break;
|
||||
case 'varchar':
|
||||
if ($iPrecision > 0 && $iPrecision <= 256)
|
||||
{
|
||||
$sTranslated = sprintf("varchar(%d)", $iPrecision);
|
||||
}
|
||||
if ($iPrecision > 256)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function TranslateDefault($sDefault)
|
||||
{
|
||||
switch ($sDefault)
|
||||
{
|
||||
case 'current_date':
|
||||
case 'current_timestamp':
|
||||
return 'GetDate()';
|
||||
}
|
||||
|
||||
return "'$sDefault'";
|
||||
}
|
||||
|
||||
// Inverse of above, convert sql column types to array info
|
||||
function rTranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = '';
|
||||
if ($sType == 'int' || $sType == 'tinyint' || $sType == 'smallint')
|
||||
{
|
||||
if ($iPrecision > 8)
|
||||
{
|
||||
$iPrecision = 8;
|
||||
}
|
||||
elseif($iPrecision > 4)
|
||||
{
|
||||
$iPrecision = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iPrecision = 2;
|
||||
}
|
||||
}
|
||||
switch($sType)
|
||||
{
|
||||
case 'tinyint':
|
||||
case 'smallint':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 2";
|
||||
break;
|
||||
case 'int':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 4";
|
||||
break;
|
||||
case 'char':
|
||||
if ($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'char', 'precision' => $iPrecision";
|
||||
}
|
||||
if ($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'decimal':
|
||||
$sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale";
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
$sTranslated = "'type' => 'float', 'precision' => $iPrecision";
|
||||
break;
|
||||
case 'smalldatetime':
|
||||
$sTranslated = "'type' => 'date'";
|
||||
break;
|
||||
case 'datetime':
|
||||
$sTranslated = "'type' => 'timestamp'";
|
||||
break;
|
||||
case 'varchar':
|
||||
if ($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'varchar', 'precision' => $iPrecision";
|
||||
}
|
||||
if ($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'image':
|
||||
$sTranslated = "'type' => 'blob'";
|
||||
break;
|
||||
case 'text':
|
||||
$sTranslated = "'type' => '$sType'";
|
||||
break;
|
||||
case 'bit':
|
||||
$sTranslated = "'type' => 'bool'";
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function GetPKSQL($sFields)
|
||||
{
|
||||
return "PRIMARY KEY NONCLUSTERED ($sFields)";
|
||||
}
|
||||
|
||||
function GetUCSQL($sFields)
|
||||
{
|
||||
return "UNIQUE($sFields)";
|
||||
}
|
||||
|
||||
function GetIXSQL($sFields,&$append,$options,$sTableName)
|
||||
{
|
||||
$append = True;
|
||||
$ixFields = str_replace(',','_',$sFields);
|
||||
$index = $sTableName . '_' . $ixFields . '_idx';
|
||||
return "CREATE INDEX $index ON $sTableName ($sFields);\n";
|
||||
}
|
||||
|
||||
function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn = '')
|
||||
{
|
||||
$sColumns = '';
|
||||
$this->pk = array();
|
||||
$this->fk = array();
|
||||
$this->ix = array();
|
||||
$this->uc = array();
|
||||
|
||||
// Field, Type, Null, Key, Default, Extra
|
||||
$oProc->m_odb->query("exec sp_columns '$sTableName'");
|
||||
while ($oProc->m_odb->next_record())
|
||||
{
|
||||
$type = $default = $null = $nullcomma = $prec = $scale = $ret = $colinfo = $scales = '';
|
||||
if ($sColumns != '')
|
||||
{
|
||||
$sColumns .= ',';
|
||||
}
|
||||
$sColumns .= $oProc->m_odb->f(0);
|
||||
|
||||
// The rest of this is used only for SQL->array
|
||||
$colinfo = explode('(',$oProc->m_odb->f(1));
|
||||
$prec = ereg_replace(')','',$colinfo[1]);
|
||||
$scales = explode(',',$prec);
|
||||
if ($scales[1])
|
||||
{
|
||||
$prec = $scales[0];
|
||||
$scale = $scales[1];
|
||||
}
|
||||
$type = $this->rTranslateType($colinfo[0], $prec, $scale);
|
||||
|
||||
if ($oProc->m_odb->f(2) == 'YES')
|
||||
{
|
||||
$null = "'nullable' => True";
|
||||
}
|
||||
else
|
||||
{
|
||||
$null = "'nullable' => False";
|
||||
}
|
||||
if ($oProc->m_odb->f(4))
|
||||
{
|
||||
$default = "'default' => '".$oProc->m_odb->f(4)."'";
|
||||
$nullcomma = ',';
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = '';
|
||||
$nullcomma = '';
|
||||
}
|
||||
if ($oProc->m_odb->f(5))
|
||||
{
|
||||
$type = "'type' => 'auto'";
|
||||
}
|
||||
$this->sCol[] = "\t\t\t\t'" . $oProc->m_odb->f(0)."' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n";
|
||||
if ($oProc->m_odb->f(3) == 'PRI')
|
||||
{
|
||||
$this->pk[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
if ($oProc->m_odb->f(3) == 'UNI')
|
||||
{
|
||||
$this->uc[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
/* Hmmm, MUL could also mean unique, or not... */
|
||||
if ($oProc->m_odb->f(3) == 'MUL')
|
||||
{
|
||||
$this->ix[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
}
|
||||
/* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */
|
||||
$this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function DropTable($oProc, &$aTables, $sTableName)
|
||||
{
|
||||
return !!($oProc->m_odb->query("DROP TABLE " . $sTableName));
|
||||
}
|
||||
|
||||
function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true)
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sTableName DROP COLUMN $sColumnName"));
|
||||
}
|
||||
|
||||
function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName)
|
||||
{
|
||||
return !!($oProc->m_odb->query("EXEC sp_rename '$sOldTableName', '$sNewTableName'"));
|
||||
}
|
||||
|
||||
function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true)
|
||||
{
|
||||
// This really needs testing - it can affect primary keys, and other table-related objects
|
||||
// like sequences and such
|
||||
global $DEBUG;
|
||||
if ($DEBUG) { echo '<br>RenameColumn: calling _GetFieldSQL for ' . $sNewColumnName; }
|
||||
if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sNewColumnName], $sNewColumnSQL))
|
||||
{
|
||||
return !!($oProc->m_odb->query("EXEC sp_rename '$sTableName.$sOldColumnName', '$sNewColumnName'"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true)
|
||||
{
|
||||
global $DEBUG;
|
||||
if ($DEBUG) { echo '<br>AlterColumn: calling _GetFieldSQL for ' . $sNewColumnName; }
|
||||
if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sColumnName], $sNewColumnSQL))
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sTableName ALTER COLUMN $sColumnName " . $sNewColumnSQL));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef)
|
||||
{
|
||||
$oProc->_GetFieldSQL($aColumnDef, $sFieldSQL);
|
||||
$query = "ALTER TABLE $sTableName ADD $sColumnName $sFieldSQL";
|
||||
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
function GetSequenceSQL($sTableName, &$sSequenceSQL)
|
||||
{
|
||||
$sSequenceSQL = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
function CreateTable($oProc, &$aTables, $sTableName, $aTableDef)
|
||||
{
|
||||
if ($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL,$append_ix))
|
||||
{
|
||||
// create sequence first since it will be needed for default
|
||||
if ($sSequenceSQL != '')
|
||||
{
|
||||
$oProc->m_odb->query($sSequenceSQL);
|
||||
}
|
||||
|
||||
if($append_ix)
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL";
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL)";
|
||||
}
|
||||
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
426
phpgwapi/inc/class.schema_proc_mysql.inc.php
Normal file
426
phpgwapi/inc/class.schema_proc_mysql.inc.php
Normal file
@ -0,0 +1,426 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Setup *
|
||||
* http://www.egroupware.org *
|
||||
* -------------------------------------------- *
|
||||
* This file written by Michael Dean<mdean@users.sourceforge.net> *
|
||||
* and Miles Lott<milosch@groupwhere.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class schema_proc_mysql
|
||||
{
|
||||
var $m_sStatementTerminator;
|
||||
/* Following added to convert sql to array */
|
||||
var $sCol = array();
|
||||
var $pk = array();
|
||||
var $fk = array();
|
||||
var $ix = array();
|
||||
var $uc = array();
|
||||
|
||||
function schema_proc_mysql()
|
||||
{
|
||||
$this->m_sStatementTerminator = ';';
|
||||
}
|
||||
|
||||
/* Return a type suitable for DDL */
|
||||
function TranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = '';
|
||||
switch($sType)
|
||||
{
|
||||
case 'auto':
|
||||
$sTranslated = 'int(11) auto_increment not null';
|
||||
break;
|
||||
case 'blob':
|
||||
$sTranslated = 'blob';
|
||||
break;
|
||||
case 'bool':
|
||||
$sTranslated = 'tinyint(1)';
|
||||
break;
|
||||
case 'char':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = sprintf("char(%d)", $iPrecision);
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
$sTranslated = 'date';
|
||||
break;
|
||||
case 'decimal':
|
||||
$sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale);
|
||||
break;
|
||||
case 'float':
|
||||
switch($iPrecision)
|
||||
{
|
||||
case 4:
|
||||
$sTranslated = 'float';
|
||||
break;
|
||||
case 8:
|
||||
$sTranslated = 'double';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
switch($iPrecision)
|
||||
{
|
||||
case 2:
|
||||
$sTranslated = 'smallint';
|
||||
break;
|
||||
case 4:
|
||||
$sTranslated = 'int';
|
||||
break;
|
||||
case 8:
|
||||
$sTranslated = 'bigint';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'longtext':
|
||||
$sTranslated = 'longtext';
|
||||
break;
|
||||
case 'text':
|
||||
$sTranslated = 'text';
|
||||
break;
|
||||
case 'timestamp':
|
||||
$sTranslated = 'datetime';
|
||||
break;
|
||||
case 'varchar':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = sprintf("varchar(%d)", $iPrecision);
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function TranslateDefault($sDefault)
|
||||
{
|
||||
switch($sDefault)
|
||||
{
|
||||
case 'current_date':
|
||||
case 'current_timestamp':
|
||||
$sDefault = 'now';
|
||||
}
|
||||
return "'$sDefault'";
|
||||
}
|
||||
|
||||
/* Inverse of above, convert sql column types to array info */
|
||||
function rTranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = '';
|
||||
if($sType == 'int' || $sType == 'tinyint' || $sType == 'smallint' || $sType == 'bigint')
|
||||
{
|
||||
if($iPrecision > 8)
|
||||
{
|
||||
$iPrecision = 8;
|
||||
}
|
||||
elseif($iPrecision > 4)
|
||||
{
|
||||
$iPrecision = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iPrecision = 2;
|
||||
}
|
||||
}
|
||||
switch($sType)
|
||||
{
|
||||
case 'tinyint':
|
||||
case 'smallint':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 2";
|
||||
break;
|
||||
case 'int':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 4";
|
||||
break;
|
||||
case 'bigint':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 8";
|
||||
break;
|
||||
case 'char':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'char', 'precision' => $iPrecision";
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'decimal':
|
||||
$sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale";
|
||||
break;
|
||||
case 'float':
|
||||
case 'double':
|
||||
$sTranslated = "'type' => 'float', 'precision' => $iPrecision";
|
||||
break;
|
||||
case 'datetime':
|
||||
$sTranslated = "'type' => 'timestamp'";
|
||||
break;
|
||||
case 'enum':
|
||||
/* Here comes a nasty assumption */
|
||||
/* $sTranslated = "'type' => 'varchar', 'precision' => 255"; */
|
||||
$sTranslated = "'type' => 'varchar', 'precision' => $iPrecision";
|
||||
break;
|
||||
case 'varchar':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'varchar', 'precision' => $iPrecision";
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'longtext':
|
||||
case 'text':
|
||||
case 'blob':
|
||||
case 'date':
|
||||
$sTranslated = "'type' => '$sType'";
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function GetPKSQL($sFields)
|
||||
{
|
||||
return "PRIMARY KEY($sFields)";
|
||||
}
|
||||
|
||||
function GetUCSQL($sFields)
|
||||
{
|
||||
return "UNIQUE($sFields)";
|
||||
}
|
||||
|
||||
function GetIXSQL($sFields,&$append,$options=False)
|
||||
{
|
||||
$append = False;
|
||||
$type = 'INDEX';
|
||||
$length = '';
|
||||
if(strtoupper($options) == 'FULLTEXT')
|
||||
{
|
||||
$type = 'FULLTEXT';
|
||||
}
|
||||
if(is_numeric($options))
|
||||
{
|
||||
$length = "($options)";
|
||||
}
|
||||
return "$type($sFields $length)";
|
||||
}
|
||||
|
||||
function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn = '')
|
||||
{
|
||||
$sColumns = '';
|
||||
$this->pk = array();
|
||||
$this->fk = array();
|
||||
$this->ix = array();
|
||||
$this->uc = array();
|
||||
|
||||
/* Field, Type, Null, Key, Default, Extra */
|
||||
$oProc->m_odb->query("describe $sTableName");
|
||||
while($oProc->m_odb->next_record())
|
||||
{
|
||||
$type = $default = $null = $nullcomma = $prec = $scale = $ret = $colinfo = $scales = '';
|
||||
if($sColumns != '')
|
||||
{
|
||||
$sColumns .= ',';
|
||||
}
|
||||
$sColumns .= $oProc->m_odb->f(0);
|
||||
|
||||
/* The rest of this is used only for SQL->array */
|
||||
$colinfo = explode('(',$oProc->m_odb->f(1));
|
||||
$prec = ereg_replace('\).*','',$colinfo[1]);
|
||||
$scales = explode(',',$prec);
|
||||
|
||||
if($colinfo[0] == 'enum')
|
||||
{
|
||||
/* set prec to length of longest enum-value */
|
||||
for($prec=0; list($nul,$name) = @each($scales);)
|
||||
{
|
||||
if($prec < (strlen($name) - 2))
|
||||
{
|
||||
/* -2 as name is like "'name'" */
|
||||
$prec = (strlen($name) - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($scales[1])
|
||||
{
|
||||
$prec = $scales[0];
|
||||
$scale = $scales[1];
|
||||
}
|
||||
$type = $this->rTranslateType($colinfo[0], $prec, $scale);
|
||||
|
||||
if($oProc->m_odb->f(2) == 'YES')
|
||||
{
|
||||
$null = "'nullable' => True";
|
||||
}
|
||||
else
|
||||
{
|
||||
$null = "'nullable' => False";
|
||||
}
|
||||
if($oProc->m_odb->f(4) != '')
|
||||
{
|
||||
$default = "'default' => '".$oProc->m_odb->f(4)."'";
|
||||
$nullcomma = ',';
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = '';
|
||||
$nullcomma = '';
|
||||
}
|
||||
if($oProc->m_odb->f(5))
|
||||
{
|
||||
$type = "'type' => 'auto'";
|
||||
}
|
||||
$this->sCol[] = "\t\t\t\t'" . $oProc->m_odb->f(0)."' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n";
|
||||
/*
|
||||
if($oProc->m_odb->f(3) == 'PRI')
|
||||
{
|
||||
$this->pk[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
if($oProc->m_odb->f(3) == 'UNI')
|
||||
{
|
||||
$this->uc[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
// index over multiple columns
|
||||
if($oProc->m_odb->f(3) == 'MUL')
|
||||
{
|
||||
$this->ix[] = $oProc->m_odb->f(0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
$this->_GetIndices($oProc,$sTableName,$this->pk,$this->ix,$this->uc,$this->fk);
|
||||
|
||||
/* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */
|
||||
$this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function _GetIndices($oProc,$sTableName,&$aPk,&$aIx,&$aUc,&$aFk)
|
||||
{
|
||||
$aPk = $aIx = $aUc = $aFk = array();
|
||||
$seq = $ix = $uc = 0;
|
||||
|
||||
$oProc->m_odb->query("show index from $sTableName");
|
||||
while($oProc->m_odb->next_record())
|
||||
{
|
||||
if($seq >= $oProc->m_odb->f('Seq_in_index')) // new index started
|
||||
{
|
||||
$$type += 1;
|
||||
}
|
||||
if($oProc->m_odb->f('Key_name') == 'PRIMARY') // pk
|
||||
{
|
||||
$aPk[] = $oProc->m_odb->f('Column_name');
|
||||
$type = 'pk';
|
||||
}
|
||||
elseif($oProc->m_odb->f('Non_unique')) // ix
|
||||
{
|
||||
$aIx[$ix][] = $oProc->m_odb->f('Column_name');
|
||||
$type = 'ix';
|
||||
if($oProc->m_odb->f('Comment') == 'FULLTEXT')
|
||||
{
|
||||
$aIx[$ix]['options'] = array('mysql' => 'FULLTEXT');
|
||||
}
|
||||
elseif((int)$oProc->m_odb->f('Sub_part'))
|
||||
{
|
||||
$aIx[$ix]['options'] = array('mysql' => (int)$oProc->m_odb->f('Sub_part'));
|
||||
}
|
||||
}
|
||||
else // uc
|
||||
{
|
||||
$aUc[$uc][] = $oProc->m_odb->f('Column_name');
|
||||
$type = 'uc';
|
||||
}
|
||||
$seq = $oProc->m_odb->f('Seq_in_index');
|
||||
}
|
||||
//echo "Indices from $sTableName<pre>pk=".print_r($aPk,True)."\nix=".print_r($aIx,True)."\nuc=".print_r($aUc,True)."</pre>\n";
|
||||
}
|
||||
|
||||
function DropTable($oProc, &$aTables, $sTableName)
|
||||
{
|
||||
return !!($oProc->m_odb->query("DROP TABLE " . $sTableName));
|
||||
}
|
||||
|
||||
function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true)
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sTableName DROP COLUMN $sColumnName"));
|
||||
}
|
||||
|
||||
function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName)
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sOldTableName RENAME $sNewTableName"));
|
||||
}
|
||||
|
||||
function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true)
|
||||
{
|
||||
/*
|
||||
TODO: This really needs testing - it can affect primary keys, and other table-related objects
|
||||
like sequences and such
|
||||
*/
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameColumn: calling _GetFieldSQL for ' . $sNewColumnName; }
|
||||
if($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sNewColumnName], $sNewColumnSQL))
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sTableName CHANGE $sOldColumnName $sNewColumnName " . $sNewColumnSQL));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>AlterColumn: calling _GetFieldSQL for ' . $sNewColumnName; }
|
||||
if($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sColumnName], $sNewColumnSQL))
|
||||
{
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sTableName MODIFY $sColumnName " . $sNewColumnSQL));
|
||||
/* return !!($oProc->m_odb->query("ALTER TABLE $sTableName CHANGE $sColumnName $sColumnName " . $sNewColumnSQL)); */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef)
|
||||
{
|
||||
$oProc->_GetFieldSQL($aColumnDef, $sFieldSQL);
|
||||
$query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL";
|
||||
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
function GetSequenceSQL($sTableName, &$sSequenceSQL)
|
||||
{
|
||||
$sSequenceSQL = '';
|
||||
return true;
|
||||
}
|
||||
|
||||
function CreateTable($oProc, &$aTables, $sTableName, $aTableDef)
|
||||
{
|
||||
if($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL,$append_ix))
|
||||
{
|
||||
/* create sequence first since it will be needed for default */
|
||||
if($sSequenceSQL != '')
|
||||
{
|
||||
$oProc->m_odb->query($sSequenceSQL);
|
||||
}
|
||||
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL)";
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
748
phpgwapi/inc/class.schema_proc_pgsql.inc.php
Normal file
748
phpgwapi/inc/class.schema_proc_pgsql.inc.php
Normal file
@ -0,0 +1,748 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Setup *
|
||||
* http://www.egroupware.org *
|
||||
* SQL for table properties taken from phpPgAdmin Version 2.2.1 *
|
||||
* http://www.greatbridge.org/project/phppgadmin *
|
||||
* Copyright (C) 1999-2000 Dan Wilson <phpPgAdmin@acucore.com> *
|
||||
* Copyright (C) 1998-1999 Tobias Ratschiller <tobias@dnet.it> *
|
||||
* -------------------------------------------- *
|
||||
* This file written by Michael Dean<mdean@users.sourceforge.net> *
|
||||
* and Miles Lott<milosch@groupwhere.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class schema_proc_pgsql
|
||||
{
|
||||
var $m_sStatementTerminator;
|
||||
/* Following added to convert sql to array */
|
||||
var $sCol = array();
|
||||
var $pk = array();
|
||||
var $fk = array();
|
||||
var $ix = array();
|
||||
var $uc = array();
|
||||
|
||||
function schema_proc_pgsql()
|
||||
{
|
||||
$this->m_sStatementTerminator = ';';
|
||||
}
|
||||
|
||||
/* Return a type suitable for DDL */
|
||||
function TranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = $sType;
|
||||
switch($sType)
|
||||
{
|
||||
case 'auto':
|
||||
$sTranslated = 'int4';
|
||||
break;
|
||||
case 'blob':
|
||||
$sTranslated = 'bytea';
|
||||
break;
|
||||
case 'char':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = sprintf("char(%d)", $iPrecision);
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
case 'decimal':
|
||||
$sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale);
|
||||
break;
|
||||
case 'float':
|
||||
if($iPrecision == 4 || $iPrecision == 8)
|
||||
{
|
||||
$sTranslated = sprintf("float%d", $iPrecision);
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
if($iPrecision == 2 || $iPrecision == 4 || $iPrecision == 8)
|
||||
{
|
||||
$sTranslated = sprintf("int%d", $iPrecision);
|
||||
}
|
||||
break;
|
||||
case 'longtext':
|
||||
$sTranslated = 'text';
|
||||
break;
|
||||
case 'varchar':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = sprintf("varchar(%d)", $iPrecision);
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = 'text';
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function TranslateDefault($sDefault)
|
||||
{
|
||||
switch($sDefault)
|
||||
{
|
||||
case 'current_date':
|
||||
case 'current_timestamp':
|
||||
$sDefault = 'now';
|
||||
}
|
||||
return "'$sDefault'";
|
||||
}
|
||||
|
||||
/* Inverse of above, convert sql column types to array info */
|
||||
function rTranslateType($sType, $iPrecision = 0, $iScale = 0)
|
||||
{
|
||||
$sTranslated = '';
|
||||
switch($sType)
|
||||
{
|
||||
case 'serial':
|
||||
$sTranslated = "'type' => 'auto'";
|
||||
break;
|
||||
case 'int2':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 2";
|
||||
break;
|
||||
case 'int4':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 4";
|
||||
break;
|
||||
case 'int8':
|
||||
$sTranslated = "'type' => 'int', 'precision' => 8";
|
||||
break;
|
||||
case 'bpchar':
|
||||
case 'char':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'char', 'precision' => $iPrecision";
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'numeric':
|
||||
/* Borrowed from phpPgAdmin */
|
||||
$iPrecision = ($iScale >> 16) & 0xffff;
|
||||
$iScale = ($iScale - 4) & 0xffff;
|
||||
$sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale";
|
||||
break;
|
||||
case 'float':
|
||||
case 'float4':
|
||||
case 'float8':
|
||||
case 'double':
|
||||
$sTranslated = "'type' => 'float', 'precision' => $iPrecision";
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$sTranslated = "'type' => 'timestamp'";
|
||||
break;
|
||||
case 'varchar':
|
||||
if($iPrecision > 0 && $iPrecision < 256)
|
||||
{
|
||||
$sTranslated = "'type' => 'varchar', 'precision' => $iPrecision";
|
||||
}
|
||||
if($iPrecision > 255)
|
||||
{
|
||||
$sTranslated = "'type' => 'text'";
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
case 'blob':
|
||||
case 'date':
|
||||
case 'bool';
|
||||
$sTranslated = "'type' => '$sType'";
|
||||
break;
|
||||
}
|
||||
return $sTranslated;
|
||||
}
|
||||
|
||||
function GetPKSQL($sFields)
|
||||
{
|
||||
return "PRIMARY KEY($sFields)";
|
||||
}
|
||||
|
||||
function GetUCSQL($sFields)
|
||||
{
|
||||
return "UNIQUE($sFields)";
|
||||
}
|
||||
|
||||
function GetIXSQL($sFields,&$append,$options,$sTableName)
|
||||
{
|
||||
$append = True;
|
||||
$ixsql = '';
|
||||
$ixFields = str_replace(',','_',$sFields);
|
||||
$index = $sTableName . '_' . $ixFields . '_idx';
|
||||
return "CREATE INDEX $index ON $sTableName ($sFields);\n";
|
||||
}
|
||||
|
||||
function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn='', $sAlteredColumn='', $sAlteredColumnType='')
|
||||
{
|
||||
$sdb = $oProc->m_odb;
|
||||
$sdc = $oProc->m_odb;
|
||||
|
||||
$sColumns = '';
|
||||
$this->pk = array();
|
||||
$this->fk = array();
|
||||
$this->ix = array();
|
||||
$this->uc = array();
|
||||
|
||||
$query = "SELECT a.attname,a.attnum FROM pg_attribute a,pg_class b WHERE ";
|
||||
$query .= "b.oid=a.attrelid AND a.attnum>0 and b.relname='$sTableName'";
|
||||
if($sDropColumn != '')
|
||||
{
|
||||
$query .= " AND a.attname != '$sDropColumn'";
|
||||
}
|
||||
$query .= ' ORDER BY a.attnum';
|
||||
|
||||
// echo '_GetColumns: ' . $query;
|
||||
|
||||
$oProc->m_odb->query($query);
|
||||
while($oProc->m_odb->next_record())
|
||||
{
|
||||
if($sColumns != '')
|
||||
{
|
||||
$sColumns .= ',';
|
||||
}
|
||||
|
||||
$sFieldName = $oProc->m_odb->f(0);
|
||||
/* Failsafe in case the query still includes the column to be dropped */
|
||||
if($sFieldName != $sDropColumn)
|
||||
{
|
||||
$sColumns .= $sFieldName;
|
||||
}
|
||||
if($sAlteredColumn == $sFieldName && $sAlteredColumnType != '')
|
||||
{
|
||||
$sColumns .= '::' . $sAlteredColumnType;
|
||||
}
|
||||
}
|
||||
//$qdefault = "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c "
|
||||
// . "WHERE c.relname = $sTableName AND c.oid = d.adrelid AND d.adnum =" . $oProc->m_odb->f(1);
|
||||
$sql_get_fields = "
|
||||
SELECT
|
||||
a.attnum,
|
||||
a.attname AS field,
|
||||
t.typname AS type,
|
||||
a.attlen AS length,
|
||||
a.atttypmod AS lengthvar,
|
||||
a.attnotnull AS notnull
|
||||
FROM
|
||||
pg_class c,
|
||||
pg_attribute a,
|
||||
pg_type t
|
||||
WHERE
|
||||
c.relname = '$sTableName'
|
||||
and a.attnum > 0
|
||||
and a.attrelid = c.oid
|
||||
and a.atttypid = t.oid
|
||||
ORDER BY a.attnum";
|
||||
/* attnum field type length lengthvar notnull(Yes/No) */
|
||||
$sdb->query($sql_get_fields);
|
||||
while($sdb->next_record())
|
||||
{
|
||||
$colnum = $sdb->f(0);
|
||||
$colname = $sdb->f(1);
|
||||
|
||||
if($sdb->f(5) == 'Yes')
|
||||
{
|
||||
$null = "'nullable' => True";
|
||||
}
|
||||
else
|
||||
{
|
||||
$null = "'nullable' => False";
|
||||
}
|
||||
|
||||
if($sdb->f(2) == 'numeric')
|
||||
{
|
||||
$prec = $sdb->f(3);
|
||||
$scale = $sdb->f(4);
|
||||
}
|
||||
elseif($sdb->f(3) > 0)
|
||||
{
|
||||
$prec = $sdb->f(3);
|
||||
$scale = 0;
|
||||
}
|
||||
elseif($sdb->f(4) > 0)
|
||||
{
|
||||
$prec = $sdb->f(4) - 4;
|
||||
$scale = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$prec = 0;
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
$type = $this->rTranslateType($sdb->f(2), $prec, $scale);
|
||||
|
||||
$sql_get_default = "
|
||||
SELECT d.adsrc AS rowdefault
|
||||
FROM pg_attrdef d, pg_class c
|
||||
WHERE
|
||||
c.relname = '$sTableName' AND
|
||||
c.oid = d.adrelid AND
|
||||
d.adnum = $colnum
|
||||
";
|
||||
$sdc->query($sql_get_default);
|
||||
$sdc->next_record();
|
||||
if($sdc->f(0))
|
||||
{
|
||||
if(strstr($sdc->f(0),'nextval'))
|
||||
{
|
||||
$default = '';
|
||||
$nullcomma = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = "'default' => '".$sdc->f(0)."'";
|
||||
$nullcomma = ',';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = '';
|
||||
$nullcomma = '';
|
||||
}
|
||||
$default = str_replace("''","'",$default);
|
||||
|
||||
$this->sCol[] = "\t\t\t\t'" . $colname . "' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n";
|
||||
}
|
||||
$sql_pri_keys = "
|
||||
SELECT
|
||||
ic.relname AS index_name,
|
||||
bc.relname AS tab_name,
|
||||
ta.attname AS column_name,
|
||||
i.indisunique AS unique_key,
|
||||
i.indisprimary AS primary_key
|
||||
FROM
|
||||
pg_class bc,
|
||||
pg_class ic,
|
||||
pg_index i,
|
||||
pg_attribute ta,
|
||||
pg_attribute ia
|
||||
WHERE
|
||||
bc.oid = i.indrelid
|
||||
AND ic.oid = i.indexrelid
|
||||
AND ia.attrelid = i.indexrelid
|
||||
AND ta.attrelid = bc.oid
|
||||
AND bc.relname = '$sTableName'
|
||||
AND ta.attrelid = i.indrelid
|
||||
AND ta.attnum = i.indkey[ia.attnum-1]
|
||||
ORDER BY
|
||||
index_name, tab_name, column_name";
|
||||
$sdc->query($sql_pri_keys);
|
||||
while($sdc->next_record())
|
||||
{
|
||||
//echo '<br> checking: ' . $sdc->f(4);
|
||||
if($sdc->f(4) == 't')
|
||||
{
|
||||
$this->pk[] = $sdc->f(2);
|
||||
}
|
||||
if($sdc->f(3) == 't')
|
||||
{
|
||||
$this->uc[] = $sdc->f(2);
|
||||
}
|
||||
}
|
||||
$this->_GetIndices($oProc,$sTableName,$this->pk,$this->ix,$this->uc,$this->fk);
|
||||
|
||||
/* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */
|
||||
$this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n";
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
function _GetIndices($oProc,$sTableName,&$aPk,&$aIx,&$aUc,&$aFk)
|
||||
{
|
||||
/* Try not to die on errors with the query */
|
||||
$tmp = $oProc->Halt_On_Error;
|
||||
$oProc->Halt_On_Error = 'no';
|
||||
$aIx = array();
|
||||
/* This select excludes any indexes that are just base indexes for constraints. */
|
||||
|
||||
if(@$oProc->m_odb->db_version >= 7.3)
|
||||
{
|
||||
$sql = "SELECT pg_catalog.pg_get_indexdef(i.indexrelid) as pg_get_indexdef FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c.relname = '$sTableName' AND pg_catalog.pg_table_is_visible(c.oid) AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) WHERE d.classid = c2.tableoid AND d.objid = c2.oid AND d.deptype = 'i' AND c.contype IN ('u', 'p') ) ORDER BY c2.relname";
|
||||
$num = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT c2.relname, i.indisprimary, i.indisunique, pg_get_indexdef(i.indexrelid) FROM pg_class c, pg_class c2, pg_index i WHERE c.relname = '$sTableName' AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND NOT i.indisprimary AND NOT i.indisunique ORDER BY c2.relname";
|
||||
$num = 3;
|
||||
}
|
||||
|
||||
@$oProc->m_odb->query($sql);
|
||||
$oProc->m_odb->next_record();
|
||||
$indexfields = ereg_replace("^CREATE.+\(",'',$oProc->m_odb->f($num));
|
||||
$indexfields = ereg_replace("\)$",'',$indexfields);
|
||||
$aIx = explode(',',$indexfields);
|
||||
$i = 0;
|
||||
foreach($aIx as $ix)
|
||||
{
|
||||
$aIx[$i] = trim($ix);
|
||||
$i++;
|
||||
}
|
||||
/* Restore original value */
|
||||
$oProc->Halt_On_Error = $tmp;
|
||||
#echo "Indices from $sTableName<pre>pk=".print_r($aPk,True)."\nix=".print_r($aIx,True)."\nuc=".print_r($aUc,True)."</pre>\n";
|
||||
}
|
||||
|
||||
function _CopyAlteredTable($oProc, &$aTables, $sSource, $sDest)
|
||||
{
|
||||
$oDB = $oProc->m_odb;
|
||||
$oProc->m_odb->query("SELECT * FROM $sSource");
|
||||
while($oProc->m_odb->next_record())
|
||||
{
|
||||
$sSQL = "INSERT INTO $sDest (";
|
||||
$i=0;
|
||||
@reset($aTables[$sDest]['fd']);
|
||||
while(list($name,$arraydef) = each($aTables[$sDest]['fd']))
|
||||
{
|
||||
if($i > 0)
|
||||
{
|
||||
$sSQL .= ',';
|
||||
}
|
||||
|
||||
$sSQL .= $name;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$sSQL .= ') VALUES (';
|
||||
@reset($aTables[$sDest]['fd']);
|
||||
$i = 0;
|
||||
while(list($name,$arraydef) = each($aTables[$sDest]['fd']))
|
||||
{
|
||||
if($i > 0)
|
||||
{
|
||||
$sSQL .= ',';
|
||||
}
|
||||
|
||||
// !isset($arraydef['nullable']) means nullable !!!
|
||||
if($oProc->m_odb->f($name) == NULL && (!isset($arraydef['nullable']) || $arraydef['nullable']))
|
||||
{
|
||||
$sSQL .= 'NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $oProc->m_odb->f($name) != NULL ? $oProc->m_odb->f($name) : @$arraydef['default'];
|
||||
switch($arraydef['type'])
|
||||
{
|
||||
case 'blob':
|
||||
case 'char':
|
||||
case 'date':
|
||||
case 'text':
|
||||
case 'timestamp':
|
||||
case 'varchar':
|
||||
$sSQL .= "'" . $oProc->m_odb->db_addslashes($oProc->m_odb->f($name)) . "'";
|
||||
break;
|
||||
default:
|
||||
$sSQL .= (int)$oProc->m_odb->f($name);
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
$sSQL .= ')';
|
||||
|
||||
$oDB->query($sSQL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function GetSequenceForTable($oProc,$table,&$sSequenceName)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>GetSequenceForTable: ' . $table; }
|
||||
|
||||
$oProc->m_odb->query("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE 'seq_$table' AND relkind='S' ORDER BY relname",__LINE__,__FILE__);
|
||||
$oProc->m_odb->next_record();
|
||||
if($oProc->m_odb->f('relname'))
|
||||
{
|
||||
$sSequenceName = $oProc->m_odb->f('relname');
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function GetSequenceFieldForTable($oProc,$table,&$sField)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>GetSequenceFieldForTable: You rang?'; }
|
||||
|
||||
$oProc->m_odb->query("SELECT a.attname FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$table' AND c.oid=d.adrelid AND d.adsrc LIKE '%seq_$table%' AND a.attrelid=c.oid AND d.adnum=a.attnum");
|
||||
$oProc->m_odb->next_record();
|
||||
if($oProc->m_odb->f('attname'))
|
||||
{
|
||||
$sField = $oProc->m_odb->f('attname');
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function GetIndexesForTable($oProc,$table,&$sIndexNames)
|
||||
{
|
||||
$oProc->m_odb->query("SELECT a.attname FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$table' AND c.oid=d.adrelid AND d.adsrc LIKE '%$table%idx' AND a.attrelid=c.oid AND d.adnum=a.attnum");
|
||||
while($oProc->m_odb->next_record())
|
||||
{
|
||||
$sIndexNames[] = $oProc->m_odb->f('attname');
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function DropSequenceForTable($oProc,$table)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>DropSequenceForTable: ' . $table; }
|
||||
|
||||
$this->GetSequenceForTable($oProc,$table,$sSequenceName);
|
||||
if($sSequenceName)
|
||||
{
|
||||
$oProc->m_odb->query("DROP SEQUENCE " . $sSequenceName,__LINE__,__FILE__);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function DropIndexesForTable($oProc,$table)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>DropSequenceForTable: ' . $table; }
|
||||
|
||||
$this->GetIndexesForTable($oProc,$table,$sIndexNames);
|
||||
if(@is_array($sIndexNames))
|
||||
{
|
||||
foreach($sIndexNames as $null => $index)
|
||||
{
|
||||
$oProc->m_odb->query("DROP INDEX $index",__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function DropTable($oProc, &$aTables, $sTableName)
|
||||
{
|
||||
$this->DropSequenceForTable($oProc,$sTableName);
|
||||
|
||||
return $oProc->m_odb->query("DROP TABLE " . $sTableName) &&
|
||||
$this->DropSequenceForTable($oProc, $sTableName) &&
|
||||
$this->DropIndexesForTable($oProc, $sTableName);
|
||||
}
|
||||
|
||||
function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true)
|
||||
{
|
||||
if($GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '<br>DropColumn: table=' . $sTableName . ', column=' . $sColumnName;
|
||||
}
|
||||
|
||||
if($bCopyData)
|
||||
{
|
||||
$oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName");
|
||||
}
|
||||
|
||||
$this->DropTable($oProc, $aTables, $sTableName);
|
||||
|
||||
$oProc->_GetTableSQL($sTableName, $aNewTableDef, $sTableSQL, $sSequenceSQL,$append_ix);
|
||||
if($sSequenceSQL)
|
||||
{
|
||||
$oProc->m_odb->query($sSequenceSQL);
|
||||
}
|
||||
if($append_ix)
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL";
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL)";
|
||||
}
|
||||
if(!$bCopyData)
|
||||
{
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
$oProc->m_odb->query($query);
|
||||
$this->_GetColumns($oProc, $sTableName . '_tmp', $sColumns, $sColumnName);
|
||||
$query = "INSERT INTO $sTableName($sColumns) SELECT $sColumns FROM $sTableName" . '_tmp';
|
||||
$bRet = !!($oProc->m_odb->query($query));
|
||||
return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . '_tmp'));
|
||||
}
|
||||
|
||||
function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName)
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): Fetching old sequence for: ' . $sOldTableName; }
|
||||
$this->GetSequenceForTable($oProc,$sOldTableName,$sSequenceName);
|
||||
|
||||
if($GLOBALS['DEBUG']) { echo ' - ' . $sSequenceName; }
|
||||
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): Fetching sequence field for: ' . $sOldTableName; }
|
||||
$this->GetSequenceFieldForTable($oProc,$sOldTableName,$sField);
|
||||
|
||||
if($GLOBALS['DEBUG']) { echo ' - ' . $sField; }
|
||||
|
||||
if($sSequenceName)
|
||||
{
|
||||
$oProc->m_odb->query("SELECT last_value FROM seq_$sOldTableName",__LINE__,__FILE__);
|
||||
$oProc->m_odb->next_record();
|
||||
$lastval = $oProc->m_odb->f(0);
|
||||
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): dropping old sequence: ' . $sSequenceName . ' used on field: ' . $sField; }
|
||||
$this->DropSequenceForTable($oProc,$sOldTableName);
|
||||
|
||||
if($lastval)
|
||||
{
|
||||
$lastval = ' start ' . $lastval;
|
||||
}
|
||||
$this->GetSequenceSQL($sNewTableName,$sSequenceSQL);
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): Making new sequence using: ' . $sSequenceSQL . $lastval; }
|
||||
$oProc->m_odb->query($sSequenceSQL . $lastval,__LINE__,__FILE__);
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): Altering column default for: ' . $sField; }
|
||||
$oProc->m_odb->query("ALTER TABLE $sOldTableName ALTER $sField SET DEFAULT nextval('seq_" . $sNewTableName . "')",__LINE__,__FILE__);
|
||||
}
|
||||
// renameing existing indexes and primary keys
|
||||
$indexes = $oProc->m_odb->Link_ID->MetaIndexes($sOldTableName,True);
|
||||
if($GLOBALS['DEBUG']) { echo '<br>RenameTable(): Fetching indexes: '; _debug_array($indexes); }
|
||||
foreach($indexes as $name => $data)
|
||||
{
|
||||
$new_name = str_replace($sOldTableName,$sNewTableName,$name);
|
||||
$sql = "ALTER TABLE $name RENAME TO $new_name";
|
||||
if($GLOBALS['DEBUG']) { echo "<br>RenameTable(): Renaming the index '$name': $sql"; }
|
||||
$oProc->m_odb->query($sql);
|
||||
}
|
||||
return !!($oProc->m_odb->query("ALTER TABLE $sOldTableName RENAME TO $sNewTableName"));
|
||||
}
|
||||
|
||||
function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true)
|
||||
{
|
||||
/*
|
||||
This really needs testing - it can affect primary keys, and other table-related objects
|
||||
like sequences and such
|
||||
*/
|
||||
if($bCopyData)
|
||||
{
|
||||
$oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName");
|
||||
}
|
||||
|
||||
$this->DropTable($oProc, $aTables, $sTableName);
|
||||
|
||||
if(!$bCopyData)
|
||||
{
|
||||
return $this->CreateTable($oProc, $aTables, $sTableName, $oProc->m_aTables[$sTableName], false);
|
||||
}
|
||||
|
||||
$this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True);
|
||||
$this->_GetColumns($oProc, $sTableName . "_tmp", $sColumns);
|
||||
$query = "INSERT INTO $sTableName SELECT $sColumns FROM $sTableName" . "_tmp";
|
||||
|
||||
$bRet = !!($oProc->m_odb->query($query));
|
||||
return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . "_tmp"));
|
||||
}
|
||||
|
||||
function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true)
|
||||
{
|
||||
if($bCopyData)
|
||||
{
|
||||
$oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName");
|
||||
}
|
||||
|
||||
$this->DropTable($oProc, $aTables, $sTableName);
|
||||
|
||||
if(!$bCopyData)
|
||||
{
|
||||
return $this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True);
|
||||
}
|
||||
|
||||
$this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True);
|
||||
$this->_GetColumns($oProc, $sTableName . "_tmp", $sColumns, '', $sColumnName, $aColumnDef['type'] == 'auto' ? 'int4' : $aColumnDef['type']);
|
||||
|
||||
/*
|
||||
TODO: analyze the type of change and determine if this is used or _CopyAlteredTable
|
||||
this is a performance consideration only, _CopyAlteredTable should be safe
|
||||
$query = "INSERT INTO $sTableName SELECT $sColumns FROM $sTableName" . "_tmp";
|
||||
$bRet = !!($oProc->m_odb->query($query));
|
||||
*/
|
||||
|
||||
$bRet = $this->_CopyAlteredTable($oProc, $aTables, $sTableName . '_tmp', $sTableName);
|
||||
|
||||
return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . "_tmp"));
|
||||
}
|
||||
|
||||
function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef)
|
||||
{
|
||||
if(isset($aColumnDef['default'])) // pgsql cant add a colum with a default
|
||||
{
|
||||
$default = $aColumnDef['default'];
|
||||
unset($aColumnDef['default']);
|
||||
}
|
||||
if(isset($aColumnDef['nullable']) && !$aColumnDef['nullable']) // pgsql cant add a column not nullable
|
||||
{
|
||||
$notnull = !$aColumnDef['nullable'];
|
||||
unset($aColumnDef['nullable']);
|
||||
}
|
||||
$oProc->_GetFieldSQL($aColumnDef, $sFieldSQL);
|
||||
$query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL";
|
||||
|
||||
if(($Ok = !!($oProc->m_odb->query($query))) && isset($default))
|
||||
{
|
||||
$query = "ALTER TABLE $sTableName ALTER COLUMN $sColumnName SET DEFAULT '$default';\n";
|
||||
|
||||
$query .= "UPDATE $sTableName SET $sColumnName='$default';\n";
|
||||
|
||||
$Ok = !!($oProc->m_odb->query($query));
|
||||
|
||||
if($OK && $notnull)
|
||||
{
|
||||
// unfortunally this is pgSQL >= 7.3
|
||||
//$query .= "ALTER TABLE $sTableName ALTER COLUMN $sColumnName SET NOT NULL;\n";
|
||||
//$Ok = !!($oProc->m_odb->query($query));
|
||||
// so we do it the slow way
|
||||
AlterColumn($oProc, $aTables, $sTableName, $sColumnName, $aColumnDef);
|
||||
}
|
||||
}
|
||||
return $Ok;
|
||||
}
|
||||
|
||||
function UpdateSequence($oDb,$sTableName,$sColName)
|
||||
{
|
||||
$sql = "SELECT MAX($sColName) FROM $sTableName";
|
||||
|
||||
$oDb->query($sql,__LINE__,__FILE__);
|
||||
if ($oDb->next_record() && $oDb->f(0))
|
||||
{
|
||||
$sql = "SELECT setval('seq_$sTableName',".(1 + $oDb->f(0)).")";
|
||||
if($GLOBALS['DEBUG']) { echo "<br>Updating sequence 'seq_$sTableName' using: $sql"; }
|
||||
return $oDb->query($sql,__LINE__,__FILE__);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
function GetSequenceSQL($sTableName, &$sSequenceSQL)
|
||||
{
|
||||
$sSequenceSQL = sprintf("CREATE SEQUENCE seq_%s", $sTableName);
|
||||
return true;
|
||||
}
|
||||
|
||||
function CreateTable($oProc, $aTables, $sTableName, $aTableDef, $bCreateSequence = true)
|
||||
{
|
||||
if($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL,$append_ix))
|
||||
{
|
||||
/* create sequence first since it will be needed for default */
|
||||
if($bCreateSequence && $sSequenceSQL != '')
|
||||
{
|
||||
if($GLOBALS['DEBUG']) { echo '<br>Making sequence using: ' . $sSequenceSQL; }
|
||||
$oProc->m_odb->query($sSequenceSQL);
|
||||
}
|
||||
|
||||
if($append_ix)
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL";
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = "CREATE TABLE $sTableName ($sTableSQL)";
|
||||
}
|
||||
|
||||
return !!($oProc->m_odb->query($query));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
964
phpgwapi/inc/class.setup.inc.php
Normal file
964
phpgwapi/inc/class.setup.inc.php
Normal file
@ -0,0 +1,964 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Setup *
|
||||
* http://www.egroupware.org *
|
||||
* -------------------------------------------- *
|
||||
* This file written by Joseph Engo<jengo@phpgroupware.org> *
|
||||
* and Dan Kuykendall<seek3r@phpgroupware.org> *
|
||||
* and Mark Peters<skeeter@phpgroupware.org> *
|
||||
* and Miles Lott<milosch@groupwhere.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
class setup
|
||||
{
|
||||
var $db;
|
||||
var $oProc;
|
||||
|
||||
var $detection = '';
|
||||
var $process = '';
|
||||
var $lang = '';
|
||||
var $html = '';
|
||||
var $appreg = '';
|
||||
|
||||
/* table name vars */
|
||||
var $tbl_apps;
|
||||
var $tbl_config;
|
||||
var $tbl_hooks;
|
||||
|
||||
function setup($html=False, $translation=False)
|
||||
{
|
||||
$this->detection = CreateObject('phpgwapi.setup_detection');
|
||||
$this->process = CreateObject('phpgwapi.setup_process');
|
||||
$this->appreg = CreateObject('phpgwapi.app_registry');
|
||||
|
||||
/* The setup application needs these */
|
||||
$this->html = $html ? CreateObject('phpgwapi.setup_html') : '';
|
||||
$this->translation = $translation ? CreateObject('phpgwapi.setup_translation') : '';
|
||||
|
||||
// $this->tbl_apps = $this->get_apps_table_name();
|
||||
// $this->tbl_config = $this->get_config_table_name();
|
||||
$this->tbl_hooks = $this->get_hooks_table_name();
|
||||
}
|
||||
|
||||
/*!
|
||||
@function loaddb
|
||||
@abstract include api db class for the ConfigDomain and connect to the db
|
||||
*/
|
||||
function loaddb()
|
||||
{
|
||||
if(!isset($this->ConfigDomain) || empty($this->ConfigDomain))
|
||||
{
|
||||
$this->ConfigDomain = get_var('ConfigDomain',array('COOKIE','POST'),$_POST['FormDomain']);
|
||||
}
|
||||
|
||||
$GLOBALS['phpgw_info']['server']['db_type'] = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_type'];
|
||||
|
||||
if ($GLOBALS['phpgw_info']['server']['db_type'] == 'pgsql')
|
||||
{
|
||||
$GLOBALS['phpgw_info']['server']['db_persistent'] = False;
|
||||
}
|
||||
$this->db = CreateObject('phpgwapi.db');
|
||||
$this->db->Host = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_host'];
|
||||
$this->db->Port = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_port'];
|
||||
$this->db->Type = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_type'];
|
||||
$this->db->Database = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_name'];
|
||||
$this->db->User = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_user'];
|
||||
$this->db->Password = $GLOBALS['phpgw_domain'][$this->ConfigDomain]['db_pass'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the domain used for cookies
|
||||
*
|
||||
* @return string domain
|
||||
*/
|
||||
function set_cookiedomain()
|
||||
{
|
||||
$this->cookie_domain = $_SERVER['HTTP_HOST'];
|
||||
|
||||
// remove port from HTTP_HOST
|
||||
if (preg_match("/^(.*):(.*)$/",$this->cookie_domain,$arr))
|
||||
{
|
||||
$this->cookie_domain = $arr[1];
|
||||
}
|
||||
if (count(explode('.',$this->cookie_domain)) <= 1)
|
||||
{
|
||||
// setcookie dont likes domains without dots, leaving it empty, gets setcookie to fill the domain in
|
||||
$this->cookie_domain = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie
|
||||
*
|
||||
* @param string $cookiename name of cookie to be set
|
||||
* @param string $cookievalue value to be used, if unset cookie is cleared (optional)
|
||||
* @param int $cookietime when cookie should expire, 0 for session only (optional)
|
||||
*/
|
||||
function set_cookie($cookiename,$cookievalue='',$cookietime=0)
|
||||
{
|
||||
if(!isset($this->cookie_domain) || !$this->cookie_domain)
|
||||
{
|
||||
$this->set_cookiedomain();
|
||||
}
|
||||
setcookie($cookiename,$cookievalue,$cookietime,'/',$this->cookie_domain);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function auth
|
||||
@abstract authenticate the setup user
|
||||
@param $auth_type ???
|
||||
*/
|
||||
function auth($auth_type='Config')
|
||||
{
|
||||
#phpinfo();
|
||||
$FormLogout = get_var('FormLogout', array('GET','POST'));
|
||||
if(!$FormLogout)
|
||||
{
|
||||
$ConfigLogin = get_var('ConfigLogin', array('POST'));
|
||||
$HeaderLogin = get_var('HeaderLogin', array('POST'));
|
||||
$FormDomain = get_var('FormDomain', array('POST'));
|
||||
$FormUser = get_var('FormUser', array('POST'));
|
||||
$FormPW = get_var('FormPW', array('POST'));
|
||||
|
||||
$this->ConfigDomain = get_var('ConfigDomain',array('POST','COOKIE'));
|
||||
$ConfigUser = get_var('ConfigUser', array('POST','COOKIE'));
|
||||
$ConfigPW = get_var('ConfigPW', array('POST','COOKIE'));
|
||||
$HeaderUser = get_var('HeaderUser', array('POST','COOKIE'));
|
||||
$HeaderPW = get_var('HeaderPW', array('POST','COOKIE'));
|
||||
$ConfigLang = get_var('ConfigLang', array('POST','COOKIE'));
|
||||
|
||||
/* Setup defaults to aid in header upgrade to version 1.26.
|
||||
* This was the first version to include the following values.
|
||||
*/
|
||||
if(!@isset($GLOBALS['phpgw_domain'][$FormDomain]['config_user']) && isset($GLOBALS['phpgw_domain'][$FormDomain]))
|
||||
{
|
||||
@$GLOBALS['phpgw_domain'][$FormDomain]['config_user'] = 'admin';
|
||||
}
|
||||
if(!@isset($GLOBALS['phpgw_info']['server']['header_admin_user']))
|
||||
{
|
||||
@$GLOBALS['phpgw_info']['server']['header_admin_user'] = 'admin';
|
||||
}
|
||||
}
|
||||
|
||||
$remoteip = $_SERVER['REMOTE_ADDR'];
|
||||
if(!empty($remoteip) && !$this->checkip($remoteip)) { return False; }
|
||||
|
||||
/* If FormLogout is set, simply invalidate the cookies (LOGOUT) */
|
||||
switch(strtolower($FormLogout))
|
||||
{
|
||||
case 'config':
|
||||
/* config logout */
|
||||
$expire = time() - 86400;
|
||||
$this->set_cookie('ConfigUser','',$expire,'/');
|
||||
$this->set_cookie('ConfigPW','',$expire,'/');
|
||||
$this->set_cookie('ConfigDomain','',$expire,'/');
|
||||
$this->set_cookie('ConfigLang','',$expire,'/');
|
||||
$GLOBALS['phpgw_info']['setup']['LastDomain'] = $_COOKIE['ConfigDomain'];
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = lang('You have successfully logged out');
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = '';
|
||||
return False;
|
||||
case 'header':
|
||||
/* header admin logout */
|
||||
$expire = time() - 86400;
|
||||
$this->set_cookie('HeaderUser','',$expire,'/');
|
||||
$this->set_cookie('HeaderPW','',$expire,'/');
|
||||
$this->set_cookie('ConfigLang','',$expire,'/');
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = lang('You have successfully logged out');
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = '';
|
||||
return False;
|
||||
}
|
||||
|
||||
/* We get here if FormLogout is not set (LOGIN or subsequent pages) */
|
||||
/* Expire login if idle for 20 minutes. The cookies are updated on every page load. */
|
||||
$expire = (int)(time() + (1200*9));
|
||||
|
||||
switch(strtolower($auth_type))
|
||||
{
|
||||
case 'header':
|
||||
if(!empty($HeaderLogin))
|
||||
{
|
||||
/* header admin login */
|
||||
/* New test is md5, cleartext version is for header < 1.26 */
|
||||
if ($this->check_auth($FormUser,$FormPW,$GLOBALS['phpgw_info']['server']['header_admin_user'],
|
||||
$GLOBALS['phpgw_info']['server']['header_admin_password']))
|
||||
{
|
||||
$this->set_cookie('HeaderUser',"$FormUser",$expire,'/');
|
||||
$this->set_cookie('HeaderPW',"$FormPW",$expire,'/');
|
||||
$this->set_cookie('ConfigLang',"$ConfigLang",$expire,'/');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = lang('Invalid password');
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = '';
|
||||
return False;
|
||||
}
|
||||
}
|
||||
elseif(!empty($HeaderPW) && $auth_type == 'Header')
|
||||
{
|
||||
// Returning after login to header admin
|
||||
/* New test is md5, cleartext version is for header < 1.26 */
|
||||
if ($this->check_auth($HeaderUser,$HeaderPW,$GLOBALS['phpgw_info']['server']['header_admin_user'],
|
||||
$GLOBALS['phpgw_info']['server']['header_admin_password']))
|
||||
{
|
||||
$this->set_cookie('HeaderUser',"$HeaderUser",$expire,'/');
|
||||
$this->set_cookie('HeaderPW',"$HeaderPW",$expire,'/');
|
||||
$this->set_cookie('ConfigLang',"$ConfigLang",$expire,'/');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = lang('Invalid password');
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = '';
|
||||
return False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'config':
|
||||
if(!empty($ConfigLogin))
|
||||
{
|
||||
/* config login */
|
||||
/* New test is md5, cleartext version is for header < 1.26 */
|
||||
if (isset($GLOBALS['phpgw_domain'][$FormDomain]) &&
|
||||
$this->check_auth($FormUser,$FormPW,@$GLOBALS['phpgw_domain'][$FormDomain]['config_user'],
|
||||
@$GLOBALS['phpgw_domain'][$FormDomain]['config_passwd']))
|
||||
{
|
||||
$this->set_cookie('ConfigUser',"$FormUser",$expire,'/');
|
||||
$this->set_cookie('ConfigPW',"$FormPW",$expire,'/');
|
||||
$this->set_cookie('ConfigDomain',"$FormDomain",$expire,'/');
|
||||
/* Set this now since the cookie will not be available until the next page load */
|
||||
$this->ConfigDomain = "$FormDomain";
|
||||
$this->set_cookie('ConfigLang',"$ConfigLang",$expire,'/');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = lang('Invalid password');
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = '';
|
||||
return False;
|
||||
}
|
||||
}
|
||||
elseif(!empty($ConfigPW))
|
||||
{
|
||||
// Returning after login to config
|
||||
/* New test is md5, cleartext version is for header < 1.26 */
|
||||
if ($this->check_auth($ConfigUser,$ConfigPW,@$GLOBALS['phpgw_domain'][$this->ConfigDomain]['config_user'],
|
||||
@$GLOBALS['phpgw_domain'][$this->ConfigDomain]['config_passwd']))
|
||||
{
|
||||
$this->set_cookie('ConfigUser',"$ConfigUser",$expire,'/');
|
||||
$this->set_cookie('ConfigPW',"$ConfigPW",$expire,'/');
|
||||
$this->set_cookie('ConfigDomain',$this->ConfigDomain,$expire,'/');
|
||||
$this->set_cookie('ConfigLang',"$ConfigLang",$expire,'/');
|
||||
return True;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = lang('Invalid password');
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = '';
|
||||
return False;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
// returns True if user and pw match, if conf_pw is a md5 ONLY compare with md5($pw) and NOT the plaintext !!!
|
||||
function check_auth($user,$pw,$conf_user,$conf_pw)
|
||||
{
|
||||
if ($user != $conf_user)
|
||||
{
|
||||
return False; // wrong username
|
||||
}
|
||||
if (preg_match('/^[0-9a-f]{32}$/',$conf_pw)) // $conf_pw is a md5
|
||||
{
|
||||
$pw = md5($pw);
|
||||
}
|
||||
return $pw == $conf_pw;
|
||||
}
|
||||
|
||||
function checkip($remoteip='')
|
||||
{
|
||||
//echo "<p>setup::checkip($remoteip) against setup_acl='".$GLOBALS['phpgw_info']['server']['setup_acl']."'</p>\n";
|
||||
$allowed_ips = explode(',',@$GLOBALS['phpgw_info']['server']['setup_acl']);
|
||||
if(empty($GLOBALS['phpgw_info']['server']['setup_acl']) || !is_array($allowed_ips))
|
||||
{
|
||||
return True; // no test
|
||||
}
|
||||
$remotes = explode('.',$remoteip);
|
||||
foreach($allowed_ips as $value)
|
||||
{
|
||||
if (!preg_match('/^[0-9.]+$/',$value))
|
||||
{
|
||||
$value = gethostbyname($was=$value); // resolve domain-name, eg. a dyndns account
|
||||
//echo "resolving '$was' to '$value'<br>\n";
|
||||
}
|
||||
$values = explode('.',$value);
|
||||
for($i = 0; $i < count($values); ++$i)
|
||||
{
|
||||
if ((int) $values[$i] != (int) $remotes[$i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($i == count($values))
|
||||
{
|
||||
return True; // match
|
||||
}
|
||||
}
|
||||
$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = '';
|
||||
$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = lang('Invalid IP address');
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function get_major
|
||||
@abstract Return X.X.X major version from X.X.X.X versionstring
|
||||
@param $
|
||||
*/
|
||||
function get_major($versionstring)
|
||||
{
|
||||
if(!$versionstring)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
$version = str_replace('pre','.',$versionstring);
|
||||
$varray = explode('.',$version);
|
||||
$major = implode('.',array($varray[0],$varray[1],$varray[2]));
|
||||
|
||||
return $major;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function clear_session_cache
|
||||
@abstract Clear system/user level cache so as to have it rebuilt with the next access
|
||||
@param None
|
||||
*/
|
||||
function clear_session_cache()
|
||||
{
|
||||
$tables = Array();
|
||||
$tablenames = $this->db->table_names();
|
||||
foreach($tablenames as $key => $val)
|
||||
{
|
||||
$tables[] = $val['table_name'];
|
||||
}
|
||||
if(in_array('phpgw_app_sessions',$tables))
|
||||
{
|
||||
$this->db->lock(array('phpgw_app_sessions'));
|
||||
@$this->db->query("DELETE FROM phpgw_app_sessions WHERE sessionid = '0' and loginid = '0' and app = 'phpgwapi' and location = 'config'",__LINE__,__FILE__);
|
||||
@$this->db->query("DELETE FROM phpgw_app_sessions WHERE app = 'phpgwapi' and location = 'phpgw_info_cache'",__LINE__,__FILE__);
|
||||
$this->db->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function register_app
|
||||
@abstract Add an application to the phpgw_applications table
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
@param $enable optional, set to True/False to override setup.inc.php setting
|
||||
*/
|
||||
function register_app($appname,$enable=99)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($enable==99)
|
||||
{
|
||||
$enable = $setup_info[$appname]['enable'];
|
||||
}
|
||||
$enable = (int)$enable;
|
||||
|
||||
/*
|
||||
Use old applications table if the currentver is less than 0.9.10pre8,
|
||||
but not if the currentver = '', which probably means new install.
|
||||
*/
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
$appstbl = 'applications';
|
||||
}
|
||||
else
|
||||
{
|
||||
$appstbl = 'phpgw_applications';
|
||||
}
|
||||
|
||||
if($GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '<br>register_app(): ' . $appname . ', version: ' . $setup_info[$appname]['version'] . ', table: ' . $appstbl . '<br>';
|
||||
// _debug_array($setup_info[$appname]);
|
||||
}
|
||||
|
||||
if($setup_info[$appname]['version'])
|
||||
{
|
||||
if($setup_info[$appname]['tables'])
|
||||
{
|
||||
$tables = implode(',',$setup_info[$appname]['tables']);
|
||||
}
|
||||
if ($setup_info[$appname]['tables_use_prefix'] == True)
|
||||
{
|
||||
echo $setup_info[$appname]['name'] . ' uses tables_use_prefix, storing '
|
||||
. $setup_info[$appname]['tables_prefix']
|
||||
. ' as prefix for ' . $setup_info[$appname]['name'] . " tables\n";
|
||||
|
||||
$sql = "INSERT INTO phpgw_config (config_app,config_name,config_value) "
|
||||
."VALUES ('".$setup_info[$appname]['name']."','"
|
||||
.$appname."_tables_prefix','".$setup_info[$appname]['tables_prefix']."');";
|
||||
$this->db->query($sql,__LINE__,__FILE__);
|
||||
}
|
||||
$this->db->query("INSERT INTO $appstbl "
|
||||
. "(app_name,app_enabled,app_order,app_tables,app_version) "
|
||||
. "VALUES ("
|
||||
. "'" . $setup_info[$appname]['name'] . "',"
|
||||
. $enable . ","
|
||||
. (int)$setup_info[$appname]['app_order'] . ","
|
||||
. "'" . $tables . "',"
|
||||
. "'" . $setup_info[$appname]['version'] . "');"
|
||||
);
|
||||
$this->clear_session_cache();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function app_registered
|
||||
@abstract Check if an application has info in the db
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
@param $enabled optional, set to False to not enable this app
|
||||
*/
|
||||
function app_registered($appname)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
$appstbl = 'applications';
|
||||
}
|
||||
else
|
||||
{
|
||||
$appstbl = 'phpgw_applications';
|
||||
}
|
||||
|
||||
if(@$GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '<br>app_registered(): checking ' . $appname . ', table: ' . $appstbl;
|
||||
// _debug_array($setup_info[$appname]);
|
||||
}
|
||||
|
||||
$this->db->query("SELECT COUNT(app_name) FROM $appstbl WHERE app_name='".$appname."'");
|
||||
$this->db->next_record();
|
||||
if($this->db->f(0))
|
||||
{
|
||||
if(@$GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '... app previously registered.';
|
||||
}
|
||||
return True;
|
||||
}
|
||||
if(@$GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '... app not registered';
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function update_app
|
||||
@abstract Update application info in the db
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
@param $enabled optional, set to False to not enable this app
|
||||
*/
|
||||
function update_app($appname)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
$appstbl = 'applications';
|
||||
}
|
||||
else
|
||||
{
|
||||
$appstbl = 'phpgw_applications';
|
||||
}
|
||||
|
||||
if($GLOBALS['DEBUG'])
|
||||
{
|
||||
echo '<br>update_app(): ' . $appname . ', version: ' . $setup_info[$appname]['currentver'] . ', table: ' . $appstbl . '<br>';
|
||||
// _debug_array($setup_info[$appname]);
|
||||
}
|
||||
|
||||
$this->db->query("SELECT COUNT(app_name) FROM $appstbl WHERE app_name='".$appname."'");
|
||||
$this->db->next_record();
|
||||
if(!$this->db->f(0))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($setup_info[$appname]['version'])
|
||||
{
|
||||
//echo '<br>' . $setup_info[$appname]['version'];
|
||||
if($setup_info[$appname]['tables'])
|
||||
{
|
||||
$tables = implode(',',$setup_info[$appname]['tables']);
|
||||
}
|
||||
|
||||
$sql = "UPDATE $appstbl "
|
||||
. "SET app_name='" . $setup_info[$appname]['name'] . "',"
|
||||
. " app_enabled=" . (int)$setup_info[$appname]['enable'] . ","
|
||||
. " app_order=" . (int)$setup_info[$appname]['app_order'] . ","
|
||||
. " app_tables='" . $tables . "',"
|
||||
. " app_version='" . $setup_info[$appname]['version'] . "'"
|
||||
. " WHERE app_name='" . $appname . "'";
|
||||
//echo $sql; exit;
|
||||
|
||||
$this->db->query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function update_app_version
|
||||
@abstract Update application version in applications table, post upgrade
|
||||
@param $setup_info Array of application information (multiple apps or single)
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
@param $tableschanged ???
|
||||
*/
|
||||
function update_app_version($setup_info, $appname, $tableschanged = True)
|
||||
{
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
$appstbl = 'applications';
|
||||
}
|
||||
else
|
||||
{
|
||||
$appstbl = 'phpgw_applications';
|
||||
}
|
||||
|
||||
if($tableschanged == True)
|
||||
{
|
||||
$GLOBALS['phpgw_info']['setup']['tableschanged'] = True;
|
||||
}
|
||||
if($setup_info[$appname]['currentver'])
|
||||
{
|
||||
$this->db->query("UPDATE $appstbl SET app_version='" . $setup_info[$appname]['currentver'] . "' WHERE app_name='".$appname."'");
|
||||
}
|
||||
return $setup_info;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function deregister_app
|
||||
@abstract de-Register an application
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
*/
|
||||
function deregister_app($appname)
|
||||
{
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
$appstbl = 'applications';
|
||||
}
|
||||
else
|
||||
{
|
||||
$appstbl = 'phpgw_applications';
|
||||
}
|
||||
|
||||
//echo 'DELETING application: ' . $appname;
|
||||
$this->db->query("DELETE FROM $appstbl WHERE app_name='". $appname ."'");
|
||||
$this->clear_session_cache();
|
||||
}
|
||||
|
||||
/*!
|
||||
@function register_hooks
|
||||
@abstract Register an application's hooks
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
*/
|
||||
function register_hooks($appname)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.8pre5') && ($setup_info['phpgwapi']['currentver'] != ''))
|
||||
{
|
||||
/* No phpgw_hooks table yet. */
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!is_object($this->hooks))
|
||||
{
|
||||
$this->hooks = CreateObject('phpgwapi.hooks',$this->db);
|
||||
}
|
||||
$this->hooks->register_hooks($appname,$setup_info[$appname]['hooks']);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function update_hooks
|
||||
@abstract Update an application's hooks
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
*/
|
||||
function update_hooks($appname)
|
||||
{
|
||||
$this->register_hooks($appname);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function deregister_hooks
|
||||
@abstract de-Register an application's hooks
|
||||
@param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
*/
|
||||
function deregister_hooks($appname)
|
||||
{
|
||||
if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.8pre5'))
|
||||
{
|
||||
/* No phpgw_hooks table yet. */
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
//echo "DELETING hooks for: " . $setup_info[$appname]['name'];
|
||||
if (!is_object($this->hooks))
|
||||
{
|
||||
$this->hooks = CreateObject('phpgwapi.hooks',$this->db);
|
||||
}
|
||||
$this->hooks->register_hooks($appname);
|
||||
}
|
||||
|
||||
/*!
|
||||
@function hook
|
||||
@abstract call the hooks for a single application
|
||||
@param $location hook location - required
|
||||
@param $appname application name - optional
|
||||
*/
|
||||
function hook($location, $appname='')
|
||||
{
|
||||
if (!is_object($this->hooks))
|
||||
{
|
||||
$this->hooks = CreateObject('phpgwapi.hooks',$this->db);
|
||||
}
|
||||
return $this->hooks->single($location,$appname,True,True);
|
||||
}
|
||||
|
||||
/*
|
||||
@function alessthanb
|
||||
@abstract phpgw version checking, is param 1 < param 2 in phpgw versionspeak?
|
||||
@param $a phpgw version number to check if less than $b
|
||||
@param $b phpgw version number to check $a against
|
||||
#return True if $a < $b
|
||||
*/
|
||||
function alessthanb($a,$b,$DEBUG=False)
|
||||
{
|
||||
$num = array('1st','2nd','3rd','4th');
|
||||
|
||||
if($DEBUG)
|
||||
{
|
||||
echo'<br>Input values: '
|
||||
. 'A="'.$a.'", B="'.$b.'"';
|
||||
}
|
||||
$newa = str_replace('pre','.',$a);
|
||||
$newb = str_replace('pre','.',$b);
|
||||
$testa = explode('.',$newa);
|
||||
if(@$testa[1] == '')
|
||||
{
|
||||
$testa[1] = 0;
|
||||
}
|
||||
|
||||
$testb = explode('.',$newb);
|
||||
if(@$testb[1] == '')
|
||||
{
|
||||
$testb[1] = 0;
|
||||
}
|
||||
if(@$testb[3] == '')
|
||||
{
|
||||
$testb[3] = 0;
|
||||
}
|
||||
$less = 0;
|
||||
|
||||
for($i=0;$i<count($testa);$i++)
|
||||
{
|
||||
if($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is less than ' . (int)$testb[$i] . ' ...'; }
|
||||
if((int)$testa[$i] < (int)$testb[$i])
|
||||
{
|
||||
if ($DEBUG) { echo ' yes.'; }
|
||||
$less++;
|
||||
if($i<3)
|
||||
{
|
||||
/* Ensure that this is definitely smaller */
|
||||
if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
|
||||
$less = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
elseif((int)$testa[$i] > (int)$testb[$i])
|
||||
{
|
||||
if($DEBUG) { echo ' no.'; }
|
||||
$less--;
|
||||
if($i<2)
|
||||
{
|
||||
/* Ensure that this is definitely greater */
|
||||
if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
|
||||
$less = -5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($DEBUG) { echo ' no, they are equal or of different length.'; }
|
||||
// makes sure eg. '1.0.0' is counted less the '1.0.0.xxx' !
|
||||
$less = count($testa) < count($testb) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
|
||||
if($less>0)
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is less than B'; }
|
||||
return True;
|
||||
}
|
||||
elseif($less<0)
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is greater than B'; }
|
||||
return False;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is equal to B'; }
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function amorethanb
|
||||
@abstract phpgw version checking, is param 1 > param 2 in phpgw versionspeak?
|
||||
@param $a phpgw version number to check if more than $b
|
||||
@param $b phpgw version number to check $a against
|
||||
#return True if $a < $b
|
||||
*/
|
||||
function amorethanb($a,$b,$DEBUG=False)
|
||||
{
|
||||
$num = array('1st','2nd','3rd','4th');
|
||||
|
||||
if($DEBUG)
|
||||
{
|
||||
echo'<br>Input values: '
|
||||
. 'A="'.$a.'", B="'.$b.'"';
|
||||
}
|
||||
$newa = str_replace('pre','.',$a);
|
||||
$newb = str_replace('pre','.',$b);
|
||||
$testa = explode('.',$newa);
|
||||
if($testa[3] == '')
|
||||
{
|
||||
$testa[3] = 0;
|
||||
}
|
||||
$testb = explode('.',$newb);
|
||||
if($testb[3] == '')
|
||||
{
|
||||
$testb[3] = 0;
|
||||
}
|
||||
$less = 0;
|
||||
|
||||
for($i=0;$i<count($testa);$i++)
|
||||
{
|
||||
if($DEBUG) { echo'<br>Checking if '. (int)$testa[$i] . ' is more than ' . (int)$testb[$i] . ' ...'; }
|
||||
if((int)$testa[$i] > (int)$testb[$i])
|
||||
{
|
||||
if($DEBUG) { echo ' yes.'; }
|
||||
$less++;
|
||||
if($i<3)
|
||||
{
|
||||
/* Ensure that this is definitely greater */
|
||||
if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely greater than B."; }
|
||||
$less = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
elseif((int)$testa[$i] < (int)$testb[$i])
|
||||
{
|
||||
if($DEBUG) { echo ' no.'; }
|
||||
$less--;
|
||||
if($i<2)
|
||||
{
|
||||
/* Ensure that this is definitely smaller */
|
||||
if($DEBUG) { echo" This is the $num[$i] octet, so A is definitely less than B."; }
|
||||
$less = -5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($DEBUG) { echo ' no, they are equal.'; }
|
||||
$less = 0;
|
||||
}
|
||||
}
|
||||
if($DEBUG) { echo '<br>Check value is: "'.$less.'"'; }
|
||||
if($less>0)
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is greater than B'; }
|
||||
return True;
|
||||
}
|
||||
elseif($less<0)
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is less than B'; }
|
||||
return False;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($DEBUG) { echo '<br>A is equal to B'; }
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
function get_hooks_table_name()
|
||||
{
|
||||
if(@$this->alessthanb($GLOBALS['setup_info']['phpgwapi']['currentver'],'0.9.8pre5') &&
|
||||
@$GLOBALS['setup_info']['phpgwapi']['currentver'] != '')
|
||||
{
|
||||
/* No phpgw_hooks table yet. */
|
||||
return False;
|
||||
}
|
||||
return 'phpgw_hooks';
|
||||
}
|
||||
|
||||
function setup_account_object()
|
||||
{
|
||||
if (!is_object($GLOBALS['phpgw']->accounts))
|
||||
{
|
||||
if (!is_object($this->db))
|
||||
{
|
||||
$this->loaddb();
|
||||
}
|
||||
/* Load up some configured values */
|
||||
$this->db->query("SELECT config_name,config_value FROM phpgw_config "
|
||||
. "WHERE config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%'",__LINE__,__FILE__);
|
||||
while($this->db->next_record())
|
||||
{
|
||||
$GLOBALS['phpgw_info']['server'][$this->db->f('config_name')] = $this->db->f('config_value');
|
||||
}
|
||||
if (!is_object($GLOBALS['phpgw']))
|
||||
{
|
||||
$GLOBALS['phpgw'] = CreateObject('phpgwapi.phpgw');
|
||||
}
|
||||
copyobj($this->db,$GLOBALS['phpgw']->db);
|
||||
$GLOBALS['phpgw']->common = CreateObject('phpgwapi.common');
|
||||
$GLOBALS['phpgw']->accounts = CreateObject('phpgwapi.accounts');
|
||||
|
||||
if(($GLOBALS['phpgw_info']['server']['account_repository'] == 'ldap') &&
|
||||
!$GLOBALS['phpgw']->accounts->ds)
|
||||
{
|
||||
printf("<b>Error: Error connecting to LDAP server %s!</b><br>",$GLOBALS['phpgw_info']['server']['ldap_host']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@function add_account
|
||||
@abstract add an user account or a user group
|
||||
@param username string alphanumerical username or groupname (account_lid)
|
||||
@param first, last string first / last name
|
||||
@param $passwd string cleartext pw
|
||||
@param $group string/boolean Groupname for users primary group or False for a group, default 'Default'
|
||||
@param $changepw boolean user has right to change pw, default False
|
||||
@returns the numerical user-id
|
||||
@note if the $username already exists, only the id is returned, no new user / group gets created
|
||||
*/
|
||||
function add_account($username,$first,$last,$passwd,$group='default',$changepw=False)
|
||||
{
|
||||
$this->setup_account_object();
|
||||
|
||||
$groupid = $group ? $GLOBALS['phpgw']->accounts->name2id($group) : False;
|
||||
|
||||
if(!($accountid = $GLOBALS['phpgw']->accounts->name2id($username)))
|
||||
{
|
||||
$accountid = $accountid ? $accountid : $GLOBALS['phpgw']->accounts->create(array(
|
||||
'account_type' => $group ? 'u' : 'g',
|
||||
'account_lid' => $username,
|
||||
'account_passwd' => $passwd,
|
||||
'account_firstname' => $first,
|
||||
'account_lastname' => $last,
|
||||
'account_status' => 'A',
|
||||
'account_primary_group' => $groupid,
|
||||
'account_expires' => -1
|
||||
));
|
||||
}
|
||||
$accountid = (int)$accountid;
|
||||
if($groupid)
|
||||
{
|
||||
$this->add_acl('phpgw_group',(int)$groupid,$accountid);
|
||||
}
|
||||
$this->add_acl('preferences','changepassword',$accountid,(int)$changepw);
|
||||
|
||||
return $accountid;
|
||||
}
|
||||
|
||||
/*!
|
||||
@function add_acl
|
||||
@abstract Add ACL rights
|
||||
@param $app string/array with app-names
|
||||
@param $locations string eg. run
|
||||
@param $account int/string accountid or account_lid
|
||||
@param $rights int rights to set, default 1
|
||||
*/
|
||||
function add_acl($apps,$location,$account,$rights=1)
|
||||
{
|
||||
if (!is_int($account))
|
||||
{
|
||||
$this->setup_account_object();
|
||||
$account = $GLOBALS['phpgw']->accounts->name2id($account);
|
||||
}
|
||||
$rights = (int)$rights;
|
||||
if(!is_object($this->db))
|
||||
{
|
||||
$this->loaddb();
|
||||
}
|
||||
|
||||
if(!is_array($apps))
|
||||
{
|
||||
$apps = array($apps);
|
||||
}
|
||||
foreach($apps as $app)
|
||||
{
|
||||
$this->db->query("DELETE FROM phpgw_acl WHERE acl_appname='$app' AND acl_location='$location' AND acl_account=$account");
|
||||
if ($rights)
|
||||
{
|
||||
$this->db->query("INSERT INTO phpgw_acl(acl_appname,acl_location,acl_account,acl_rights) VALUES('$app','$location',$account,$rights)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -426,7 +426,7 @@
|
||||
|
||||
// explode with "\t" and removing "\n" with str_replace, needed to work with mbstring.overload=7
|
||||
list($message_id,$app_name,,$content) = explode("\t",$line);
|
||||
$content=str_replace("\n",'',$content);
|
||||
$content=str_replace(array("\n","\r"),'',$content);
|
||||
$message_id = substr(strtolower(chop($message_id)),0,MAX_MESSAGE_ID_LENGTH);
|
||||
$app_name = chop($app_name);
|
||||
$raw[$app_name][$message_id] = $content;
|
||||
|
1370
phpgwapi/inc/class.vfs_shared.inc.php
Normal file
1370
phpgwapi/inc/class.vfs_shared.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
183
setup/setup_demo.php
Normal file
183
setup/setup_demo.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare *
|
||||
* http://www.egroupware.org *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
// Little file to setup a demo install
|
||||
|
||||
$GLOBALS['phpgw_info']['flags'] = array(
|
||||
'noheader' => True,
|
||||
'nonavbar' => True,
|
||||
'currentapp' => 'home',
|
||||
'noapi' => True
|
||||
);
|
||||
include('./inc/functions.inc.php');
|
||||
|
||||
// Authorize the user to use setup app and load the database
|
||||
// Does not return unless user is authorized
|
||||
if(!$GLOBALS['phpgw_setup']->auth('Config') || get_var('cancel',Array('POST')))
|
||||
{
|
||||
Header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!get_var('submit',Array('POST')))
|
||||
{
|
||||
$tpl_root = $GLOBALS['phpgw_setup']->html->setup_tpl_dir('setup');
|
||||
$setup_tpl = CreateObject('setup.Template',$tpl_root);
|
||||
$setup_tpl->set_file(array(
|
||||
'T_head' => 'head.tpl',
|
||||
'T_footer' => 'footer.tpl',
|
||||
'T_alert_msg' => 'msg_alert_msg.tpl',
|
||||
'T_login_main' => 'login_main.tpl',
|
||||
'T_login_stage_header' => 'login_stage_header.tpl',
|
||||
'T_setup_demo' => 'setup_demo.tpl'
|
||||
));
|
||||
$setup_tpl->set_block('T_login_stage_header','B_multi_domain','V_multi_domain');
|
||||
$setup_tpl->set_block('T_login_stage_header','B_single_domain','V_single_domain');
|
||||
|
||||
$GLOBALS['phpgw_setup']->html->show_header(lang('Demo Server Setup'));
|
||||
|
||||
$setup_tpl->set_var('action_url','setup_demo.php');
|
||||
$setup_tpl->set_var('description',lang('<b>This will create 1 admin account and 3 demo accounts</b><br>The username/passwords are: demo/guest, demo2/guest and demo3/guest.'));
|
||||
$setup_tpl->set_var('lang_deleteall',lang('Delete all existing SQL accounts, groups, ACLs and preferences (normally not necessary)?'));
|
||||
|
||||
$setup_tpl->set_var('detailadmin',lang('Details for Admin account'));
|
||||
$setup_tpl->set_var('adminusername',lang('Admin username'));
|
||||
$setup_tpl->set_var('adminfirstname',lang('Admin first name'));
|
||||
$setup_tpl->set_var('adminlastname',lang('Admin last name'));
|
||||
$setup_tpl->set_var('adminpassword',lang('Admin password'));
|
||||
$setup_tpl->set_var('adminpassword2',lang('Re-enter password'));
|
||||
$setup_tpl->set_var('create_demo_accounts',lang('Create demo accounts'));
|
||||
|
||||
$setup_tpl->set_var('lang_submit',lang('Save'));
|
||||
$setup_tpl->set_var('lang_cancel',lang('Cancel'));
|
||||
$setup_tpl->pparse('out','T_setup_demo');
|
||||
$GLOBALS['phpgw_setup']->html->show_footer();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Posted admin data */
|
||||
$passwd = get_var('passwd',Array('POST'));
|
||||
$passwd2 = get_var('passwd2',Array('POST'));
|
||||
$username = get_var('username',Array('POST'));
|
||||
$fname = get_var('fname',Array('POST'));
|
||||
$lname = get_var('lname',Array('POST'));
|
||||
|
||||
if($passwd != $passwd2)
|
||||
{
|
||||
echo lang('Passwords did not match, please re-enter') . '.';
|
||||
exit;
|
||||
}
|
||||
if(!$username)
|
||||
{
|
||||
echo lang('You must enter a username for the admin') . '.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$GLOBALS['phpgw_setup']->loaddb();
|
||||
/* Begin transaction for acl, etc */
|
||||
$GLOBALS['phpgw_setup']->db->transaction_begin();
|
||||
|
||||
if($_POST['delete_all'])
|
||||
{
|
||||
/* Now, clear out existing tables */
|
||||
$GLOBALS['phpgw_setup']->db->query('DELETE FROM phpgw_accounts');
|
||||
$GLOBALS['phpgw_setup']->db->query('DELETE FROM phpgw_preferences');
|
||||
$GLOBALS['phpgw_setup']->db->query('DELETE FROM phpgw_acl');
|
||||
}
|
||||
/* Create the demo groups */
|
||||
$defaultgroupid = (int)$GLOBALS['phpgw_setup']->add_account('Default','Default','Group',False,False);
|
||||
$admingroupid = (int)$GLOBALS['phpgw_setup']->add_account('Admins','Admin','Group',False,False);
|
||||
|
||||
if (!$defaultgroupid || !$admingroupid)
|
||||
{
|
||||
echo '<p><b>'.lang('Error in group-creation !!!')."</b></p>\n";
|
||||
echo '<p>'.lang('click <a href="index.php">here</a> to return to setup.')."</p>\n";
|
||||
$GLOBALS['phpgw_setup']->db->transaction_abort();
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Group perms for the default group */
|
||||
$GLOBALS['phpgw_setup']->add_acl(array('addressbook','calendar','infolog','email','preferences'),'run',$defaultgroupid);
|
||||
|
||||
// give admin access to all apps, to save us some support requests
|
||||
$all_apps = array();
|
||||
$GLOBALS['phpgw_setup']->db->query('SELECT app_name FROM phpgw_applications WHERE app_enabled<3');
|
||||
while ($GLOBALS['phpgw_setup']->db->next_record())
|
||||
{
|
||||
$all_apps[] = $GLOBALS['phpgw_setup']->db->f('app_name');
|
||||
}
|
||||
$GLOBALS['phpgw_setup']->add_acl($all_apps,'run',$admingroupid);
|
||||
|
||||
function insert_default_prefs($accountid)
|
||||
{
|
||||
$defaultprefs = array(
|
||||
'common' => array(
|
||||
'maxmatchs' => 15,
|
||||
'template_set' => 'idots',
|
||||
'theme' => 'idots',
|
||||
'navbar_format' => 'icons',
|
||||
'tz_offset' => 0,
|
||||
'dateformat' => 'Y/m/d',
|
||||
'timeformat' => '24',
|
||||
'lang' => get_var('ConfigLang',Array('POST','COOKIE'),'en'),
|
||||
'default_app' => 'calendar',
|
||||
'currency' => '$',
|
||||
'show_help' => True,
|
||||
),
|
||||
'calendar' => array(
|
||||
'workdaystarts' => 9,
|
||||
'workdayends' => 17,
|
||||
'weekdaystarts' => 'Monday',
|
||||
'defaultcalendar' => 'day',
|
||||
'planner_start_with_group' => $GLOBALS['defaultgroupid'],
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($defaultprefs as $app => $prefs)
|
||||
{
|
||||
$prefs = $GLOBALS['phpgw_setup']->db->db_addslashes(serialize($prefs));
|
||||
$GLOBALS['phpgw_setup']->db->query("INSERT INTO phpgw_preferences(preference_owner,preference_app,preference_value) VALUES($accountid,'$app','$prefs')",__FILE__,__LINE__);
|
||||
}
|
||||
}
|
||||
insert_default_prefs(-2); // set some default prefs
|
||||
|
||||
/* Creation of the demo accounts is optional - the checkbox is on by default. */
|
||||
if(get_var('create_demo',Array('POST')))
|
||||
{
|
||||
// Create 3 demo accounts
|
||||
$GLOBALS['phpgw_setup']->add_account('demo','Demo','Account','guest');
|
||||
$GLOBALS['phpgw_setup']->add_account('demo2','Demo2','Account','guest');
|
||||
$GLOBALS['phpgw_setup']->add_account('demo3','Demo3','Account','guest');
|
||||
}
|
||||
|
||||
/* Create records for administrator account, with Admins as primary and Default as additional group */
|
||||
$accountid = $GLOBALS['phpgw_setup']->add_account($username,$fname,$lname,$passwd,'Admins',True);
|
||||
if (!$accountid)
|
||||
{
|
||||
echo '<p><b>'.lang('Error in admin-creation !!!')."</b></p>\n";
|
||||
echo '<p>'.lang('click <a href="index.php">here</a> to return to setup.')."</p>\n";
|
||||
$GLOBALS['phpgw_setup']->db->transaction_abort();
|
||||
exit;
|
||||
}
|
||||
$GLOBALS['phpgw_setup']->add_acl('phpgw_group',$admingroupid,$accountid);
|
||||
$GLOBALS['phpgw_setup']->add_acl('phpgw_group',$defaultgroupid,$accountid);
|
||||
|
||||
/* Clear the access log, since these are all new users anyway */
|
||||
$GLOBALS['phpgw_setup']->db->query('DELETE FROM phpgw_access_log');
|
||||
|
||||
$GLOBALS['phpgw_setup']->db->transaction_commit();
|
||||
|
||||
Header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue
Block a user