--- loncom/metadata_database/LONCAPA/lonmetadata.pm 2006/12/29 19:15:28 1.15 +++ loncom/metadata_database/LONCAPA/lonmetadata.pm 2007/01/02 12:53:27 1.16 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonmetadata.pm,v 1.15 2006/12/29 19:15:28 raeburn Exp $ +# $Id: lonmetadata.pm,v 1.16 2007/01/02 12:53:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -30,6 +30,7 @@ package LONCAPA::lonmetadata; use strict; use DBI; +use HTML::TokeParser; use vars qw($Metadata_Table_Description $Portfolio_metadata_table_description $Portfolio_access_table_description $Fulltext_indicies $Portfolio_metadata_indices $Portfolio_access_indices $Portfolio_addedfields_table_description $Portfolio_addedfields_indices); @@ -502,7 +503,7 @@ sub lookup_metadata { $error = $sth->errstr; } } - } + } return ($error,$returnvalue); } @@ -928,10 +929,237 @@ sub dynamic_metadata_storage { return %Store; } +############################################################### +############################################################### +### ### +### &portfolio_metadata($filepath,$dom,$uname,$group) ### +### Retrieve metadata for the given file ### +### Returns array - ### +### contains reference to metadatahash and ### +### optional reference to addedfields hash ### +### ### +############################################################### +############################################################### + +sub portfolio_metadata { + my ($fullpath,$dom,$uname,$group)=@_; + my ($mime) = ( $fullpath=~/\.(\w+)$/ ); + my %metacache=(); + if ($fullpath !~ /\.meta$/) { + $fullpath .= '.meta'; + } + my (@standard_fields,%addedfields); + my $colsref = $Portfolio_metadata_table_description; + if (ref($colsref) eq 'ARRAY') { + my @columns = @{$colsref}; + foreach my $coldata (@columns) { + push(@standard_fields,$coldata->{'name'}); + } + } + my $metastring=&getfile($fullpath); + if (! defined($metastring)) { + $metacache{'keys'}= 'owner,domain,mime'; + $metacache{'owner'} = $uname.':'.$dom; + $metacache{'domain'} = $dom; + $metacache{'mime'} = $mime; + if ($group ne '') { + $metacache{'keys'} .= ',courserestricted'; + $metacache{'courserestricted'} = 'course.'.$dom.'_'.$uname; + } + } else { + my $parser=HTML::TokeParser->new(\$metastring); + my $token; + while ($token=$parser->get_token) { + if ($token->[0] eq 'S') { + my $entry=$token->[1]; + if ($metacache{'keys'}) { + $metacache{'keys'}.=','.$entry; + } else { + $metacache{'keys'}=$entry; + } + my $value = $parser->get_text('/'.$entry); + if (!grep(/^\Q$entry\E$/,@standard_fields)) { + my $clean_value = lc($value); + $clean_value =~ s/\s/_/g; + if ($clean_value ne $entry) { + if (defined($addedfields{$entry})) { + $addedfields{$entry} .=','.$value; + } else { + $addedfields{$entry} = $value; + } + } + } else { + $metacache{$entry} = $value; + } + } + } # End of ($token->[0] eq 'S') + } + if (keys(%addedfields) > 0) { + foreach my $key (sort keys(%addedfields)) { + $metacache{'addedfieldnames'} .= $key.','; + $metacache{'addedfieldvalues'} .= $addedfields{$key}.'&&&'; + } + $metacache{'addedfieldnames'} =~ s/,$//; + $metacache{'addedfieldvalues'} =~ s/\&\&\&$//; + if ($metacache{'keys'}) { + $metacache{'keys'}.=',addedfieldnames'; + } else { + $metacache{'keys'}='addedfieldnames'; + } + $metacache{'keys'}.=',addedfieldvalues'; + } + return (\%metacache,$metacache{'courserestricted'},\%addedfields); +} + +sub process_portfolio_access_data { + my ($dbh,$simulate,$newnames,$url,$fullpath,$access_hash,$caller) = @_; + my %loghash; + if ($caller eq 'update') { + # Delete old data (no error if deleting non-existent record). + my $error=&delete_metadata($dbh,$newnames->{'access'},$url); + if (defined($error)) { + $loghash{'access'}{'err'} = "MySQL Error Delete: ".$error; + return %loghash; + } + } + # Check the file exists + if (-e $fullpath) { + foreach my $key (keys(%{$access_hash})) { + my $acc_data; + $acc_data->{url} = $url; + $acc_data->{keynum} = $key; + my ($num,$scope,$end,$start) = + ($key =~ /^([^:]+):([a-z]+)_(\d*)_?(\d*)$/); + next if (($scope ne 'public') && ($scope ne 'guest')); + $acc_data->{scope} = $scope; + if ($end != 0) { + $acc_data->{end} = &sqltime($end); + } + $acc_data->{start} = &sqltime($start); + if (! $simulate) { + my ($count,$err) = + &store_metadata($dbh,$newnames->{'access'}, + 'portfolio_access',$acc_data); + if ($err) { + $loghash{$key}{'err'} = "MySQL Error Insert: ".$err; + } + if ($count < 1) { + $loghash{$key}{'count'} = + "Unable to insert record into MySQL database for $url"; + } + } + } + } + return %loghash; +} + +sub process_portfolio_metadata { + my ($dbh,$simulate,$newnames,$url,$fullpath,$is_course,$dom,$uname,$group,$caller) = @_; + my %loghash; + if ($caller eq 'update') { + # Delete old data (no error if deleting non-existent record). + my $error=&delete_metadata($dbh,$newnames->{'portfolio'},$url); + if (defined($error)) { + $loghash{'metadata'}{'err'} = "MySQL Error delete metadata: ". + $error; + return %loghash; + } + $error=&delete_metadata($dbh,$newnames->{'addedfields'},$url); + if (defined($error)) { + $loghash{'addedfields'}{'err'}="MySQL Error delete addedfields: ".$error; + } + } + # Check the file exists. + if (-e $fullpath) { + my ($ref,$crs,$addedfields) = &portfolio_metadata($fullpath,$dom,$uname, + $group); + &getfiledates($ref,$fullpath); + if ($is_course) { + $ref->{'groupname'} = $group; + } + my %Data; + if (ref($ref) eq 'HASH') { + %Data = %{$ref}; + } + %Data = ( + %Data, + 'url'=>$url, + 'version'=>'current', + ); + my %loghash; + if (! $simulate) { + my ($count,$err) = + &store_metadata($dbh,$newnames->{'portfolio'},'portfolio_metadata', + \%Data); + if ($err) { + $loghash{'metadata'."\0"}{'err'} = "MySQL Error Insert: ".$err; + } + if ($count < 1) { + $loghash{'metadata'."\0"}{'count'} = "Unable to insert record into MySQL portfolio_metadata database table for $url"; + } + if (ref($addedfields) eq 'HASH') { + if (keys(%{$addedfields}) > 0) { + foreach my $key (keys(%{$addedfields})) { + my $added_data = { + 'url' => $url, + 'field' => $key, + 'value' => $addedfields->{$key}, + 'courserestricted' => $crs, + }; + my ($count,$err) = + &store_metadata($dbh,$newnames->{'addedfields'}, + 'portfolio_addedfields',$added_data); + if ($err) { + $loghash{$key}{'err'} = + "MySQL Error Insert: ".$err; + } + if ($count < 1) { + $loghash{$key}{'count'} = "Unable to insert record into MySQL portfolio_addedfields database table for url = $url and field = $key"; + } + } + } + } + } + } + return %loghash; +} + ###################################################################### ###################################################################### -## Utility originally in searchcat.pl. Moved to be more widely available. +## Utilities originally in searchcat.pl. Moved to be more widely available. + +sub getfile { + my $file = shift(); + if (! -e $file ) { + return undef; + } + my $fh=IO::File->new($file); + my $contents = ''; + while (<$fh>) { + $contents .= $_; + } + return $contents; +} + +## +## &getfiledates() +## Converts creationdate and modifieddates to SQL format +## Applies stat() to file to retrieve dates if missing +sub getfiledates { + my ($ref,$target) = @_; + if (! defined($ref->{'creationdate'}) || + $ref->{'creationdate'} =~ /^\s*$/) { + $ref->{'creationdate'} = (stat($target))[9]; + } + if (! defined($ref->{'lastrevisiondate'}) || + $ref->{'lastrevisiondate'} =~ /^\s*$/) { + $ref->{'lastrevisiondate'} = (stat($target))[9]; + } + $ref->{'creationdate'} = &sqltime($ref->{'creationdate'}); + $ref->{'lastrevisiondate'} = &sqltime($ref->{'lastrevisiondate'}); +} + ## ## &sqltime($timestamp) ##