##########description################################################################# # # Copyright (C) Daniel Guermeur - 1999-2001 # Copyright (C) Metadot Corporation - 2001-2005 # # This file is part of Metadot Portal Server software $Name: Release_6_4_r3 $ # # Metadot Portal Server software 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. # # Metadot Portal Server software 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 # Metadot Portal Server; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # For more information, please contact info@metadot.com. # ############################################################################ package CMSDocument; use strict; use GizmoBuilder; use Gizmo::CMSDocument::Version; use Metadot::MIME::Types; use Metadot::Controllable; use Utility; use Metadot::Notifiable; use vars qw(@ISA); @ISA=qw(GizmoBuilder Metadot::Rateable Metadot::Controllable Metadot::Notifiable); my $version = "4.6"; sub get_version { return $version; } use Metadot qw($USER $SESSION %FORM $PARAMS); #################################### sub new { my $proto = shift; my $class = ref($proto) || $proto; my $args = $class->normalize_constructor_args(shift); my $id = $args->{id}; my $self; if (defined ($id)){ return $class->restore($id); } else { $self = $class->SUPER::new($args); } $self->{cool}='No'; $self->{is_a} = __PACKAGE__; $self->_form_initialize(); $self->set_field_info ( # "name", "CMS Document Name", 1, "name", "" . $self->get_gizmo_name() . " Name", 1, "file1", "File Name", 1, "description", "Description", 1, "t4", "Check in Comment", 1, "t2", "Mod User ID", 0, "t1", "File Mofidication Date" , 0, "t9", "File Checked out?", 0, "cool", "Star this " . $self->get_gizmo_name() . "?", 0, ## (qp) "t6", "Revision major.minor", 0, ); $self->{display_wrapped} = { show => 1, }; bless ($self, $class); # reconsecrate return $self; } # this class tries to save a FileHandle into file1, which breaks Oracle sub add { my $self = shift; $self->_fix_file1(); return $self->SUPER::add(@_); } # this class tries to save a FileHandle into file1, which breaks Oracle sub save { my $self = shift; $self->_fix_file1(); return $self->SUPER::save(@_); } # ensures that file1 is a string sub _fix_file1 { my $self = shift; $self->{file1} = "$self->{file1}"; return $self; } sub customize_permissions { my $self = shift; my $ac = shift; $self->SUPER::customize_permissions($ac); # checkin/checkout $ac->add_bundle('CHECKINOUT', 'Checkin
Checkout', '8','2'); $ac->add_op('CHECKINOUT', 'cancelcheckout'); $ac->add_op('CHECKINOUT', 'checkout'); $ac->add_op('CHECKINOUT', 'modify_existing'); $ac->add_op('CHECKINOUT', 'save_existing'); $ac->add_op('CHECKINOUT', 'force_download'); Metadot::Notifiable->customize_permissions($ac); return $ac; } sub get_gizmo_name { my $self = shift; return "Document With Version Control"; } sub set_checked_out_status { my $self = shift; $self->{t9} = shift; } sub get_checked_out_status { my $self = shift; return $self->{t9}; } sub get_checkout_owner { my $self = shift; return $self->{t2}; } sub set_checkout_owner { my $self = shift; $self->{t2} = shift; } sub get_current_version { my $self = shift; return $self->{t3}; } ## (qp) to support major.minor format sub get_next_version { my $self = shift; my $v = shift; my $ret = $v; if ( $v =~ /(\d+)\.(\d+)/ ) { my $major = $1; my $minor = $2; $minor += 1; $ret = "$major\.$minor"; } return $ret; } sub set_current_version { my $self = shift; $self->{t3} = shift; } sub get_current_version_iid { my $self = shift; return $self->{i1}; } sub set_current_version_iid { my $self = shift; $self->{i1} = shift; } sub set_downloaded_state { my $self = shift; $self->{t5} = shift; } sub get_downloaded_state { my $self = shift; return $self->{t5}; } sub get_version_object { my $self = shift; my $version_iid = shift || $self->get_current_version_iid(); return Version->new($version_iid); } sub get_previous_versions { my $self = shift; my @results = (); my $current_version_iid = $self->get_current_version_iid(); my $parent_iid = $self->get_iid(); if (defined($parent_iid) && defined($current_version_iid)) { my $sth = DBAccess->sqlSelectMany("iid", "instance", "parentiid = $parent_iid and iid != $current_version_iid order by CreationDate desc"); while (my ($child_iid) = $sth->fetchrow_array()) { push @results, Version->new($child_iid); } $sth->finish; } return \@results; } sub _form_initialize { my $self = shift; $self->{fields}->{t9}->{formtype} = "radio"; $self->{fields}->{t9}->{selectsize} = "1"; $self->{fields}->{t10}->{formtype} = "checkbox"; $self->{fields}->{t10}->{selectsize} = "1"; $self->{fields}->{t4}->{formtype} = "mediumtext"; # (qp) $self->{fields}->{t6}->{formtype} = "text"; } #aju # sub www_show { sub show { my $self = shift; $self->debug_msg(3, "CMSDocument::www_show()"); my $iid = $self->get_iid(); my $name = $self->get_name(); my $content; my $current_version = $self->get_current_version(); my $imageslocation = $PARAMS->{'imageslocation'}; my $current_version_iid = $self->get_current_version_iid(); my $version = $self->get_version_object(); my $last_checkin_time = $version->get_modification_time(); my $last_checkin_name = $USER->get_fullname_from_uid($version->get_uid_of_modifier()); my $currfilename = $version->get_file_1(); my $file_icon = $version->get_file_1_icon(); my $current_remark = $version->get_comment(); $current_remark =~ s/\n/
/gi if $current_remark ; $content .= "
" ; $content .= "
$name
"; $content .= "
".$self->get_check_buttons()."
" ; $content .= "
"; $content .= " "; $content .= "" ; $content .= "" ; $content .= "" ; $content .= "" ; $content .= ""; $content .= ""; $content .= ""; # $content .= ""; my $previous_versions = Version->show_previous($iid, $current_version_iid); if ($previous_versions) { $content .= ""; $content .= ""; } $content .= "
Current version:" ; $content .= "$currfilename - v$current_version" ; $content .= "  " ; $content .= $file_icon; $content .= "
Check in comment:$current_remark
Last modification:$last_checkin_time
Last checked in by:$last_checkin_name
View all Versions

