forked from extern/egroupware
New doc for using admin/config.php. This should probably go somewhere else...
This commit is contained in:
parent
6c2caba4ba
commit
cbd35e90eb
BIN
admin/doc/adminconfig.dvi
Normal file
BIN
admin/doc/adminconfig.dvi
Normal file
Binary file not shown.
413
admin/doc/adminconfig.lyx
Normal file
413
admin/doc/adminconfig.lyx
Normal file
@ -0,0 +1,413 @@
|
||||
#LyX 1.1 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 218
|
||||
\textclass docbook
|
||||
\language english
|
||||
\inputencoding auto
|
||||
\fontscheme default
|
||||
\graphics default
|
||||
\paperfontsize default
|
||||
\spacing single
|
||||
\papersize Default
|
||||
\paperpackage a4
|
||||
\use_geometry 0
|
||||
\use_amsmath 0
|
||||
\paperorientation portrait
|
||||
\secnumdepth 3
|
||||
\tocdepth 3
|
||||
\paragraph_separation indent
|
||||
\defskip medskip
|
||||
\quotes_language english
|
||||
\quotes_times 2
|
||||
\papercolumns 1
|
||||
\papersides 1
|
||||
\paperpagestyle default
|
||||
|
||||
\layout Title
|
||||
|
||||
phpGroupWare admin/config.php
|
||||
\layout Abstract
|
||||
|
||||
A brief introduction to writing hooks and templates for any application
|
||||
to use this admin interface, by
|
||||
\layout Abstract
|
||||
|
||||
Miles Lott <milosch@phpgroupware.org> Dec 22, 2001.
|
||||
\layout Section
|
||||
|
||||
Files
|
||||
\layout Subsection
|
||||
|
||||
config.tpl (required)
|
||||
\layout Standard
|
||||
|
||||
In your application/templates/default directory, create a new template file
|
||||
named 'config.tpl'.
|
||||
This will be included by config.php and used to draw the page.
|
||||
This template should include a POST method form.
|
||||
The following template tags may be used:
|
||||
\layout Enumerate
|
||||
|
||||
{action_url} - A phpgw->link to config.php will be inserted.
|
||||
\layout Enumerate
|
||||
|
||||
{title} - This will be parsed to display 'Site Configuration'.
|
||||
\layout Enumerate
|
||||
|
||||
{th_bg},{th_text},{row_on},{row_off} - Replaced with the current theme colors.
|
||||
\layout Standard
|
||||
|
||||
and the following special types:
|
||||
\layout Enumerate
|
||||
|
||||
{lang_XXX} - Filled with lang('XXX').
|
||||
\layout Enumerate
|
||||
|
||||
{value_XXX} - Filled with the current value of config item 'XXX'.
|
||||
\layout Enumerate
|
||||
|
||||
{selected_XXX} - set to '', or ' selected' if an option value is current.
|
||||
\layout Enumerate
|
||||
|
||||
{hook_XXX} - Calls a function named XXX (will be discussed later).
|
||||
\layout Standard
|
||||
|
||||
Following is an example from the addressbook application:
|
||||
\layout Code
|
||||
|
||||
<form method="POST" action="{action_url}">
|
||||
\layout Code
|
||||
|
||||
<table border="0" align="center">
|
||||
\layout Code
|
||||
|
||||
<tr bgcolor="{th_bg}">
|
||||
\layout Code
|
||||
|
||||
<td colspan="2"><font color="{th_text}"> <b>{title}</b></font></td>
|
||||
\layout Code
|
||||
|
||||
</tr> <tr bgcolor="{th_err}">
|
||||
\layout Code
|
||||
|
||||
<td colspan="2"> <b>{error}</b></font></td>
|
||||
\layout Code
|
||||
|
||||
</tr>
|
||||
\layout Code
|
||||
|
||||
<!-- END header -->
|
||||
\layout Code
|
||||
|
||||
<!-- BEGIN body -->
|
||||
\layout Code
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
\layout Code
|
||||
|
||||
<td colspan="2"> </td>
|
||||
\layout Code
|
||||
|
||||
</tr>
|
||||
\layout Code
|
||||
|
||||
<tr bgcolor="{row_off}">
|
||||
\layout Code
|
||||
|
||||
<td colspan="2"> <b>{lang_Addressbook}/{lang_Contact_Settings}</b></font>
|
||||
\layout Code
|
||||
|
||||
</td>
|
||||
\layout Code
|
||||
|
||||
</tr>
|
||||
\layout Code
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
\layout Code
|
||||
|
||||
<td>{lang_Contact_application}:</td>
|
||||
\layout Code
|
||||
|
||||
<td><input name="newsettings[contact_application]" value="{value_contact_appli
|
||||
cation}"></td>
|
||||
\layout Code
|
||||
|
||||
</tr>
|
||||
\layout Code
|
||||
|
||||
...
|
||||
\layout Standard
|
||||
|
||||
Note the fieldname, newsettings[contact_application].
|
||||
This array name must be used for the form values.
|
||||
Next, note the value setting for this form element, {value_contact_application}.
|
||||
This indicates that we want the current value of the config setting, 'contact_a
|
||||
pplication', to be set and displayed on the form.
|
||||
Lastly, look at the template element, {lang_Contact_application}.
|
||||
Here, the value from the lang db table will be inserted if available.
|
||||
\layout Standard
|
||||
|
||||
Let's take a look at part of the preferences/default/config.tpl:
|
||||
\layout Code
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
\layout Code
|
||||
|
||||
<td>{lang_Country_Selection} ({lang_Text_Entry}/{lang_SelectBox}):</td>
|
||||
\layout Code
|
||||
|
||||
<td>
|
||||
\layout Code
|
||||
|
||||
<select name="newsettings[countrylist]">
|
||||
\layout Code
|
||||
|
||||
{hook_country_set}
|
||||
\layout Code
|
||||
|
||||
</select>
|
||||
\layout Code
|
||||
|
||||
</td>
|
||||
\layout Code
|
||||
|
||||
</tr>
|
||||
\layout Standard
|
||||
|
||||
Here, we are adding a new element, {hook_country_set}.
|
||||
This brings up the next file we will need to parse this value...
|
||||
\layout Subsection
|
||||
|
||||
hook_config.inc.php (optional)
|
||||
\layout Standard
|
||||
|
||||
At each invocation of config.php, a call to the common class function hook_single
|
||||
() is made.
|
||||
It attempts to include a file, hook_config.inc.php as a set of code for config.php
|
||||
to use.
|
||||
In the case of the preferences example above, using hook_country_set, here
|
||||
is the corresponding function in preferences/inc/hook_config.inc.php:
|
||||
\layout Code
|
||||
|
||||
function country_set($config)
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$country = array( 'user_choice' => 'Users Choice', 'force_select' =>
|
||||
'Force Selectbox' );
|
||||
\layout Code
|
||||
|
||||
while (list ($key, $value) = each ($country))
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
if ($config['countrylist'] == $key)
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$selected = ' selected';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
else
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$selected = '';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
$descr = lang($value);
|
||||
\layout Code
|
||||
|
||||
$out .= '<option value="' .
|
||||
$key .
|
||||
'"' .
|
||||
$selected .
|
||||
'>' .
|
||||
$descr .
|
||||
'</option>' .
|
||||
"
|
||||
\backslash
|
||||
n";
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
return $out;
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Standard
|
||||
|
||||
Note again the template value we used earlier, {hook_country_set}.
|
||||
This causes config.php to look for a function named country_set().
|
||||
Since we included the file with this function via the hook_single() call,
|
||||
this function is executed.
|
||||
It's return is a string, and the function prints nothing itself.
|
||||
\layout Subsection
|
||||
|
||||
hook_config_validate.inc.php (optional)
|
||||
\layout Standard
|
||||
|
||||
Once the admin clicks the submit button to post the form, we can optionally
|
||||
validate their input using one or many different functions.
|
||||
This is done by first making another call to hook_single() in the API common
|
||||
class.
|
||||
This time, the name config_validate is used, so common tries to include
|
||||
'application/inc/hook_config_validate.inc.php'.
|
||||
\layout Standard
|
||||
|
||||
If this file exists, it sets a var to tell config.php it was found.
|
||||
Following then are functions named after each config we want to validate.
|
||||
The following example is for addressbook:
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['phpgw_info']['server']['found_validation_hook'] = True;
|
||||
\layout Code
|
||||
|
||||
\layout Code
|
||||
|
||||
/* Check a specific setting.
|
||||
Name must match the setting.
|
||||
*/
|
||||
\layout Code
|
||||
|
||||
function ldap_contact_context($value='')
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
if($value == $GLOBALS['phpgw_info']['server']['ldap_context'])
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context for ldap must be
|
||||
different from the context used for accounts';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
elseif($value == $GLOBALS['phpgw_info']['server']['ldap_group_context'])
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context for ldap must be
|
||||
different from the context used for groups';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
else
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = '';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Standard
|
||||
|
||||
Here we created a function to check the entered value for the config item,
|
||||
ldap_contact_context.
|
||||
We want to make sure the admin did not set this value to one which would
|
||||
conflict with another config item, used for accounts or groups in phpGroupWare.
|
||||
\layout Standard
|
||||
|
||||
config.php calls this function, sending it the POSTed value.
|
||||
config.php continues, adding all other config items from the POSTed values.
|
||||
\layout Standard
|
||||
|
||||
The variable $GLOBALS['config_error'] is parsed through lang(), then appended
|
||||
to the local variable, $error.
|
||||
If this has any value after the POSTed variables are checked, the form
|
||||
then has its {error} tag filled with this result.
|
||||
The form is displayed again, with the error.
|
||||
If $error has no value, config.php redirects to admin/index.php.
|
||||
\layout Standard
|
||||
|
||||
However, there is one more function that may be included in hook_config_validate.
|
||||
inc.php:
|
||||
\layout Code
|
||||
|
||||
/* Check all settings to validate input.
|
||||
Name must be 'final_validation' */
|
||||
\layout Code
|
||||
|
||||
function final_validation($value='')
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
if($value['contact_repository'] == 'ldap' && !$value['ldap_contact_dn'])
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact dn must be set';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
elseif($value['contact_repository'] == 'ldap' && !$value['ldap_contact_c
|
||||
ontext'])
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context must be set';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
else
|
||||
\layout Code
|
||||
|
||||
{
|
||||
\layout Code
|
||||
|
||||
$GLOBALS['config_error'] = '';
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Code
|
||||
|
||||
}
|
||||
\layout Standard
|
||||
|
||||
config.php checks for the existence of the function 'final_validation()'.
|
||||
This function can be used to check all form values at once.
|
||||
It gets sent the entire $newsettings array POSTed from the form.
|
||||
As with the other functions in this file, final_validation() should set
|
||||
$GLOBALS['config_error'] if there is a problem.
|
||||
\the_end
|
BIN
admin/doc/adminconfig.pdf
Normal file
BIN
admin/doc/adminconfig.pdf
Normal file
Binary file not shown.
534
admin/doc/adminconfig.ps
Normal file
534
admin/doc/adminconfig.ps
Normal file
@ -0,0 +1,534 @@
|
||||
%!PS-Adobe-2.0
|
||||
%%Creator: dvips(k) 5.86 Copyright 1999 Radical Eye Software
|
||||
%%Title: adminconfig.dvi
|
||||
%%Pages: 6
|
||||
%%PageOrder: Ascend
|
||||
%%BoundingBox: 0 0 612 792
|
||||
%%DocumentFonts: Helvetica-Bold Times-Roman Courier Times-Italic
|
||||
%%EndComments
|
||||
%DVIPSWebPage: (www.radicaleye.com)
|
||||
%DVIPSCommandLine: dvips -t letter -o adminconfig.ps adminconfig.dvi
|
||||
%DVIPSParameters: dpi=600, compressed
|
||||
%DVIPSSource: TeX output 2001.12.22:1805
|
||||
%%BeginProcSet: texc.pro
|
||||
%!
|
||||
/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S
|
||||
N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72
|
||||
mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0
|
||||
0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{
|
||||
landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize
|
||||
mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[
|
||||
matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round
|
||||
exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{
|
||||
statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0]
|
||||
N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin
|
||||
/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array
|
||||
/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2
|
||||
array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N
|
||||
df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A
|
||||
definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get
|
||||
}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub}
|
||||
B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr
|
||||
1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3
|
||||
1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx
|
||||
0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx
|
||||
sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{
|
||||
rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp
|
||||
gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B
|
||||
/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{
|
||||
/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{
|
||||
A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy
|
||||
get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse}
|
||||
ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp
|
||||
fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17
|
||||
{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add
|
||||
chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{
|
||||
1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop}
|
||||
forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn
|
||||
/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put
|
||||
}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{
|
||||
bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A
|
||||
mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{
|
||||
SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{
|
||||
userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X
|
||||
1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4
|
||||
index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N
|
||||
/p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{
|
||||
/Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT)
|
||||
(LaserWriter 16/600)]{A length product length le{A length product exch 0
|
||||
exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse
|
||||
end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask
|
||||
grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot}
|
||||
imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round
|
||||
exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto
|
||||
fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p
|
||||
delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M}
|
||||
B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{
|
||||
p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S
|
||||
rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end
|
||||
|
||||
%%EndProcSet
|
||||
%%BeginProcSet: 8r.enc
|
||||
% @@psencodingfile@{
|
||||
% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry",
|
||||
% version = "0.6",
|
||||
% date = "22 June 1996",
|
||||
% filename = "8r.enc",
|
||||
% email = "kb@@mail.tug.org",
|
||||
% address = "135 Center Hill Rd. // Plymouth, MA 02360",
|
||||
% codetable = "ISO/ASCII",
|
||||
% checksum = "119 662 4424",
|
||||
% docstring = "Encoding for TrueType or Type 1 fonts to be used with TeX."
|
||||
% @}
|
||||
%
|
||||
% Idea is to have all the characters normally included in Type 1 fonts
|
||||
% available for typesetting. This is effectively the characters in Adobe
|
||||
% Standard Encoding + ISO Latin 1 + extra characters from Lucida.
|
||||
%
|
||||
% Character code assignments were made as follows:
|
||||
%
|
||||
% (1) the Windows ANSI characters are almost all in their Windows ANSI
|
||||
% positions, because some Windows users cannot easily reencode the
|
||||
% fonts, and it makes no difference on other systems. The only Windows
|
||||
% ANSI characters not available are those that make no sense for
|
||||
% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen
|
||||
% (173). quotesingle and grave are moved just because it's such an
|
||||
% irritation not having them in TeX positions.
|
||||
%
|
||||
% (2) Remaining characters are assigned arbitrarily to the lower part
|
||||
% of the range, avoiding 0, 10 and 13 in case we meet dumb software.
|
||||
%
|
||||
% (3) Y&Y Lucida Bright includes some extra text characters; in the
|
||||
% hopes that other PostScript fonts, perhaps created for public
|
||||
% consumption, will include them, they are included starting at 0x12.
|
||||
%
|
||||
% (4) Remaining positions left undefined are for use in (hopefully)
|
||||
% upward-compatible revisions, if someday more characters are generally
|
||||
% available.
|
||||
%
|
||||
% (5) hyphen appears twice for compatibility with both ASCII and Windows.
|
||||
%
|
||||
/TeXBase1Encoding [
|
||||
% 0x00 (encoded characters from Adobe Standard not in Windows 3.1)
|
||||
/.notdef /dotaccent /fi /fl
|
||||
/fraction /hungarumlaut /Lslash /lslash
|
||||
/ogonek /ring /.notdef
|
||||
/breve /minus /.notdef
|
||||
% These are the only two remaining unencoded characters, so may as
|
||||
% well include them.
|
||||
/Zcaron /zcaron
|
||||
% 0x10
|
||||
/caron /dotlessi
|
||||
% (unusual TeX characters available in, e.g., Lucida Bright)
|
||||
/dotlessj /ff /ffi /ffl
|
||||
/.notdef /.notdef /.notdef /.notdef
|
||||
/.notdef /.notdef /.notdef /.notdef
|
||||
% very contentious; it's so painful not having quoteleft and quoteright
|
||||
% at 96 and 145 that we move the things normally found there down to here.
|
||||
/grave /quotesingle
|
||||
% 0x20 (ASCII begins)
|
||||
/space /exclam /quotedbl /numbersign
|
||||
/dollar /percent /ampersand /quoteright
|
||||
/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash
|
||||
% 0x30
|
||||
/zero /one /two /three /four /five /six /seven
|
||||
/eight /nine /colon /semicolon /less /equal /greater /question
|
||||
% 0x40
|
||||
/at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O
|
||||
% 0x50
|
||||
/P /Q /R /S /T /U /V /W
|
||||
/X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore
|
||||
% 0x60
|
||||
/quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o
|
||||
% 0x70
|
||||
/p /q /r /s /t /u /v /w
|
||||
/x /y /z /braceleft /bar /braceright /asciitilde
|
||||
/.notdef % rubout; ASCII ends
|
||||
% 0x80
|
||||
/.notdef /.notdef /quotesinglbase /florin
|
||||
/quotedblbase /ellipsis /dagger /daggerdbl
|
||||
/circumflex /perthousand /Scaron /guilsinglleft
|
||||
/OE /.notdef /.notdef /.notdef
|
||||
% 0x90
|
||||
/.notdef /.notdef /.notdef /quotedblleft
|
||||
/quotedblright /bullet /endash /emdash
|
||||
/tilde /trademark /scaron /guilsinglright
|
||||
/oe /.notdef /.notdef /Ydieresis
|
||||
% 0xA0
|
||||
/.notdef % nobreakspace
|
||||
/exclamdown /cent /sterling
|
||||
/currency /yen /brokenbar /section
|
||||
/dieresis /copyright /ordfeminine /guillemotleft
|
||||
/logicalnot
|
||||
/hyphen % Y&Y (also at 45); Windows' softhyphen
|
||||
/registered
|
||||
/macron
|
||||
% 0xD0
|
||||
/degree /plusminus /twosuperior /threesuperior
|
||||
/acute /mu /paragraph /periodcentered
|
||||
/cedilla /onesuperior /ordmasculine /guillemotright
|
||||
/onequarter /onehalf /threequarters /questiondown
|
||||
% 0xC0
|
||||
/Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla
|
||||
/Egrave /Eacute /Ecircumflex /Edieresis
|
||||
/Igrave /Iacute /Icircumflex /Idieresis
|
||||
% 0xD0
|
||||
/Eth /Ntilde /Ograve /Oacute
|
||||
/Ocircumflex /Otilde /Odieresis /multiply
|
||||
/Oslash /Ugrave /Uacute /Ucircumflex
|
||||
/Udieresis /Yacute /Thorn /germandbls
|
||||
% 0xE0
|
||||
/agrave /aacute /acircumflex /atilde
|
||||
/adieresis /aring /ae /ccedilla
|
||||
/egrave /eacute /ecircumflex /edieresis
|
||||
/igrave /iacute /icircumflex /idieresis
|
||||
% 0xF0
|
||||
/eth /ntilde /ograve /oacute
|
||||
/ocircumflex /otilde /odieresis /divide
|
||||
/oslash /ugrave /uacute /ucircumflex
|
||||
/udieresis /yacute /thorn /ydieresis
|
||||
] def
|
||||
|
||||
%%EndProcSet
|
||||
%%BeginProcSet: texps.pro
|
||||
%!
|
||||
TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2
|
||||
index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll
|
||||
exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics
|
||||
exch def dict begin Encoding{exch dup type/integertype ne{pop pop 1 sub
|
||||
dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}
|
||||
ifelse}forall Metrics/Metrics currentdict end def[2 index currentdict
|
||||
end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{
|
||||
dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1
|
||||
roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def
|
||||
dup[exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}
|
||||
if}forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}
|
||||
def end
|
||||
|
||||
%%EndProcSet
|
||||
%%BeginProcSet: special.pro
|
||||
%!
|
||||
TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N
|
||||
/vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N
|
||||
/rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N
|
||||
/@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{
|
||||
/hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho
|
||||
X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B
|
||||
/@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{
|
||||
/urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known
|
||||
{userdict/md get type/dicttype eq{userdict begin md length 10 add md
|
||||
maxlength ge{/md md dup length 20 add dict copy def}if end md begin
|
||||
/letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S
|
||||
atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{
|
||||
itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll
|
||||
transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll
|
||||
curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf
|
||||
pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}
|
||||
if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1
|
||||
-1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3
|
||||
get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip
|
||||
yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub
|
||||
neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{
|
||||
noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop
|
||||
90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get
|
||||
neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr
|
||||
1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr
|
||||
2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4
|
||||
-1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S
|
||||
TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{
|
||||
Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale
|
||||
}if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState
|
||||
save N userdict maxlength dict begin/magscale true def normalscale
|
||||
currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts
|
||||
/psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x
|
||||
psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx
|
||||
psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub
|
||||
TR/showpage{}N/erasepage{}N/copypage{}N/p 3 def @MacSetUp}N/doclip{
|
||||
psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2
|
||||
roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath
|
||||
moveto}N/endTexFig{end psf$SavedState restore}N/@beginspecial{SDict
|
||||
begin/SpecialSave save N gsave normalscale currentpoint TR
|
||||
@SpecialDefaults count/ocount X/dcount countdictstack N}N/@setspecial{
|
||||
CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto
|
||||
closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx
|
||||
sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR
|
||||
}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse
|
||||
CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury
|
||||
lineto closepath clip}if/showpage{}N/erasepage{}N/copypage{}N newpath}N
|
||||
/@endspecial{count ocount sub{pop}repeat countdictstack dcount sub{end}
|
||||
repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N
|
||||
/@fedspecial{end}B/li{lineto}B/rl{rlineto}B/rc{rcurveto}B/np{/SaveX
|
||||
currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY
|
||||
moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X
|
||||
/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0
|
||||
1 startangle endangle arc savematrix setmatrix}N end
|
||||
|
||||
%%EndProcSet
|
||||
%%BeginProcSet: color.pro
|
||||
%!
|
||||
TeXDict begin/setcmykcolor where{pop}{/setcmykcolor{dup 10 eq{pop
|
||||
setrgbcolor}{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll
|
||||
}repeat setrgbcolor pop}ifelse}B}ifelse/TeXcolorcmyk{setcmykcolor}def
|
||||
/TeXcolorrgb{setrgbcolor}def/TeXcolorgrey{setgray}def/TeXcolorgray{
|
||||
setgray}def/TeXcolorhsb{sethsbcolor}def/currentcmykcolor where{pop}{
|
||||
/currentcmykcolor{currentrgbcolor 10}B}ifelse/DC{exch dup userdict exch
|
||||
known{pop pop}{X}ifelse}B/GreenYellow{0.15 0 0.69 0 setcmykcolor}DC
|
||||
/Yellow{0 0 1 0 setcmykcolor}DC/Goldenrod{0 0.10 0.84 0 setcmykcolor}DC
|
||||
/Dandelion{0 0.29 0.84 0 setcmykcolor}DC/Apricot{0 0.32 0.52 0
|
||||
setcmykcolor}DC/Peach{0 0.50 0.70 0 setcmykcolor}DC/Melon{0 0.46 0.50 0
|
||||
setcmykcolor}DC/YellowOrange{0 0.42 1 0 setcmykcolor}DC/Orange{0 0.61
|
||||
0.87 0 setcmykcolor}DC/BurntOrange{0 0.51 1 0 setcmykcolor}DC
|
||||
/Bittersweet{0 0.75 1 0.24 setcmykcolor}DC/RedOrange{0 0.77 0.87 0
|
||||
setcmykcolor}DC/Mahogany{0 0.85 0.87 0.35 setcmykcolor}DC/Maroon{0 0.87
|
||||
0.68 0.32 setcmykcolor}DC/BrickRed{0 0.89 0.94 0.28 setcmykcolor}DC/Red{
|
||||
0 1 1 0 setcmykcolor}DC/OrangeRed{0 1 0.50 0 setcmykcolor}DC/RubineRed{
|
||||
0 1 0.13 0 setcmykcolor}DC/WildStrawberry{0 0.96 0.39 0 setcmykcolor}DC
|
||||
/Salmon{0 0.53 0.38 0 setcmykcolor}DC/CarnationPink{0 0.63 0 0
|
||||
setcmykcolor}DC/Magenta{0 1 0 0 setcmykcolor}DC/VioletRed{0 0.81 0 0
|
||||
setcmykcolor}DC/Rhodamine{0 0.82 0 0 setcmykcolor}DC/Mulberry{0.34 0.90
|
||||
0 0.02 setcmykcolor}DC/RedViolet{0.07 0.90 0 0.34 setcmykcolor}DC
|
||||
/Fuchsia{0.47 0.91 0 0.08 setcmykcolor}DC/Lavender{0 0.48 0 0
|
||||
setcmykcolor}DC/Thistle{0.12 0.59 0 0 setcmykcolor}DC/Orchid{0.32 0.64 0
|
||||
0 setcmykcolor}DC/DarkOrchid{0.40 0.80 0.20 0 setcmykcolor}DC/Purple{
|
||||
0.45 0.86 0 0 setcmykcolor}DC/Plum{0.50 1 0 0 setcmykcolor}DC/Violet{
|
||||
0.79 0.88 0 0 setcmykcolor}DC/RoyalPurple{0.75 0.90 0 0 setcmykcolor}DC
|
||||
/BlueViolet{0.86 0.91 0 0.04 setcmykcolor}DC/Periwinkle{0.57 0.55 0 0
|
||||
setcmykcolor}DC/CadetBlue{0.62 0.57 0.23 0 setcmykcolor}DC
|
||||
/CornflowerBlue{0.65 0.13 0 0 setcmykcolor}DC/MidnightBlue{0.98 0.13 0
|
||||
0.43 setcmykcolor}DC/NavyBlue{0.94 0.54 0 0 setcmykcolor}DC/RoyalBlue{1
|
||||
0.50 0 0 setcmykcolor}DC/Blue{1 1 0 0 setcmykcolor}DC/Cerulean{0.94 0.11
|
||||
0 0 setcmykcolor}DC/Cyan{1 0 0 0 setcmykcolor}DC/ProcessBlue{0.96 0 0 0
|
||||
setcmykcolor}DC/SkyBlue{0.62 0 0.12 0 setcmykcolor}DC/Turquoise{0.85 0
|
||||
0.20 0 setcmykcolor}DC/TealBlue{0.86 0 0.34 0.02 setcmykcolor}DC
|
||||
/Aquamarine{0.82 0 0.30 0 setcmykcolor}DC/BlueGreen{0.85 0 0.33 0
|
||||
setcmykcolor}DC/Emerald{1 0 0.50 0 setcmykcolor}DC/JungleGreen{0.99 0
|
||||
0.52 0 setcmykcolor}DC/SeaGreen{0.69 0 0.50 0 setcmykcolor}DC/Green{1 0
|
||||
1 0 setcmykcolor}DC/ForestGreen{0.91 0 0.88 0.12 setcmykcolor}DC
|
||||
/PineGreen{0.92 0 0.59 0.25 setcmykcolor}DC/LimeGreen{0.50 0 1 0
|
||||
setcmykcolor}DC/YellowGreen{0.44 0 0.74 0 setcmykcolor}DC/SpringGreen{
|
||||
0.26 0 0.76 0 setcmykcolor}DC/OliveGreen{0.64 0 0.95 0.40 setcmykcolor}
|
||||
DC/RawSienna{0 0.72 1 0.45 setcmykcolor}DC/Sepia{0 0.83 1 0.70
|
||||
setcmykcolor}DC/Brown{0 0.81 1 0.60 setcmykcolor}DC/Tan{0.14 0.42 0.56 0
|
||||
setcmykcolor}DC/Gray{0 0 0 0.50 setcmykcolor}DC/Black{0 0 0 1
|
||||
setcmykcolor}DC/White{0 0 0 0 setcmykcolor}DC end
|
||||
|
||||
%%EndProcSet
|
||||
TeXDict begin 40258431 52099146 1000 600 600 (adminconfig.dvi)
|
||||
@start /Fa 138[42 2[32 1[42 42 42 60 3[23 42 42 1[37
|
||||
42 37 1[42 9[69 15[60 16[42 42 42 42 42 42 1[23 21 43[42
|
||||
2[{TeXBase1Encoding ReEncodeFont}24 83.022 /Times-Italic
|
||||
rf /Fb 107[45 22[45 1[45 1[45 45 45 45 45 45 45 45 1[45
|
||||
45 45 45 45 45 1[45 45 45 45 45 45 45 45 45 1[45 1[45
|
||||
45 45 5[45 45 45 2[45 45 45 1[45 2[45 1[45 45 45 45 45
|
||||
45 45 2[45 45 45 45 45 7[45 1[45 45 45 45 45 1[45 45
|
||||
45 45 45 1[45 1[45 45 33[{TeXBase1Encoding ReEncodeFont}64
|
||||
74.7198 /Courier rf /Fc 137[66 73 40 1[47 73 73 73 73
|
||||
1[33 66 1[33 73 73 1[66 73 66 1[66 1[66 43[66 66 66 2[33
|
||||
4[40 40 37[73 2[{TeXBase1Encoding ReEncodeFont}25 119.552
|
||||
/Helvetica-Bold rf /Fd 140[80 6[40 2[40 3[80 30[88 20[80
|
||||
2[40 46[{TeXBase1Encoding ReEncodeFont}7 143.462 /Helvetica-Bold
|
||||
rf /Fe 107[37 22[40 1[40 1[42 42 60 42 42 23 32 28 1[42
|
||||
42 42 65 23 42 1[23 42 42 28 37 42 37 42 37 1[42 1[28
|
||||
1[28 2[60 78 2[51 46 55 1[46 60 60 74 51 2[28 60 60 46
|
||||
1[60 55 55 60 76 1[47 1[47 1[23 5[42 42 42 42 42 23 21
|
||||
28 21 2[28 28 28 2[42 32[46 46 2[{TeXBase1Encoding ReEncodeFont}66
|
||||
83.022 /Times-Roman rf /Ff 138[126 2[80 1[126 126 126
|
||||
184 3[57 126 126 1[115 126 115 1[115 9[195 15[161 23[57
|
||||
57 43[126 2[{TeXBase1Encoding ReEncodeFont}18 206.584
|
||||
/Helvetica-Bold rf end
|
||||
%%EndProlog
|
||||
%%BeginSetup
|
||||
%%Feature: *Resolution 600dpi
|
||||
TeXDict begin
|
||||
%%BeginPaperSize: Letter
|
||||
letter
|
||||
%%EndPaperSize
|
||||
|
||||
%%EndSetup
|
||||
%%Page: 1 1
|
||||
1 0 bop Black 0 TeXcolorgray Black Black 505 647 a Ff(phpGr)l(oupW)-8
|
||||
b(are)58 b(admin/con\002g.php)695 879 y Fe(A)21 b(brief)e(introduction)
|
||||
f(to)i(writing)g(hooks)f(and)h(templates)g(for)f(an)o(y)h(application)e
|
||||
(to)j(use)f(this)695 987 y(admin)f(interf)o(ace,)h(by)695
|
||||
1136 y(Miles)h(Lott)f(<milosch@phpgroupw)o(are.or)o(g)o(>)15
|
||||
b(Dec)20 b(22,)g(2001.)-2 1854 y Fd(1.)39 b(Files)-2
|
||||
2182 y Fc(1.1.)34 b(con\002g.tpl)h(\(required\))396 2350
|
||||
y Fe(In)20 b(your)f(application/templates/def)o(ault)e(directory)-5
|
||||
b(,)18 b(create)i(a)g(ne)n(w)g(template)g(\002le)h(named)e
|
||||
('con\002g.tpl'.)f(This)i(will)396 2458 y(be)g(included)f(by)h
|
||||
(con\002g.php)d(and)j(used)g(to)g(dra)o(w)g(the)g(page.)f(This)i
|
||||
(template)e(should)h(include)f(a)h(POST)h(method)396
|
||||
2566 y(form.)e(The)h(follo)n(wing)f(template)g(tags)i(may)e(be)i(used:)
|
||||
p Black 463 2798 a(1.)p Black 40 w({action_url})e(-)h(A)h(phpgw->link)c
|
||||
(to)j(con\002g.php)e(will)j(be)f(inserted.)p Black 463
|
||||
2947 a(2.)p Black 40 w({title})h(-)f(This)h(will)g(be)f(parsed)f(to)i
|
||||
(display)e('Site)i(Con\002guration'.)p Black 463 3097
|
||||
a(3.)p Black 40 w({th_bg},{th_te)o(xt},{ro)n(w_on)o(},{r)o(o)n(w_)o(of)
|
||||
m(f})15 b(-)20 b(Replaced)g(with)g(the)g(current)f(theme)h(colors.)396
|
||||
3246 y(and)g(the)g(follo)n(wing)f(special)h(types:)p
|
||||
Black 463 3479 a(1.)p Black 40 w({lang_XXX})f(-)i(Filled)f(with)h
|
||||
(lang\('XXX'\).)p Black 463 3628 a(2.)p Black 40 w({v)n(alue_XXX})e(-)h
|
||||
(Filled)h(with)f(the)g(current)f(v)n(alue)h(of)g(con\002g)f(item)h
|
||||
('XXX'.)p Black 463 3778 a(3.)p Black 40 w({selected_XXX})g(-)g(set)h
|
||||
(to)f(\224,)h(or)f(')g(selected')g(if)g(an)h(option)d(v)n(alue)i(is)h
|
||||
(current.)p Black 463 3927 a(4.)p Black 40 w({hook_XXX})d(-)j(Calls)g
|
||||
(a)g(function)d(named)h(XXX)i(\(will)f(be)h(discussed)f(later\).)396
|
||||
4077 y(F)o(ollo)n(wing)f(is)i(an)f(e)o(xample)f(from)g(the)h
|
||||
(addressbook)e(application:)396 4257 y Fb(<form)44 b(method="POST")f
|
||||
(action="{action_url}">)396 4354 y(<table)h(border="0")f
|
||||
(align="center">)441 4451 y(<tr)h(bgcolor="{th_bg}">)486
|
||||
4548 y(<td)g(colspan="2"><font)e
|
||||
(color="{th_text}"> <b>{title}</b></f)o(ont><)o(/td>)441
|
||||
4645 y(</tr>)i(<tr)g(bgcolor="{th_err}">)486 4742 y(<td)g
|
||||
(colspan="2"> <b>{error}</b></font></)o(td>)441
|
||||
4840 y(</tr>)p Black 3842 5278 a Fa(1)p Black eop
|
||||
%%Page: 2 2
|
||||
2 1 bop Black 0 TeXcolorgray Black 2778 67 a Fa(phpGr)l(oupW)-8
|
||||
b(ar)m(e)19 b(admin/con\002g)o(.php)p Black 396 579 a
|
||||
Fb(<!--)44 b(END)h(header)f(-->)396 676 y(<!--)g(BEGIN)g(body)h(-->)441
|
||||
773 y(<tr)f(bgcolor="{row_on}">)486 870 y(<td)g
|
||||
(colspan="2"> </td>)441 967 y(</tr>)441 1065 y(<tr)g
|
||||
(bgcolor="{row_off}">)486 1162 y(<td)g
|
||||
(colspan="2"> <b>{lang_Addressbook}/{)o(lang_C)o(ontact)o(_Setti)o
|
||||
(ngs}<)o(/b></f)o(ont>)396 1259 y(</td>)441 1356 y(</tr>)441
|
||||
1453 y(<tr)g(bgcolor="{row_on}">)486 1550 y
|
||||
(<td>{lang_Contact_application}:</td>)486 1647 y(<td><input)f
|
||||
(name="newsettings[contact_application]")38 b
|
||||
(value="{value_contact_application}"></td>)441 1745 y(</tr>)396
|
||||
1842 y(...)396 2130 y Fe(Note)20 b(the)h(\002eldname,)e(ne)n
|
||||
(wsettings[contact_application].)c(This)20 b(array)f(name)h(must)g(be)g
|
||||
(used)g(for)g(the)g(form)f(v)n(alues.)396 2238 y(Ne)o(xt,)h(note)g(the)
|
||||
g(v)n(alue)f(setting)i(for)e(this)i(form)e(element,)g({v)n
|
||||
(alue_contact_application}.)c(This)20 b(indicates)g(that)h(we)396
|
||||
2346 y(w)o(ant)g(the)f(current)f(v)n(alue)g(of)h(the)g(con\002g)g
|
||||
(setting,)g('contact_application',)c(to)k(be)g(set)h(and)f(displayed)f
|
||||
(on)g(the)i(form.)396 2454 y(Lastly)-5 b(,)20 b(look)f(at)i(the)f
|
||||
(template)g(element,)f({lang_Contact_application}.)d(Here,)j(the)i(v)n
|
||||
(alue)e(from)g(the)i(lang)e(db)h(table)396 2561 y(will)h(be)f(inserted)
|
||||
g(if)g(a)n(v)n(ailable.)396 2711 y(Let')-5 b(s)21 b(tak)o(e)f(a)h(look)
|
||||
e(at)i(part)f(of)g(the)g(preferences/def)o(ault/con\002g.tpl:)441
|
||||
2891 y Fb(<tr)44 b(bgcolor="{row_on}">)486 2988 y
|
||||
(<td>{lang_Country_Selection})c
|
||||
(\({lang_Text_Entry}/{lang_SelectBox}\):</)o(td>)486
|
||||
3085 y(<td>)531 3182 y(<select)j(name="newsettings[countrylist]">)396
|
||||
3280 y({hook_country_set})531 3377 y(</select>)486 3474
|
||||
y(</td>)441 3571 y(</tr>)396 3859 y Fe(Here,)20 b(we)h(are)f(adding)f
|
||||
(a)h(ne)n(w)g(element,)f({hook_country_set}.)d(This)k(brings)f(up)h
|
||||
(the)g(ne)o(xt)g(\002le)h(we)f(will)h(need)f(to)396 3967
|
||||
y(parse)g(this)h(v)n(alue...)-2 4337 y Fc(1.2.)34 b
|
||||
(hook_con\002g.inc.php)j(\(optional\))396 4504 y Fe(At)21
|
||||
b(each)f(in)m(v)n(ocation)e(of)i(con\002g.php,)d(a)k(call)g(to)f(the)g
|
||||
(common)f(class)i(function)d(hook_single\(\))f(is)k(made.)f(It)g
|
||||
(attempts)396 4612 y(to)h(include)e(a)h(\002le,)h
|
||||
(hook_con\002g.inc.php)14 b(as)21 b(a)g(set)g(of)f(code)f(for)h
|
||||
(con\002g.php)d(to)k(use.)f(In)g(the)g(case)h(of)f(the)g(preferences)
|
||||
396 4720 y(e)o(xample)f(abo)o(v)o(e,)f(using)i(hook_country_set,)15
|
||||
b(here)20 b(is)h(the)f(corresponding)d(function)i(in)396
|
||||
4828 y(preferences/inc/hook_con\002g.)o(inc.p)o(hp)o(:)p
|
||||
Black 3842 5278 a Fa(2)p Black eop
|
||||
%%Page: 3 3
|
||||
3 2 bop Black 0 TeXcolorgray Black 2778 67 a Fa(phpGr)l(oupW)-8
|
||||
b(ar)m(e)19 b(admin/con\002g)o(.php)p Black 396 579 a
|
||||
Fb(function)44 b(country_set\($config\))396 676 y({)576
|
||||
773 y($country)f(=)i(array\()f('user_choice')e(=>)j('Users)f(Choice',)f
|
||||
('force_select')f(=>)j('Force)f(Se-)396 870 y(lectbox')g(\);)576
|
||||
967 y(while)g(\(list)g(\($key,)f($value\))h(=)h(each)f(\($country\)\))
|
||||
576 1065 y({)755 1162 y(if)g(\($config['countrylist'])d(==)k($key\))755
|
||||
1259 y({)934 1356 y($selected)f(=)g(')h(selected';)755
|
||||
1453 y(})755 1550 y(else)755 1647 y({)934 1745 y($selected)f(=)g(\224;)
|
||||
755 1842 y(})755 1939 y($descr)g(=)g(lang\($value\);)755
|
||||
2036 y($out)g(.=)h('<option)e(value="')h(.)g($key)g(.)h('"')f(.)h
|
||||
($selected)e(.)i('>')f(.)h($descr)f(.)g('</option>')f(.)i("\\n";)576
|
||||
2133 y(})576 2230 y(return)e($out;)396 2327 y(})396 2615
|
||||
y Fe(Note)20 b(again)g(the)g(template)f(v)n(alue)h(we)h(used)e(earlier)
|
||||
m(,)h({hook_country_set}.)15 b(This)20 b(causes)h(con\002g.php)c(to)k
|
||||
(look)e(for)h(a)396 2723 y(function)f(named)g(country_set\(\).)e(Since)
|
||||
j(we)h(included)d(the)j(\002le)g(with)f(this)h(function)d(via)i(the)g
|
||||
(hook_single\(\))d(call,)396 2831 y(this)k(function)d(is)k(e)o(x)o
|
||||
(ecuted.)c(It')-5 b(s)21 b(return)e(is)i(a)f(string,)g(and)g(the)g
|
||||
(function)e(prints)i(nothing)f(itself.)-2 3201 y Fc(1.3.)34
|
||||
b(hook_con\002g_v)n(alidate)r(.inc.php)39 b(\(optional\))396
|
||||
3369 y Fe(Once)20 b(the)g(admin)g(clicks)g(the)g(submit)g(b)n(utton)f
|
||||
(to)i(post)f(the)g(form,)f(we)i(can)f(optionally)e(v)n(alidate)i(their)
|
||||
g(input)f(using)396 3477 y(one)h(or)g(man)o(y)f(dif)n(ferent)f
|
||||
(functions.)h(This)h(is)h(done)e(by)h(\002rst)h(making)e(another)g
|
||||
(call)h(to)h(hook_single\(\))c(in)j(the)g(API)396 3584
|
||||
y(common)f(class.)h(This)h(time,)f(the)g(name)g(con\002g_v)n(alidate)d
|
||||
(is)k(used,)f(so)h(common)d(tries)j(to)f(include)396
|
||||
3692 y('application/inc/hook_con\002g_)o(v)n(a)o(lidate.in)o(c.p)o(hp)o
|
||||
('.)396 3842 y(If)g(this)h(\002le)g(e)o(xists,)f(it)h(sets)g(a)g(v)n
|
||||
(ar)f(to)g(tell)h(con\002g.php)d(it)i(w)o(as)i(found.)c(F)o(ollo)n
|
||||
(wing)h(then)g(are)h(functions)f(named)g(after)396 3950
|
||||
y(each)h(con\002g)f(we)i(w)o(ant)f(to)h(v)n(alidate.)e(The)h(follo)n
|
||||
(wing)e(e)o(xample)h(is)i(for)f(addressbook:)576 4130
|
||||
y Fb($GLOBALS['phpgw_info']['server']['fou)o(nd_val)o(idatio)o(n_hook)o
|
||||
('])39 b(=)45 b(True;)576 4227 y(/*)f(Check)g(a)h(specific)e(setting.)h
|
||||
(Name)g(must)g(match)g(the)g(setting.)g(*/)576 4324 y(function)f
|
||||
(ldap_contact_context\($value=\224\))576 4421 y({)755
|
||||
4518 y(if\($value)g(==)i($GLOBALS['phpgw_info']['server']['ldap)o
|
||||
(_conte)o(xt']\))755 4616 y({)934 4713 y($GLOBALS['config_error'])c(=)k
|
||||
('Contact)e(context)h(for)g(ldap)g(must)g(be)h(differ-)396
|
||||
4810 y(ent)g(from)f(the)g(context)g(used)g(for)g(accounts';)p
|
||||
Black 3842 5278 a Fa(3)p Black eop
|
||||
%%Page: 4 4
|
||||
4 3 bop Black 0 TeXcolorgray Black 2778 67 a Fa(phpGr)l(oupW)-8
|
||||
b(ar)m(e)19 b(admin/con\002g)o(.php)p Black 755 579 a
|
||||
Fb(})755 676 y(elseif\($value)43 b(==)h
|
||||
($GLOBALS['phpgw_info']['server']['ldap_g)o(roup_)o(contex)o(t']\))755
|
||||
773 y({)934 870 y($GLOBALS['config_error'])d(=)k('Contact)e(context)h
|
||||
(for)g(ldap)g(must)g(be)h(differ-)396 967 y(ent)g(from)f(the)g(context)
|
||||
g(used)g(for)g(groups';)755 1065 y(})755 1162 y(else)755
|
||||
1259 y({)934 1356 y($GLOBALS['config_error'])d(=)k(\224;)755
|
||||
1453 y(})576 1550 y(})396 1838 y Fe(Here)20 b(we)f(created)g(a)h
|
||||
(function)e(to)i(check)e(the)i(entered)e(v)n(alue)h(for)g(the)g
|
||||
(con\002g)g(item,)g(ldap_contact_conte)o(xt.)c(W)-7 b(e)21
|
||||
b(w)o(ant)396 1946 y(to)g(mak)o(e)e(sure)h(the)h(admin)e(did)h(not)g
|
||||
(set)h(this)f(v)n(alue)g(to)g(one)g(which)g(w)o(ould)f(con\003ict)h
|
||||
(with)g(another)f(con\002g)g(item,)h(used)396 2054 y(for)g(accounts)f
|
||||
(or)h(groups)f(in)h(phpGroupW)-7 b(are.)396 2204 y(con\002g.php)18
|
||||
b(calls)j(this)g(function,)d(sending)h(it)i(the)f(POST)-6
|
||||
b(ed)20 b(v)n(alue.)f(con\002g.php)f(continues,)h(adding)g(all)h(other)
|
||||
g(con\002g)396 2312 y(items)h(from)e(the)h(POST)-6 b(ed)21
|
||||
b(v)n(alues.)396 2461 y(The)f(v)n(ariable)f($GLOB)m
|
||||
(ALS['con\002g_error'])c(is)21 b(parsed)f(through)e(lang\(\),)h(then)g
|
||||
(appended)f(to)j(the)f(local)g(v)n(ariable,)396 2569
|
||||
y($error)-5 b(.)19 b(If)h(this)h(has)f(an)o(y)g(v)n(alue)f(after)h(the)
|
||||
g(POST)-6 b(ed)20 b(v)n(ariables)g(are)g(check)o(ed,)f(the)h(form)f
|
||||
(then)h(has)g(its)h({error})e(tag)396 2677 y(\002lled)i(with)f(this)h
|
||||
(result.)f(The)g(form)f(is)i(displayed)e(again,)g(with)h(the)g(error)-5
|
||||
b(.)20 b(If)g($error)e(has)j(no)e(v)n(alue,)h(con\002g.php)396
|
||||
2785 y(redirects)g(to)g(admin/inde)o(x.php.)396 2934
|
||||
y(Ho)n(we)n(v)o(er)m(,)e(there)i(is)h(one)f(more)f(function)g(that)h
|
||||
(may)g(be)g(included)e(in)j(hook_con\002g_v)n(alidate.inc)o(.ph)o(p:)
|
||||
576 3114 y Fb(/*)44 b(Check)g(all)g(settings)g(to)g(validate)g(input.)g
|
||||
(Name)g(must)g(be)h('final_validation')c(*/)576 3212
|
||||
y(function)i(final_validation\($value=\224\))576 3309
|
||||
y({)755 3406 y(if\($value['contact_repository'])d(==)k('ldap')g(&&)g
|
||||
(!$value['ldap_contact_dn']\))755 3503 y({)934 3600 y
|
||||
($GLOBALS['config_error'])d(=)k('Contact)e(dn)i(must)f(be)g(set';)755
|
||||
3697 y(})755 3794 y(elseif\($value['contact_repository'])39
|
||||
b(==)44 b('ldap')g(&&)h(!$value['ldap_contact_context']\))755
|
||||
3891 y({)934 3989 y($GLOBALS['config_error'])c(=)k('Contact)e(context)h
|
||||
(must)g(be)h(set';)755 4086 y(})755 4183 y(else)755 4280
|
||||
y({)934 4377 y($GLOBALS['config_error'])c(=)k(\224;)755
|
||||
4474 y(})576 4571 y(})p Black 3842 5278 a Fa(4)p Black
|
||||
eop
|
||||
%%Page: 5 5
|
||||
5 4 bop Black 0 TeXcolorgray Black 2778 67 a Fa(phpGr)l(oupW)-8
|
||||
b(ar)m(e)19 b(admin/con\002g)o(.php)p Black 396 579 a
|
||||
Fe(con\002g.php)f(checks)i(for)f(the)h(e)o(xistence)g(of)g(the)g
|
||||
(function)e('\002nal_v)n(alidation\(\)'.)f(This)j(function)e(can)i(be)g
|
||||
(used)g(to)396 687 y(check)g(all)g(form)g(v)n(alues)f(at)i(once.)e(It)i
|
||||
(gets)f(sent)h(the)f(entire)g($ne)n(wsettings)f(array)g(POST)-6
|
||||
b(ed)21 b(from)e(the)h(form.)f(As)i(with)396 795 y(the)f(other)g
|
||||
(functions)f(in)h(this)h(\002le,)f(\002nal_v)n(alidation\(\))d(should)j
|
||||
(set)h($GLOB)m(ALS['con\002g_error'])15 b(if)20 b(there)g(is)h(a)396
|
||||
903 y(problem.)p Black 3842 5278 a Fa(5)p Black eop
|
||||
%%Page: 6 6
|
||||
6 5 bop Black 0 TeXcolorgray Black 2778 67 a Fa(phpGr)l(oupW)-8
|
||||
b(ar)m(e)19 b(admin/con\002g)o(.php)p Black Black 3840
|
||||
5278 a(6)p Black eop
|
||||
%%Trailer
|
||||
end
|
||||
userdict /end-hook known{end-hook}if
|
||||
%%EOF
|
216
admin/doc/adminconfig.sgml
Normal file
216
admin/doc/adminconfig.sgml
Normal file
@ -0,0 +1,216 @@
|
||||
<!doctype article public "-//OASIS//DTD DocBook V3.1//EN">
|
||||
|
||||
<article lang="en">
|
||||
<!-- DocBook file was created by LyX 1.1
|
||||
See http://www.lyx.org/ for more information -->
|
||||
<artheader>
|
||||
<title>
|
||||
phpGroupWare admin/config.php
|
||||
</title>
|
||||
<abstract>
|
||||
<para>
|
||||
A brief introduction to writing hooks and templates for any application to use this admin interface, by
|
||||
</para>
|
||||
<para>
|
||||
Miles Lott <milosch@phpgroupware.org> Dec 22, 2001.
|
||||
</para>
|
||||
</abstract>
|
||||
</artheader>
|
||||
<sect1>
|
||||
<title>
|
||||
Files
|
||||
</title>
|
||||
<sect2>
|
||||
<title>
|
||||
config.tpl (required)
|
||||
</title>
|
||||
<para>
|
||||
In your application/templates/default directory, create a new template file named 'config.tpl'. This will be included by config.php and used to draw the page. This template should include a POST method form. The following template tags may be used:
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
{action_url} - A phpgw->link to config.php will be inserted.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
{title} - This will be parsed to display 'Site Configuration'.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
{th_bg},{th_text},{row_on},{row_off} - Replaced with the current theme colors.
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>
|
||||
and the following special types:
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
{lang_XXX} - Filled with lang('XXX').
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
{value_XXX} - Filled with the current value of config item 'XXX'.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
{selected_XXX} - set to '', or ' selected' if an option value is current.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
{hook_XXX} - Calls a function named XXX (will be discussed later).
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>
|
||||
Following is an example from the addressbook application:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![ CDATA [<form method="POST" action="{action_url}">
|
||||
]]><![ CDATA [<table border="0" align="center">
|
||||
]]><![ CDATA [ <tr bgcolor="{th_bg}">
|
||||
]]><![ CDATA [ <td colspan="2"><font color="{th_text}"> <b>{title}</b></font></td>
|
||||
]]><![ CDATA [ </tr> <tr bgcolor="{th_err}">
|
||||
]]><![ CDATA [ <td colspan="2"> <b>{error}</b></font></td>
|
||||
]]><![ CDATA [ </tr>
|
||||
]]><![ CDATA [<!-- END header -->
|
||||
]]><![ CDATA [<!-- BEGIN body -->
|
||||
]]><![ CDATA [ <tr bgcolor="{row_on}">
|
||||
]]><![ CDATA [ <td colspan="2"> </td>
|
||||
]]><![ CDATA [ </tr>
|
||||
]]><![ CDATA [ <tr bgcolor="{row_off}">
|
||||
]]><![ CDATA [ <td colspan="2"> <b>{lang_Addressbook}/{lang_Contact_Settings}</b></font>
|
||||
]]><![ CDATA [</td>
|
||||
]]><![ CDATA [ </tr>
|
||||
]]><![ CDATA [ <tr bgcolor="{row_on}">
|
||||
]]><![ CDATA [ <td>{lang_Contact_application}:</td>
|
||||
]]><![ CDATA [ <td><input name="newsettings[contact_application]" value="{value_contact_application}"></td>
|
||||
]]><![ CDATA [ </tr>
|
||||
]]><![ CDATA [...
|
||||
]]> </programlisting>
|
||||
<para>
|
||||
Note the fieldname, newsettings[contact_application]. This array name must be used for the form values. Next, note the value setting for this form element, {value_contact_application}. This indicates that we want the current value of the config setting, 'contact_application', to be set and displayed on the form. Lastly, look at the template element, {lang_Contact_application}. Here, the value from the lang db table will be inserted if available.
|
||||
</para>
|
||||
<para>
|
||||
Let's take a look at part of the preferences/default/config.tpl:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![ CDATA [ <tr bgcolor="{row_on}">
|
||||
]]><![ CDATA [ <td>{lang_Country_Selection} ({lang_Text_Entry}/{lang_SelectBox}):</td>
|
||||
]]><![ CDATA [ <td>
|
||||
]]><![ CDATA [ <select name="newsettings[countrylist]">
|
||||
]]><![ CDATA [{hook_country_set}
|
||||
]]><![ CDATA [ </select>
|
||||
]]><![ CDATA [ </td>
|
||||
]]><![ CDATA [ </tr>
|
||||
]]> </programlisting>
|
||||
<para>
|
||||
Here, we are adding a new element, {hook_country_set}. This brings up the next file we will need to parse this value...
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>
|
||||
hook_config.inc.php (optional)
|
||||
</title>
|
||||
<para>
|
||||
At each invocation of config.php, a call to the common class function hook_single() is made. It attempts to include a file, hook_config.inc.php as a set of code for config.php to use. In the case of the preferences example above, using hook_country_set, here is the corresponding function in preferences/inc/hook_config.inc.php:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![ CDATA [function country_set($config)
|
||||
]]><![ CDATA [{
|
||||
]]><![ CDATA [ $country = array( 'user_choice' => 'Users Choice', 'force_select' => 'Force Selectbox' );
|
||||
]]><![ CDATA [ while (list ($key, $value) = each ($country))
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ if ($config['countrylist'] == $key)
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $selected = ' selected';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ else
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $selected = '';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ $descr = lang($value);
|
||||
]]><![ CDATA [ $out .= '<option value="' . $key . '"' . $selected . '>' . $descr . '</option>' . "\n";
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ return $out;
|
||||
]]><![ CDATA [}
|
||||
]]> </programlisting>
|
||||
<para>
|
||||
Note again the template value we used earlier, {hook_country_set}. This causes config.php to look for a function named country_set(). Since we included the file with this function via the hook_single() call, this function is executed. It's return is a string, and the function prints nothing itself.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>
|
||||
hook_config_validate.inc.php (optional)
|
||||
</title>
|
||||
<para>
|
||||
Once the admin clicks the submit button to post the form, we can optionally validate their input using one or many different functions. This is done by first making another call to hook_single() in the API common class. This time, the name config_validate is used, so common tries to include 'application/inc/hook_config_validate.inc.php'.
|
||||
</para>
|
||||
<para>
|
||||
If this file exists, it sets a var to tell config.php it was found. Following then are functions named after each config we want to validate. The following example is for addressbook:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![ CDATA [ $GLOBALS['phpgw_info']['server']['found_validation_hook'] = True;
|
||||
]]><![ CDATA [
|
||||
]]><![ CDATA [ /* Check a specific setting. Name must match the setting. */
|
||||
]]><![ CDATA [ function ldap_contact_context($value='')
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ if($value == $GLOBALS['phpgw_info']['server']['ldap_context'])
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = 'Contact context for ldap must be different from the context used for accounts';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ elseif($value == $GLOBALS['phpgw_info']['server']['ldap_group_context'])
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = 'Contact context for ldap must be different from the context used for groups';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ else
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = '';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ }
|
||||
]]> </programlisting>
|
||||
<para>
|
||||
Here we created a function to check the entered value for the config item, ldap_contact_context. We want to make sure the admin did not set this value to one which would conflict with another config item, used for accounts or groups in phpGroupWare.
|
||||
</para>
|
||||
<para>
|
||||
config.php calls this function, sending it the POSTed value. config.php continues, adding all other config items from the POSTed values.
|
||||
</para>
|
||||
<para>
|
||||
The variable $GLOBALS['config_error'] is parsed through lang(), then appended to the local variable, $error. If this has any value after the POSTed variables are checked, the form then has its {error} tag filled with this result. The form is displayed again, with the error. If $error has no value, config.php redirects to admin/index.php.
|
||||
</para>
|
||||
<para>
|
||||
However, there is one more function that may be included in hook_config_validate.inc.php:
|
||||
</para>
|
||||
<programlisting>
|
||||
<![ CDATA [ /* Check all settings to validate input. Name must be 'final_validation' */
|
||||
]]><![ CDATA [ function final_validation($value='')
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ if($value['contact_repository'] == 'ldap' && !$value['ldap_contact_dn'])
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = 'Contact dn must be set';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ elseif($value['contact_repository'] == 'ldap' && !$value['ldap_contact_context'])
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = 'Contact context must be set';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ else
|
||||
]]><![ CDATA [ {
|
||||
]]><![ CDATA [ $GLOBALS['config_error'] = '';
|
||||
]]><![ CDATA [ }
|
||||
]]><![ CDATA [ }
|
||||
]]> </programlisting>
|
||||
<para>
|
||||
config.php checks for the existence of the function 'final_validation()'. This function can be used to check all form values at once. It gets sent the entire $newsettings array POSTed from the form. As with the other functions in this file, final_validation() should set $GLOBALS['config_error'] if there is a problem.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
|
||||
</article>
|
283
admin/doc/adminconfig.txt
Normal file
283
admin/doc/adminconfig.txt
Normal file
@ -0,0 +1,283 @@
|
||||
|
||||
|
||||
phpGroupWare admin/config.php
|
||||
|
||||
Abstract
|
||||
|
||||
A brief introduction to writing hooks and templates for any
|
||||
application to use this admin interface, by
|
||||
|
||||
Abstract
|
||||
|
||||
Miles Lott <milosch@phpgroupware.org> Dec 22, 2001.
|
||||
|
||||
1 Files
|
||||
|
||||
1.1 config.tpl (required)
|
||||
|
||||
In your application/templates/default directory, create a
|
||||
new template file named 'config.tpl'. This will be included
|
||||
by config.php and used to draw the page. This template should
|
||||
include a POST method form. The following template tags
|
||||
may be used:
|
||||
|
||||
1. {action_url} - A phpgw->link to config.php will be inserted.
|
||||
|
||||
2. {title} - This will be parsed to display 'Site Configuration'.
|
||||
|
||||
3. {th_bg},{th_text},{row_on},{row_off} - Replaced with the
|
||||
current theme colors.
|
||||
|
||||
and the following special types:
|
||||
|
||||
1. {lang_XXX} - Filled with lang('XXX').
|
||||
|
||||
2. {value_XXX} - Filled with the current value of config item
|
||||
'XXX'.
|
||||
|
||||
3. {selected_XXX} - set to '', or ' selected' if an option
|
||||
value is current.
|
||||
|
||||
4. {hook_XXX} - Calls a function named XXX (will be discussed
|
||||
later).
|
||||
|
||||
Following is an example from the addressbook application:
|
||||
|
||||
<form method="POST" action="{action_url}">
|
||||
|
||||
<table border="0" align="center">
|
||||
|
||||
<tr bgcolor="{th_bg}">
|
||||
|
||||
<td colspan="2"><font color="{th_text}"> <b>{title}</b></font></td>
|
||||
|
||||
</tr> <tr bgcolor="{th_err}">
|
||||
|
||||
<td colspan="2"> <b>{error}</b></font></td>
|
||||
|
||||
</tr>
|
||||
|
||||
<!-- END header -->
|
||||
|
||||
<!-- BEGIN body -->
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
|
||||
<td colspan="2"> </td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr bgcolor="{row_off}">
|
||||
|
||||
<td colspan="2"> <b>{lang_Addressbook}/{lang_Contact_Settings}</b></font>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
|
||||
<td>{lang_Contact_application}:</td>
|
||||
|
||||
<td><input name="newsettings[contact_application]" value="{value_contact_application}"></td>
|
||||
|
||||
</tr>
|
||||
|
||||
...
|
||||
|
||||
Note the fieldname, newsettings[contact_application]. This
|
||||
array name must be used for the form values. Next, note
|
||||
the value setting for this form element, {value_contact_application}.
|
||||
This indicates that we want the current value of the config
|
||||
setting, 'contact_application', to be set and displayed
|
||||
on the form. Lastly, look at the template element, {lang_Contact_application}.
|
||||
Here, the value from the lang db table will be inserted
|
||||
if available.
|
||||
|
||||
Let's take a look at part of the preferences/default/config.tpl:
|
||||
|
||||
<tr bgcolor="{row_on}">
|
||||
|
||||
<td>{lang_Country_Selection} ({lang_Text_Entry}/{lang_SelectBox}):</td>
|
||||
|
||||
<td>
|
||||
|
||||
<select name="newsettings[countrylist]">
|
||||
|
||||
{hook_country_set}
|
||||
|
||||
</select>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
Here, we are adding a new element, {hook_country_set}. This
|
||||
brings up the next file we will need to parse this value...
|
||||
|
||||
1.2 hook_config.inc.php (optional)
|
||||
|
||||
At each invocation of config.php, a call to the common class
|
||||
function hook_single() is made. It attempts to include a
|
||||
file, hook_config.inc.php as a set of code for config.php
|
||||
to use. In the case of the preferences example above, using
|
||||
hook_country_set, here is the corresponding function in
|
||||
preferences/inc/hook_config.inc.php:
|
||||
|
||||
function country_set($config)
|
||||
|
||||
{
|
||||
|
||||
$country = array( 'user_choice' => 'Users Choice', 'force_select'
|
||||
=> 'Force Selectbox' );
|
||||
|
||||
while (list ($key, $value) = each ($country))
|
||||
|
||||
{
|
||||
|
||||
if ($config['countrylist'] == $key)
|
||||
|
||||
{
|
||||
|
||||
$selected = ' selected';
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
$selected = '';
|
||||
|
||||
}
|
||||
|
||||
$descr = lang($value);
|
||||
|
||||
$out .= '<option value="' . $key . '"' . $selected
|
||||
. '>' . $descr . '</option>' . "\n";
|
||||
|
||||
}
|
||||
|
||||
return $out;
|
||||
|
||||
}
|
||||
|
||||
Note again the template value we used earlier, {hook_country_set}.
|
||||
This causes config.php to look for a function named country_set().
|
||||
Since we included the file with this function via the hook_single()
|
||||
call, this function is executed. It's return is a string,
|
||||
and the function prints nothing itself.
|
||||
|
||||
1.3 hook_config_validate.inc.php (optional)
|
||||
|
||||
Once the admin clicks the submit button to post the form,
|
||||
we can optionally validate their input using one or many
|
||||
different functions. This is done by first making another
|
||||
call to hook_single() in the API common class. This time,
|
||||
the name config_validate is used, so common tries to include
|
||||
'application/inc/hook_config_validate.inc.php'.
|
||||
|
||||
If this file exists, it sets a var to tell config.php it
|
||||
was found. Following then are functions named after each
|
||||
config we want to validate. The following example is for
|
||||
addressbook:
|
||||
|
||||
$GLOBALS['phpgw_info']['server']['found_validation_hook']
|
||||
= True;
|
||||
|
||||
/* Check a specific setting. Name must match the setting.
|
||||
*/
|
||||
|
||||
function ldap_contact_context($value='')
|
||||
|
||||
{
|
||||
|
||||
if($value == $GLOBALS['phpgw_info']['server']['ldap_context'])
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context for
|
||||
ldap must be different from the context used for accounts';
|
||||
|
||||
}
|
||||
|
||||
elseif($value == $GLOBALS['phpgw_info']['server']['ldap_group_context'])
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context for
|
||||
ldap must be different from the context used for groups';
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = '';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Here we created a function to check the entered value for
|
||||
the config item, ldap_contact_context. We want to make sure
|
||||
the admin did not set this value to one which would conflict
|
||||
with another config item, used for accounts or groups in
|
||||
phpGroupWare.
|
||||
|
||||
config.php calls this function, sending it the POSTed value.
|
||||
config.php continues, adding all other config items from
|
||||
the POSTed values.
|
||||
|
||||
The variable $GLOBALS['config_error'] is parsed through lang(),
|
||||
then appended to the local variable, $error. If this has
|
||||
any value after the POSTed variables are checked, the form
|
||||
then has its {error} tag filled with this result. The form
|
||||
is displayed again, with the error. If $error has no value,
|
||||
config.php redirects to admin/index.php.
|
||||
|
||||
However, there is one more function that may be included
|
||||
in hook_config_validate.inc.php:
|
||||
|
||||
/* Check all settings to validate input. Name must be
|
||||
'final_validation' */
|
||||
|
||||
function final_validation($value='')
|
||||
|
||||
{
|
||||
|
||||
if($value['contact_repository'] == 'ldap' && !$value['ldap_contact_dn'])
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact dn must be
|
||||
set';
|
||||
|
||||
}
|
||||
|
||||
elseif($value['contact_repository'] == 'ldap' &&
|
||||
!$value['ldap_contact_context'])
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = 'Contact context must
|
||||
be set';
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
$GLOBALS['config_error'] = '';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
config.php checks for the existence of the function 'final_validation()'.
|
||||
This function can be used to check all form values at once.
|
||||
It gets sent the entire $newsettings array POSTed from the
|
||||
form. As with the other functions in this file, final_validation()
|
||||
should set $GLOBALS['config_error'] if there is a problem.
|
Loading…
Reference in New Issue
Block a user