# $Id: Conf.pm,v 1.8 2004/07/28 15:44:20 gwolf Exp $
######################################                                           
# Comas - Conference Management System
######################################
# Copyright 2003 CONSOL
# Congreso Nacional de Software Libre (http://www.consol.org.mx/)
#   Gunnar Wolf <gwolf@gwolf.cx>
#   Manuel Rabade <mig@mig-29.net>
#
# 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.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
######################################

######################################
# Module: Comas::Conf
# Comas' configuration management routines

use strict;
use warnings;
use Carp;

package Comas::Conf;

BEGIN {
    our (@ISA, @EXPORT_OK, %EXPORT_TAGS);
    use Exporter;
    @ISA = qw(Exporter);
    @EXPORT_OK = qw(conf_entries get_conf get_info new_conf set_conf 
                    get_db_conf init_db_conf);
    %EXPORT_TAGS = (read => [qw(conf_entries get_conf get_info)], 
		    write => [qw(new_conf set_conf)],
		    init => [qw(init_db_conf)]);
}

=head1 NAME

Comas::Conf - Comas' configuration management routines

=head1 SYNOPSIS

Comas::Conf is not supposed to be called by itself - It is meant to be
called from within Comas::DB exporting its functions to it. Functions in
this package are meant to be called as Comas::DB methods - If this is not
how you plan to use them, you are on your own ;-)

Configuration entries have three parts: Name, description and value. The name 
is the identifier for a configuration entry, and will be denoted as C<$name>.
The description is the human-readable description for managing this entry, and
will be denoted as C<$descr>. The value stored for the entry will be denoted
as C<$value>.

If a command returns success/failure, number of rows affected or other
similar information, it will be denoted by C<$ok>.

=head2 RETREIVING INFORMATION

In order to retrieve the value for a configuration option, use:

    $value = get_conf($db, $name);

If you want fuller information (the description as well as the value) use:

    ($descr, $value) = get_info($db, $name);

To show all the existing configuration entries:

    @name = $conf_entries($db);

=head2 STORING INFORMATION

To change the value for an existing configuration option:

    $ok = set_conf($db, $name, $value);

Note that this will NOT create the configuration option (C<$ok> will be false).
If you want to create a new configuration option, use:

    $ok = new_conf($db, $name, $descr, $value);

=head2 INITIALIZING THE DATABASE

The database configuration can be initialized to the minimum defaults by using:

    $ok = init_db_conf($db);

Note that this operation will B<fail> if any of the basic system configuration 
keys are set. This is an operation that should only be run at system 
installation time. The default values are:

B<attendees_recover_passwd_from>: comas@localhost.localdomain

B<comas_url>: /comas

B<conference_url>: http://my.conference/

B<max_authors_x_proposal>: 0

B<max_proposals_x_person>:0

B<priv_person_types>: 4

B<prop_files_path>: /home/comas/material/

B<proposal_modif_mail_from>: comas@localhost.localdomain

B<proposal_new_mail_from>: comas@localhost.localdomain

B<proposal_revision_mail_from>: comas@localhost.localdomain

B<proposals_accepted_id>: 10

B<proposals_new_max_date>: 1980-01-01 00:00

B<smtp_host>: localhost

=head1 EXPORTS

    conf_entries, get_conf, get_info, new_conf, set_conf

All of them are not exported by default - you must explicitly
import them, or call them from the Comas::Conf namespace. They are 
grouped in the 'read' (conf_entries, get_conf, get_info) and 'write'
(new_conf, set_conf) tags - you can import them by using:

    use Comas::Conf qw(:read);
    use Comas::Conf qw(:write);
    use Comas::Conf qw(:read :write);

=head1 SEE ALSO

L<Comas::DB|Comas::DB> for OO invocation

L<Exporter|Exporter> for details on importing/exporting symbols 

=head1 AUTHOR

Gunnar Wolf, gwolf@gwolf.cx

Manuel Rabade, mig@mig-29.net

Comas has been developed for CONSOL, Congreso Nacional de Software Libre,
http://www.consol.org.mx/

=head1 COPYRIGHT

Copyright 2003 Gunnar Wolf and Manuel Rabade

This library is free software, you can redistribute it and/or modify it
under the terms of the GPL version 2 or later.

=cut

#################################################################
# Class Metods

my $lastError;

sub lastError {
    return $lastError;
}

sub setLastError {
    $lastError = shift;
}

#################################################################
# Methods

sub get_conf {
    # Receives a Comas::DB object as its first parameter and the name of
    # a configuration option as its second parameter, returns its value
    my ($db, $name, $sth);
    $db = shift;
    $name = shift;
    unless ($sth = $db->prepare('SELECT value FROM config WHERE name = ?') and
	    _ck_sth_ex($sth->execute($name))) {
        setLastError(300);
	return undef; 
    }
    return $sth->fetchrow_array();
}