Previous versions:
 
" ; $content .= $previous_versions; $content .= "
"; if ($FORM{checkingout} eq 'yes') { unless ($self->get_downloaded_state() eq 'yes') { $content .= $self->get_download_javascript(); $self->set_downloaded_state('yes'); $self->save(); } } return $content; } sub exec_show { my ($self, $context) = @_; if ($FORM{checkingout} eq 'yes') { unless ($self->get_downloaded_state() eq 'yes') { $self->set_downloaded_state('yes'); $self->save(); } } return $self->SUPER::exec_show($context); } sub get_download_javascript { my $self = shift; my $rand = rand; my $current_version_iid = $self->get_current_version_iid(); my $result = < EOM ; return $result; } sub is_checked_out { my $self = shift; return ($self->get_checked_out_status() eq "Yes"); } sub get_check_buttons () { my $self = shift; $self->debug_msg(3, "CMSDocument::get_check_buttons()"); my $imageslocation = $PARAMS->{'imageslocation'} ; my $iid = $self->defined_or_exit($self->id,"id is missing."); my $content = "" ; if ($self->is_checked_out()) { my $checkout_owner = $self->get_checkout_owner(); my $checkout_owner_name = $USER->get_fullname_from_uid($checkout_owner); $content .= "is currently checked out by: $checkout_owner_name
"; if ($checkout_owner == $USER->{uid}) { $content .= "Check in"; } if (($checkout_owner == $USER->{uid}) || ($self->is_allowed_to_do('modify', $USER))) { $content .= " " ; $content .= "Cancel Checkout"; } } else { if ($self->is_allowed_to_do('checkout', $USER)) { $content .= "Check out"; } } return $content ; } sub www_modify { my $self = shift; my $errormsg = shift; $self->debug_msg(3, "CMSDocument::www_modify()"); my $iid = $self->id(); my $isa = $self->is_a(); my $target = $SESSION->{referer}; if (!defined $iid){ $self->click_back ("Error:", "id is missing."); exit(0); } my ($checkout_owner, $checkout_status) = DBAccess->sqlSelect("t2,t9", "instance", "iid=$iid"); $errormsg = $errormsg ? "

Please correct the following error(s):

\n$errormsg

\n" : ""; my $form = $self->show_edit_form("Modify " . $self->get_gizmo_name() . " information"); my $content = "" ; # JSForm my $form_tag = "

" ; if (defined($self->{jsform})) { $content .= $self->{jsform}->get_form($form_tag, 1) ; } else { $content .= $form_tag ; } # JSForm $content .= " ".$self->make_hidden()."
$errormsg $form

 
"; $self->print_form($content); } sub www_modify_existing { my $self = shift; my $name = $self->get_name(); my $errormsg = shift; $self->debug_msg(3, "CMSDocument::www_modify_existing()"); my $iid = $self->id(); my $isa = $self->is_a(); my $target = $SESSION->{referer}; if (!defined $iid){ $self->click_back ("Error:", "id is missing."); exit(0); } $errormsg = $errormsg ? "

