~kosova/+junk/tuxfamily-twiki

« back to all changes in this revision

Viewing changes to foswiki/lib/Foswiki/Configure/Load.pm

  • Committer: James Michael DuPont
  • Date: 2009-07-18 19:58:49 UTC
  • Revision ID: jamesmikedupont@gmail.com-20090718195849-vgbmaht2ys791uo2
added foswiki

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# See bottom of file for license and copyright information
 
2
 
 
3
=begin TML
 
4
 
 
5
---+ package Foswiki::Configure::Load
 
6
 
 
7
---++ Purpose
 
8
 
 
9
This module consists of just a single subroutine =readConfig=.  It allows to
 
10
safely modify configuration variables _for one single run_ without affecting
 
11
normal Foswiki operation.
 
12
 
 
13
=cut
 
14
 
 
15
package Foswiki::Configure::Load;
 
16
 
 
17
our $TRUE = 1;
 
18
 
 
19
=begin TML
 
20
 
 
21
---++ StaticMethod readConfig()
 
22
 
 
23
In normal Foswiki operations as a web server this routine is called by the
 
24
=BEGIN= block of =Foswiki.pm=.  However, when benchmarking/debugging it can be
 
25
replaced by custom code which sets the configuration hash.  To prevent us from
 
26
overriding the custom code again, we use an "unconfigurable" key
 
27
=$cfg{ConfigurationFinished}= as an indicator.
 
28
 
 
29
Note that this method is called by Foswiki and configure, and *only* reads
 
30
Foswiki.spec= to get defaults. Other spec files (those for extensions) are
 
31
*not* read.
 
32
 
 
33
The assumption is that =configure= will be run when an extension is installed,
 
34
and that will add the config values to LocalSite.cfg, so no defaults are
 
35
needed. Foswiki.spec is still read because so much of the core code doesn't
 
36
provide defaults, and it would be silly to have them in two places anyway.
 
37
 
 
38
=cut
 
39
 
 
40
sub readConfig {
 
41
    return if $Foswiki::cfg{ConfigurationFinished};
 
42
 
 
43
    # Read LocalSite.cfg
 
44
    unless ( do 'Foswiki.spec' ) {
 
45
        die <<GOLLYGOSH;
 
46
Content-type: text/plain
 
47
 
 
48
Perl error when reading Foswiki.spec: $@
 
49
Please inform the site admin.
 
50
GOLLYGOSH
 
51
        exit 1;
 
52
    }
 
53
 
 
54
    # Read LocalSite.cfg
 
55
    unless ( do 'LocalSite.cfg' ) {
 
56
        die <<GOLLYGOSH;
 
57
Content-type: text/plain
 
58
 
 
59
Perl error when reading LocalSite.cfg: $@
 
60
Please inform the site admin.
 
61
GOLLYGOSH
 
62
        exit 1;
 
63
    }
 
64
 
 
65
    # If we got this far without definitions for key variables, then
 
66
    # we need to default them. otherwise we get peppered with
 
67
    # 'uninitialised variable' alerts later.
 
68
 
 
69
    foreach my $var qw( DataDir DefaultUrlHost PubUrlPath WorkingDir
 
70
      PubDir TemplateDir ScriptUrlPath LocalesDir ) {
 
71
 
 
72
        # We can't do this, because it prevents Foswiki being run without
 
73
        # a LocalSite.cfg, which we don't want
 
74
        # die "$var must be defined in LocalSite.cfg"
 
75
        #  unless( defined $Foswiki::cfg{$var} );
 
76
        $Foswiki::cfg{$var} = 'NOT SET' unless defined $Foswiki::cfg{$var};
 
77
      }
 
78
 
 
79
      # Expand references to $Foswiki::cfg vars embedded in the values of
 
80
      # other $Foswiki::cfg vars.
 
81
      expand( \%Foswiki::cfg );
 
82
 
 
83
    $Foswiki::cfg{ConfigurationFinished} = 1;
 
84
 
 
85
    # Alias TWiki cfg to Foswiki cfg for plugins and contribs
 
86
    *{'TWiki::cfg'} = *{'Foswiki::cfg'};
 
87
}
 