sub set_conf {
    # Sets a configuration value in the database.
    # Receives a Comas::DB object as its first parameter, the configuration
    # name as its second parameter and its new value as the third.
    # If the configuration option referred does not exist, set_conf will NOT
    # create it - Use new_conf(...) to create a new configuration entry.
    my ($db, $name, $value, $sth, $res);
    $db = shift;
    $name = shift;
    $value = shift;
    unless ($sth = $db->prepare('UPDATE config SET value = ? WHERE name = ?')) {
        setLastError(301);
	return undef;
    }
    $res = $sth->execute($value, $name);
    return $res eq '0E0' ? undef : $res;
}

sub new_conf {
    # Creates a new configuration entry in the database.
    # Receives a Comas::DB object as its first parameter, the configuration 
    # name as the second, the description as the third and the initial value
    # as its fourth parameter.
    # Returns true if the entry was created successfully, undef if it failed
    my ($db, $name, $descr, $value, $sth);
    $db = shift;
    $name = shift;
    $descr = shift;
    $value = shift;
    unless ($sth = $db->prepare('INSERT INTO config (name, descr, value) VALUES (?, ?, ?)')) {
        setLastError(302);
	return undef;
    }
    return $sth->execute($name, $descr, $value);
}

sub get_info {
    # Returns the description and current value for a configuration entry.
    # Receives a Comas::DB object as its first parameter, and the entry's
    # name as its second parameter.
    my ($db, $name, $sth, $descr, $value);
    $db = shift;
    $name = shift;
    unless ($sth = $db->prepare('SELECT descr, value FROM config WHERE name = ?') 
	    and _ck_sth_ex($sth->execute($name))) {
        setLastError(300);
	return undef;
    }
    return $sth->fetchrow_array();
}

sub conf_entries {
    # Returns the list of defined configuration entries.
    # Receives a Comas::DB object as its first parameter.
    my ($db, @names, $sth);
    $db = shift;
    @names = ();
    unless ($sth = $db->prepare('SELECT name FROM config ORDER BY name') 
	    and _ck_sth_ex($sth->execute())) {
        setLastError(303);
	return undef;
    }
    while (my @row = $sth->fetchrow_array()) {
	push(@names,$row[0]);
    }
    return @names;
}

sub init_db_conf {
    my ($db, %defaults, $sth);
    $db = shift;
    %defaults = ('proposal_new_mail_from' => ['Address with which to send the mail when a new proposal is received', 'comas@localhost.localdomain'],
		 'max_authors_x_proposal' => ['The limit of authors per proposal', '0'],
		 'max_proposals_x_person' => ['The limit of proposals per person','0'],
		 'proposals_new_max_date' => ['The last date for sending a proposal, the format is YYYY-MM-DD HH:MM (in 24 hours style)', '1980-01-01 00:00'],
		 'priv_person_types' => ['The privileged person types (an administrator should set this in a person), separated by ,', '4'],
		 'proposal_modif_mail_from' => ['Address with which to send the mail to the academic committee when the proposal is modified by the author', 'comas@localhost.localdomain'],
		 'smtp_host' => ['SMTP server', 'localhost'],
		 'conference_url' => ['URL of the conference\'s main Web page', 'http://my.conference/'],
		 'proposal_revision_mail_from' => ['Address with which to send the mail when the proposal is revised by the academic committee', 'comas@localhost.localdomain'],
		 'attendees_recover_passwd_from' => ['Address with which to send the mail with the new password when requested', 'comas@localhost.localdomain'],
		 'comas_url' => ['Path to Comas\' root page (can be relative to the host)', '/comas'],
		 'prop_files_path' => ['Path of the material for the proposals', '/home/comas/material/'],
		 'proposals_accepted_id' => ['The id of the accepted proposals', '10']);

    $db->begin_work;

    unless ($sth = $db->prepare('INSERT INTO config (key, value, descr) VALUES
            ?, ?, ?')) {
	$db->rollback;
	warn 'Error preparing insertion';
	return undef;
    }
    for my $key (keys %defaults) {
	unless ($sth->execute($key, $defaults{$key}[0], $defaults{$key}[1])) {
	    $db->rollback;
	    warn "Error inserting key $key into config - Already existing?";
	    return undef;	    
	}
    }

    $db->commit;
    return 1;
}

###########################################################################
# Internal functions, not for human consumption

sub _ck_sth_ex {
    # Transforms a STH return value into something more similar to what we
    # use/need
    my $res = shift;

    # We define wrong as undef, 0E0 or less than 0
    return undef if !defined $res or $res == '0E0' or $res < 0;

    # Ok, fine, return the received value.
    return $res;
}

1;

# $Log: Conf.pm,v $
# Revision 1.8  2004/07/28 15:44:20  gwolf
# Added a function to initialize an empty database
#
# Revision 1.7  2003/12/21 04:27:44  mig
# - Ups .. ya no existe 'setLastMsg'.
#
# Revision 1.6  2003/12/20 04:14:51  mig
# - Agrego tags Id y Log que expanda el CVS
#