Please correct the following error(s):

\n$errormsg

\n" : ""; # my $form = $self->show_edit_form_modify("$name
Checking in an update to $isa"); my $form = $self->show_edit_form_modify("Checking in document update"); my $content = "" ; # JSForm my $form_tag = "

" ; if (defined($self->{jsform})) { $content .= $self->{jsform}->get_form($form_tag, 1) ; } else { $content .= $form_tag ; } # JSForm $content .= " ".$self->make_hidden()."
$errormsg $form

 
"; $self->print_form($content); } ## build form for adding and updating sub show_edit_form { my $self = shift; my $title = shift; my $s = ""; my $iid = $self->{id}; $s .= "

" . $title . "

\n"; if (defined($iid) && '$iid' ne '0') { #editing # if there is any intro text to be displayed at the top, add it. $s .= "

" . $self->get_intro_text() . "

"; $s .= $self->get_form_box('name'); $s .= "

"; $s .= $self->{fields}->{description}->{label}; $s .= " (*)
\n"; ## (qp) $self->{t6} = $self->get_current_version(); $s .= $self->get_form_box( "t6" ); $s .= $self->get_form_box('cool'); $s .= "
"; } else { #creating new { $s .= $self->get_form_box('name'); $s .= "

"; $s .= $self->{fields}->{description}->{label}; $s .= " (*)
\n"; $s .= "

"; $s .= $self->{fields}->{t4}->{label}; $s .= " (*)
\n"; $self->{t6} = "1.0"; $s .= $self->get_form_box( "t6" ); $s .= $self->get_form_box('cool'); $s .= "

Add a new File (*)
"; # JSForm $self->{jsform}->add_check_simple("file1", "Add a new File", "notempty") if defined($self->{jsform}) ; # JSForm } $s .= "


(*) Mandatory field(s)
"; return $s; } ## build form for checking in sub show_edit_form_modify { my $self = shift; my $title = shift; my $s = ""; $s .= "

" . $title . "

\n"; # if there is any intro text to be displayed at the top, add it. $s .= "

" . $self->get_intro_text() . "

"; $s .= "
Check in comment (*)
"; $s .= "\n"; # JSForm $self->{jsform}->add_check_simple("t4", "Check in comment", "notempty") if defined($self->{jsform}) ; $s .= "

Upload a new version of the file (*)
"; # (qp ) $self->{t6} = $self->get_current_version(); $self->{t6} = $self->get_next_version( $self->{t6} ); $s .= $self->get_form_box( "t6" ); # JSForm $self->{jsform}->add_check_simple("file1", "Upload a new version of the file", "notempty") if defined($self->{jsform}) ; $s .= "