88
 
 
89
sub expand {
 
90
    my $hash = shift;
 
91
 
 
92
    foreach ( values %$hash ) {
 
93
        next unless $_;
 
94
        if ( ref($_) eq 'HASH' ) {
 
95
            expand( \%$_ );
 
96
        }
 
97
        else {
 
98
            s/(\$Foswiki::cfg{[[A-Za-z0-9{}]+})/eval $1||'undef'/ge;
 
99
        }
 
100
    }
 
101
}
 
102
 
 
103
=begin TML
 
104
 
 
105
---++ StaticMethod expandValue($string) -> $boolean
 
106
 
 
107
Expands references to Foswiki configuration items which occur in the
 
108
value of other configuration items.  Use expand($hashref) if the item
 
109
is not a plain scalar.
 
110
 
 
111
Happens to return true if something has been expanded, though I don't
 
112
know whether you would want that.  The replacement is done in-place,
 
113
 
 
114
=cut
 
115
 
 
116
sub expandValue {
 
117
    $_[0] =~ s/(\$Foswiki::cfg{[[A-Za-z0-9{}]+})/eval $1||'undef'/ge;
 
118
}
 
119
 
 
120
=begin TML
 
121
 
 
122
---++ StaticMethod readDefaults() -> \@errors
 
123
 
 
124
This is only called by =configure= to initialise the Foswiki config hash with
 
125
default values from the .spec files.
 
126
 
 
127
Normally all configuration values come from LocalSite.cfg. However when
 
128
=configure= runs it has to get default values for config vars that have not
 
129
yet been saved to =LocalSite.cfg=.
 
130
 
 
131
Returns a reference to a list of the errors it saw.
 
132
 
 
133
SEE ALSO: Foswiki::Configure::FoswikiCfg::load
 
134
 
 
135
=cut
 
136
 
 
137
sub readDefaults {
 
138
    my %read = ();
 
139
    my @errors;
 
140
 
 
141
    eval {
 
142
        do 'Foswiki.spec';
 
143
        $read{'Foswiki.spec'} = $INC{'Foswiki.spec'};
 
144
    };
 
145
    push( @errors, $@ ) if ($@);
 
146
    foreach my $dir (@INC) {
 
147
        _loadDefaultsFrom( "$dir/Foswiki/Plugins", $root, \%read, \@errors );
 
148
        _loadDefaultsFrom( "$dir/Foswiki/Contrib", $root, \%read, \@errors );
 
149
        _loadDefaultsFrom( "$dir/TWiki/Plugins",   $root, \%read, \@errors );
 
150
        _loadDefaultsFrom( "$dir/TWiki/Contrib",   $root, \%read, \@errors );
 
151
    }
 
152
    if ( defined %TWiki::cfg ) {
 
153
 
 
154
        # We had some TWiki plugins, need to map their config to Foswiki
 
155
        sub mergeHash {
 
156
 
 
157
          # Merges the keys in the right hashref to the ones in the left hashref
 
158
            my ( $left, $right, $errors ) = @_;
 
159
            while ( my ( $key, $value ) = each %$right ) {
 
160
                if ( exists $left->{$key} ) {
 
161
                    if ( ref($value) ne ref( $left->{$key} ) ) {
 
162
                        push @$errors,
 
163
                            'Trying to overwrite $Foswiki::cfg{' 
 
164
                          . $key
 
165
                          . '} with its $TWiki::cfg version ('
 
166
                          . $value . ')';
 
167
                    }
 
168
                    elsif ( ref($value) eq 'SCALAR' ) {
 
169
                        $left->{$key} = $value;
 
170
                    }
 
171
                    elsif ( ref($value) eq 'HASH' ) {
 
172
                        $left->{$key} =
 
173
                          mergeHash( $left->{$key}, $value, $errors );
 
174
                    }
 
175
                    elsif ( ref($value) eq 'ARRAY' ) {
 
176
 
 
177
                        # It's an array. try to be smart
 
178
                        # SMELL: Ideally, it should keep order too
 
179
                        foreach my $item (@$value) {
 
180
                            unless ( grep /^$item$/, @{ $left->{$key} } ) {
 
181
 
 
182
                         # The item isn't in the current list, add it at the end
 
183
                                unshift @{ $left->{$key} }, $item;
 
184
                            }
 
185
                        }
 
186
                    }
 
187
                    else {
 
188
 
 
189
                        # It's something else (GLOB, coderef, ...)
 
190
                        push @$errors,
 
191
                            '$TWiki::cfg{' 
 
192
                          . $key
 
193
                          . '} is a reference to a'
 
194
                          . ref($value)
 
195
                          . '. No idea how to merge that, sorry.';
 
196
                    }
 
197
                }
 
198
                else {
 
199
 
 
200
                    # We don't already have such a key in the Foswiki scope
 
201
                    $left->{$key} = $value;
 
202
                }
 
203
            }
 
204
            return $left;
 
205
        }
 
206
        mergeHash \%Foswiki::cfg, \%TWiki::cfg, \@errors;
 
207
    }    # define %TWiki::cfg
 
208
 
 
209
    return \@errors;
 
210
}
 
211
 
 
212
sub _loadDefaultsFrom {
 
213
    my ( $dir, $root, $read, $errors ) = @_;
 
214
 
 
215
    return unless opendir( D, $dir );
 
216
    foreach my $extension ( grep { !/^\./ } readdir D ) {
 
217
        $extension =~ /(.*)/;
 
218
        $extension = $1;    # untaint
 
219
        next if $read->{$extension};
 
220
        my $file = "$dir/$extension/Config.spec";
 
221
        next unless -e $file;
 
222
        eval { do $file; };
 
223
        push( @$errors, $@ ) if ($@);
 
224
        $read->{$extension} = $file;
 
225
    }
 
226
    closedir(D);
 
227
}
 
228
 
 
229
1;
 
230
__DATA__
 
231
# Module of Foswiki - The Free and Open Source Wiki, http://foswiki.org/
 
232
#
 
233
# Copyright (C) 2008 Foswiki Contributors. Foswiki Contributors
 
234
# are listed in the AUTHORS file in the root of this distribution.
 
235
# NOTE: Please extend that file, not this notice.
 
236
#
 
237
# Additional copyrights apply to some or all of the code in this
 
238
# file as follows:
 
239
#
 
240
# Copyright (C) 1999-2006 TWiki Contributors. All Rights Reserved.
 
241
# TWiki Contributors are listed in the AUTHORS file in the root of
 
242
# this distribution. NOTE: Please extend that file, not this notice.
 
243
#
 
244
# This program is free software; you can redistribute it and/or
 
245
# modify it under the terms of the GNU General Public License
 
246
# as published by the Free Software Foundation; either version 2
 
247
# of the License, or (at your option) any later version. For
 
248
# more details read LICENSE in the root of this distribution.
 
249
#
 
250
# This program is distributed in the hope that it will be useful,
 
251
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
252
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
253
#
 
254
# As per the GPL, removal of this notice is prohibited.