(*) Mandatory field(s)
"; return $s; } sub www_checkout { my $self = shift; my $iid = $self->id(); my $isa = $self->is_a(); #mark as checked out $self->set_checked_out_status("Yes"); $self->set_downloaded_state("No"); #set the user $self->set_checkout_owner($USER->{uid}); $self->save(); $self->md_redirect("index.pl?id=$iid&isa=$isa&op=show&checkingout=yes"); } sub www_cancelcheckout { my $self = shift; my $iid = $self->id(); my $uid = $USER->uid(); my $isa = $self->is_a(); unless (($uid = $self->get_checkout_owner) || ($self->is_allowed_to_do('modify'))) { $self->print_click_back("Sorry", "You must be the person who has the version checked out, or you must have edit privileges on this CMSDocument, in order to cancel a checkout\n"); exit; } $self->set_checked_out_status("No"); $self->set_checkout_owner("NULL"); $self->save(); $self->md_redirect("index.pl?id=$iid&isa=$isa&op=show"); } ## called for saving the first time and when editing sub www_save { my $self = shift; my $checked_reqs = shift; #optional my $order = 0; my $uid = $USER->uid(); my $error = undef; my $rev ; if(ord substr($FORM{file1},0,1) < 32) { $FORM{file1} = "" ; } if (!$checked_reqs) { ## check for required fields #print STDERR "checking for field "; foreach my $field (keys (%{$self->{fields}})) { #print STDERR " $field : $FORM{$field}\n"; if (($field ne "file1") && ($field ne "t4")) { if ($self->{fields}->{$field}->{required} && (!$FORM{$field} || !($FORM{$field} =~ /\S/)) # field is not just whitespace ) { $error .= "
".$self->{fields}->{$field}->{label} . " is a required field.\n"; } } } } ## (qp) validate the major.minor revision specification if ( defined( $FORM{"t6"} ) ) { if ( $FORM{"t6"} =~ /^\d+\.\d+$/ ) { # good } else { # bad $error .= "
Revision number must be in the form M.N where M and N are integers.\n"; } } my $iid = $self->get_iid(); if (defined($error) && $iid){ ## if error and updating $self->www_modify($error); exit; } elsif (defined($error)) { ## if error and saving new my $parentid = $self->parent_id(); my $parent = Gizmo->restore($parentid); $parent->www_add_child($error, $self->is_a); exit; } #print STDERR "\nwww_save::got past the error checks!\n"; if (!$iid){ ## we are creating new foreach my $field (keys (%{$self->{fields}})) { $order = $self->{fields}->{$field}->{order}; next if !defined($order) || $order <= 0; $self->{$field} = $FORM{$field}; } $iid = $self->add(); # (qp) # $rev = "1.1"; $rev = ($self->{t6}) ? $self->{t6} : "1.0"; my $parent_id = $self->parent_id(); my $CMS_owner = $self->{uid} || $USER->{uid}; my $version = Version->new({ parent_id => $iid }); my $navigable_parent = $self->get_navigation_parent(); $version->set_version_number($rev); $version->set_comment($self->{t4}); $version->set_uid_of_modifier($USER->{uid}); $version->set_owner($CMS_owner); $version->add(); ###must call add before uploading the file, in order to get an iid for the directory name eval { my $upload_file = $version->upload_file($FORM{file1}); }; if( $@ ) { $version->delete(); $self->delete(); exit(0); } my $filename = $version->get_file1(); if ($filename =~ m/QUOTA_EXCEEDED/) { #handle quota exceeded here $version->set_file1(""); $version->delete(); $self->delete(); if ($filename eq 'USER_QUOTA_EXCEEDED') { $self->print_click_back("Sorry", "You have exceeded your user file space quota. Remove some files from the server or ask the administrator for additional space.\n"); } else { $self->print_click_back("Sorry", "You have exceeded the site-wide file space quota. Please remove some files from the server or ask the administrator for additional space.\n"); } exit; } $version->save(); $self->set_current_version_iid($version->get_iid); # (qp) # $self->set_current_version("1.1" ); $self->set_current_version(($self->{t6}) ? $self->{t6} : "1.0"); #update the filename from the version $self->{file1} = $filename; $self->save(); $self->two_choices("New " . $self->get_gizmo_name() . " added!

What do you want to do?", "confirm", "Add another " . $self->get_gizmo_name(), "index.pl?child_type=CMSDocument&isa=Category&iid=$parent_id&op=add_child", "Enough for now!", "index.pl?id=$parent_id", ); } else { $self->{name} = $FORM{"name"}; $self->{description} = $FORM{"description"}; ## (qp) $self->set_current_version( $FORM{"t6"} ); $self->{cool} = $FORM{"cool"}; $self->save(); $self->md_redirect("index.pl?iid=".$self->parent_id); } } sub www_delete_ok { my $self = shift; my $iid = $self->get_iid(); Version->delete_children($iid); $self->SUPER::www_delete_ok(); } ## called for updating sub www_save_existing { my $self = shift; my $checked_reqs = shift; #optional my $order = 0; my $uid = $USER->uid(); my $error = undef; my $rev ; if ($USER->{uid} != $self->get_checkout_owner()) { $self->print_click_back("Sorry", "You are not the person who currently has this item checked out\n"); exit; } if(ord substr($FORM{file1},0,1) < 32) { $FORM{file1} = "" ; } if (!$checked_reqs) { ## check for required fields #we only have two fielda to save and mofigy, file1 and comment foreach my $field (keys (%{$self->{fields}})) { if (($field ne "description") && ($field ne "name")) { if ($self->{fields}->{$field}->{required} && (!$FORM{$field} || !($FORM{$field} =~ /\S/)) # field is not just whitespace ) { $error .= "
".$self->{fields}->{$field}->{label} . " is a required field.\n"; } } } } my $iid = $self->get_iid(); if (defined($error) && $iid){ ## if error and updating $self->www_modify_existing($error); exit; } elsif (defined($error)) { ## if error and saving new my $parentid = $self->parent_id(); my $parent = Gizmo->restore($parentid); $parent->www_add_child($error, $self->is_a); exit; } my $CMS_owner = $self->{uid} || $USER->{uid}; my $current_version = $self->get_current_version(); ## (qp) support major.minor format ## $current_version++; if ( defined( $FORM{t6} ) ) { $current_version = $FORM{t6}; } else { $current_version = $self->get_next_version( $current_version ); } ## end (qp) $self->set_current_version($current_version); my $version = Version->new({ parent_id => $iid }); $version->set_version_number($current_version); $version->set_comment($FORM{t4}); $version->set_uid_of_modifier($USER->{uid}); $version->set_owner($CMS_owner); $version->add(); ###must call add before uploading the file, in order to get an iid for the directory name eval { $version->upload_file($FORM{file1}); }; if( $@ ) { $version->delete(); exit(0); } my $filename = $version->get_file1(); if ($filename =~ m/QUOTA_EXCEEDED/) { #handle quota exceeded here $version->set_file1(""); $version->delete(); if ($filename eq 'USER_QUOTA_EXCEEDED') { $self->print_click_back("Sorry", "You have exceeded your user file space quota. Remove some files from the server or ask the administrator for additional space.\n"); } else { $self->print_click_back("Sorry", "You have exceeded the site-wide file space quota. Please remove some files from the server or ask the administrator for additional space.\n"); } exit; } $version->save(); $self->set_current_version_iid($version->get_iid); $self->set_checked_out_status("No"); # update the filename from the version $self->{file1} = $filename; $self->save(); $self->md_redirect("index.pl?iid=".$self->parent_id); } sub show_summary { my $self = shift; my $name = $self->get_name(); my $description = $self->get_description(); my $url = $self->get_url(); my $cool_icon = $self->get_cool_icon(); my $buttons = $self->get_buttons(); my $isa = $self->is_a(); my $iid = $self->id(); my $current_version_iid = $self->get_current_version_iid(); my $version = $self->get_version_object(); my $file_icon = $version->get_file_1_icon(); my $current_version = $self->get_current_version(); my $imageslocation = $PARAMS->{'imageslocation'}; my $html = ''; my $maxiLen = 60 ; # make a little smaller (need more general soln) my $nameLen = length($name) ; my $linkLen = length($url) ; my $coolLen = ($cool_icon ne '') ? 10 : 0 ; my $fileLen = ($file_icon ne '') ? 10 : 0 ; my $fullLen = $nameLen + $linkLen + $coolLen + $fileLen ; my $flgUrl = (defined($url) && $url ne '' && $url ne "http://") ; # [vadim] upon Philippe's request $description =~ s/\n/
/g ; $html .= ""; $html .= ""; # cell #1 start $html .= "" ; # cell #1 end # cell #2 start $html .= "" ; # cell #2 end # cell #3 start $html .= "" ; # cell #3 end $html .= "" ; if($description ne '') { $html .= ""; } $html .= "
" ; # cell #1 end if ($buttons ne '') { $html .= " $buttons" ; } $html .= "" ; if ($flgUrl) { $html .= " $name " ."- v" . "$current_version"; } else { $html .= "$name - v$current_version"; } if ($cool_icon ne '') { $html .= "$cool_icon" ; } if ($file_icon ne '') { $html .= "$file_icon" ; } $html .= "
$description
"; return $html; } sub show_line { my $self = shift; my $name = $self->get_name(); my $description = $self->get_description(); my $url = $self->get_url(); my $file_icon = $self->get_file_1_icon(); my $cool_icon = $self->get_cool_icon(); my $buttons = $self->get_buttons(); my $html = ''; $html .= "$buttons $cool_icon $file_icon"; if (defined($url) && $url ne '' && $url ne "http://") { $html .= "make_url($url)."\">$name\n"; } else { $html .= $name . "\n"; } $html .= $description; return $html; } 1; __END__ =head1 NAME Gizmo::CMSDoc - can either create a new Item (returing a pointer to the new object) or control the way existing ones are displayed (returning the formatted HTML). =head1 SYNOPSIS use Gizmo::CMSDoc; $cmsdoc = cmsdoc->new ($id); $html = $cmsdoc->show (); $html = $cmsdoc->show_as_bullet (); $html = $cmsdoc->show_as_dash (); $version = CMSDocument->get_version(); =head1 DESCRIPTION cmsdoc is the basic building block for the Portal. Adding an cmsdoc allows the user to create a link to a URL, and the user may also attach a file to an cmsdoc. =head1 Methods Calling the new function instantiates a new cmsdoc or retrive its persistent info from the backend database. Class method to retrieve the version of the gizmo $version = CMSDocument->get_version(); The remaining functions control how an cmsdoc is displayed: $cmsdoc->show() displays an cmsdoc. $cmsdoc->show_as_bullet() displays the cmsdoc as an cmsdoc in a bulleted list. $cmsdoc_as_dash() show the cmsdoc with a dash in front of its name. =cut