[system] / branches / rel-2-4-patches / webwork-modperl / lib / WeBWorK / Utils / ListingDB.pm Repository:
ViewVC logotype

View of /branches/rel-2-4-patches/webwork-modperl/lib/WeBWorK/Utils/ListingDB.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5734 - (download) (as text) (annotate)
Tue Jun 24 00:44:59 2008 UTC (4 years, 11 months ago)
File size: 18973 byte(s)
This commit was manufactured by cvs2svn to create branch 'rel-2-4-patches'.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright � 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader$
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 package WeBWorK::Utils::ListingDB;
   18 
   19 use strict;
   20 use DBI;
   21 use WeBWorK::Utils qw(sortByName);
   22 
   23 use constant LIBRARY_STRUCTURE => {
   24   textbook => { select => 'tbk.textbook_id,tbk.title,tbk.author,tbk.edition',
   25   name => 'library_textbook', where => 'tbk.textbook_id'},
   26   textchapter => { select => 'tc.number,tc.name', name=>'library_textchapter',
   27   where => 'tc.name'},
   28   textsection => { select => 'ts.number,ts.name', name=>'library_textsection',
   29   where => 'ts.name'},
   30   problem => { select => 'prob.name' },
   31   };
   32 
   33 BEGIN
   34 {
   35   require Exporter;
   36   use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
   37 
   38   $VERSION    =1.0;
   39   @ISA    =qw(Exporter);
   40   @EXPORT =qw(
   41   &createListing &updateListing &deleteListing &getAllChapters
   42   &getAllSections &searchListings &getAllListings &getSectionListings
   43   &getAllDBsubjects &getAllDBchapters &getAllDBsections &getDBTextbooks
   44   &getDBListings &countDBListings
   45   );
   46   %EXPORT_TAGS    =();
   47   @EXPORT_OK    =qw();
   48 }
   49 use vars @EXPORT_OK;
   50 
   51 
   52 sub getDB {
   53   my $ce = shift;
   54   my $dbh = DBI->connect(
   55     $ce->{problemLibrary_db}->{dbsource},
   56     $ce->{problemLibrary_db}->{user},
   57     $ce->{problemLibrary_db}->{passwd},
   58     {
   59       PrintError => 0,
   60       RaiseError => 1,
   61     },
   62   );
   63   die "Cannot connect to problem library database" unless $dbh;
   64   return($dbh);
   65 }
   66 
   67 =item kwtidy($s) and keywordcleaner($s)
   68 Both take a string and perform utility functions related to keywords.
   69 keywordcleaner splits a string, and uses kwtidy to regularize punctuation
   70 and case for an individual entry.
   71 
   72 =cut
   73 
   74 sub kwtidy {
   75   my $s = shift;
   76   $s =~ s/\W//g;
   77   $s =~ s/_//g;
   78   $s = lc($s);
   79   return($s);
   80 }
   81 
   82 sub keywordCleaner {
   83   my $string = shift;
   84   my @spl1 = split /\s*,\s*/, $string;
   85   my @spl2 = map(kwtidy($_), @spl1);
   86   return(@spl2);
   87 }
   88 
   89 sub makeKeywordWhere {
   90   my $kwstring = shift;
   91   my @kwlist = keywordCleaner($kwstring);
   92   @kwlist = map { "kw.keyword = \"$_\"" } @kwlist;
   93   my $where = join(" OR ", @kwlist);
   94   return "AND ( $where )";
   95 }
   96 
   97 =item getDBTextbooks($r)
   98 Returns textbook dependent entries.
   99 
  100 $r is a Apache request object so we can extract whatever parameters we want
  101 
  102 $thing is a string of either 'textbook', 'textchapter', or 'textsection' to
  103 specify what to return.
  104 
  105 If we are to return textbooks, then return an array of textbook names
  106 consistent with the DB subject, chapter, section selected.
  107 
  108 =cut
  109 
  110 sub getDBTextbooks {
  111   my $r = shift;
  112   my $thing = shift || 'textbook';
  113   my $dbh = getDB($r->ce);
  114   my $extrawhere = '';
  115   # Handle DB* restrictions
  116   my $subj = $r->param('library_subjects') || "";
  117   my $chap = $r->param('library_chapters') || "";
  118   my $sec = $r->param('library_sections') || "";
  119   if($subj) {
  120     $subj =~ s/'/\\'/g;
  121     $extrawhere .= " AND t.name = \'$subj\'\n";
  122   }
  123   if($chap) {
  124     $chap =~ s/'/\\'/g;
  125     $extrawhere .= " AND c.name = \'$chap\' AND c.DBsubject_id=t.DBsubject_id\n";
  126   }
  127   if($sec) {
  128     $sec =~ s/'/\\'/g;
  129     $extrawhere .= " AND s.name = \'$sec\' AND s.DBchapter_id = c.DBchapter_id AND s.DBsection_id=pgf.DBsection_id";
  130   }
  131   my $textextrawhere = '';
  132   my $textid = $r->param('library_textbook') || '';
  133   if($textid and $thing ne 'textbook') {
  134     $textextrawhere .= " AND tbk.textbook_id=\"$textid\" ";
  135   } else {
  136     return([]) if($thing ne 'textbook');
  137   }
  138 
  139   my $textchap = $r->param('library_textchapter') || '';
  140   $textchap =~ s/^\s*\d+\.\s*//;
  141   if($textchap and $thing eq 'textsection') {
  142     $textextrawhere .= " AND tc.name=\"$textchap\" ";
  143   } else {
  144     return([]) if($thing eq 'textsection');
  145   }
  146 
  147   my $selectwhat = LIBRARY_STRUCTURE->{$thing}{select};
  148 
  149   my $query = "SELECT DISTINCT $selectwhat
  150           FROM `NPL-textbook` tbk, `NPL-problem` prob,
  151       `NPL-pgfile-problem` pg, `NPL-pgfile` pgf,
  152             `NPL-DBsection` s, `NPL-DBchapter` c, `NPL-DBsubject` t,
  153       `NPL-chapter` tc, `NPL-section` ts
  154           WHERE ts.section_id=prob.section_id AND
  155             prob.problem_id=pg.problem_id AND
  156             s.DBchapter_id=c.DBchapter_id AND
  157             c.DBsubject_id=t.DBsubject_id AND
  158             pgf.DBsection_id=s.DBsection_id AND
  159             pgf.pgfile_id=pg.pgfile_id AND
  160             ts.chapter_id=tc.chapter_id AND
  161             tc.textbook_id=tbk.textbook_id
  162             $extrawhere $textextrawhere ";
  163 #$query =~ s/\n/ /g;
  164 #warn $query;
  165   my $text_ref = $dbh->selectall_arrayref($query);
  166   my @texts = @{$text_ref};
  167   if( $thing eq 'textbook') {
  168     @texts = grep { $_->[1] =~ /\S/ } @texts;
  169     my @sortarray = map { $_->[1] . $_->[2] . $_->[3] } @texts;
  170     @texts = indirectSortByName( \@sortarray, @texts );
  171     return(\@texts);
  172   } else {
  173     @texts = grep { $_->[1] =~ /\S/ } @texts;
  174     my @sortarray = map { $_->[0] .". " . $_->[1] } @texts;
  175     @texts = map { [ $_ ] } @sortarray;
  176     @texts = indirectSortByName(\@sortarray, @texts);
  177     return(\@texts);
  178   }
  179 }
  180 
  181 =item getAllDBsubjects($r)
  182 Returns an array of DBsubject names
  183 
  184 $r is the Apache request object
  185 
  186 =cut
  187 
  188 sub getAllDBsubjects {
  189   my $r = shift;
  190   my @results=();
  191   my $row;
  192   my $query = "SELECT DISTINCT name FROM `NPL-DBsubject`";
  193   my $dbh = getDB($r->ce);
  194   my $sth = $dbh->prepare($query);
  195   $sth->execute();
  196   while ($row = $sth->fetchrow_array()) {
  197     push @results, $row;
  198   }
  199   @results = sortByName(undef, @results);
  200   return @results;
  201 }
  202 
  203 
  204 =item getAllDBchapters($r)
  205 Returns an array of DBchapter names
  206 
  207 $r is the Apache request object
  208 
  209 =cut
  210 
  211 sub getAllDBchapters {
  212   my $r = shift;
  213   my $subject = $r->param('library_subjects');
  214   return () unless($subject);
  215   my $dbh = getDB($r->ce);
  216   my $query = "SELECT DISTINCT c.name FROM `NPL-DBchapter` c,
  217         `NPL-DBsubject` t
  218                  WHERE c.DBsubject_id = t.DBsubject_id AND
  219                  t.name = \"$subject\"";
  220   my $all_chaps_ref = $dbh->selectall_arrayref($query);
  221   my @results = map { $_->[0] } @{$all_chaps_ref};
  222   @results = sortByName(undef, @results);
  223   return @results;
  224 }
  225 
  226 =item getAllDBsections($r)
  227 Returns an array of DBsection names
  228 
  229 $r is the Apache request object
  230 
  231 =cut
  232 
  233 sub getAllDBsections {
  234   my $r = shift;
  235   my $subject = $r->param('library_subjects');
  236   return () unless($subject);
  237   my $chapter = $r->param('library_chapters');
  238   return () unless($chapter);
  239   my $dbh = getDB($r->ce);
  240   my $query = "SELECT DISTINCT s.name FROM `NPL-DBsection` s,
  241                  `NPL-DBchapter` c, `NPL-DBsubject` t
  242                  WHERE s.DBchapter_id = c.DBchapter_id AND
  243                  c.DBsubject_id = t.DBsubject_id AND
  244                  t.name = \"$subject\" AND c.name = \"$chapter\"";
  245   my $all_sections_ref = $dbh->selectall_arrayref($query);
  246   my @results = map { $_->[0] } @{$all_sections_ref};
  247   @results = sortByName(undef, @results);
  248   return @results;
  249 }
  250 
  251 =item getDBSectionListings($r)
  252 Returns an array of hash references with the keys: path, filename.
  253 
  254 $r is an Apache request object that has all needed data inside of it
  255 
  256 Here, we search on all known fields out of r
  257 
  258 =cut
  259 
  260 sub getDBListings {
  261   my $r = shift;
  262   my $amcounter = shift;
  263   my $ce = $r->ce;
  264   my $subj = $r->param('library_subjects') || "";
  265   my $chap = $r->param('library_chapters') || "";
  266   my $sec = $r->param('library_sections') || "";
  267   my $keywords = $r->param('library_keywords') || "";
  268   my ($kw1, $kw2) = ('','');
  269   if($keywords) {
  270     $kw1 = ", `NPL-keyword` kw, `NPL-pgfile-keyword` pgkey";
  271     $kw2 = " AND kw.keyword_id=pgkey.keyword_id AND
  272        pgkey.pgfile_id=pgf.pgfile_id ".
  273       makeKeywordWhere($keywords) ;
  274   }
  275 
  276   my $dbh = getDB($ce);
  277 
  278   my $extrawhere = '';
  279   if($subj) {
  280     $subj =~ s/'/\\'/g;
  281     $extrawhere .= " AND dbsj.name=\"$subj\" ";
  282   }
  283   if($chap) {
  284     $chap =~ s/'/\\'/g;
  285     $extrawhere .= " AND dbc.name=\"$chap\" ";
  286   }
  287   if($sec) {
  288     $sec =~ s/'/\\'/g;
  289     $extrawhere .= " AND dbsc.name=\"$sec\" ";
  290   }
  291   my $textextrawhere = '';
  292     my $haveTextInfo=0;
  293   for my $j (qw( textbook textchapter textsection )) {
  294     my $foo = $r->param(LIBRARY_STRUCTURE->{$j}{name}) || '';
  295     $foo =~ s/^\s*\d+\.\s*//;
  296     if($foo) {
  297             $haveTextInfo=1;
  298       $foo =~ s/'/\\'/g;
  299       $textextrawhere .= " AND ".LIBRARY_STRUCTURE->{$j}{where}."=\"$foo\" ";
  300     }
  301   }
  302 
  303   my $selectwhat = 'DISTINCT pgf.pgfile_id';
  304   $selectwhat = 'COUNT(' . $selectwhat . ')' if ($amcounter);
  305 
  306   my $query = "SELECT $selectwhat from `NPL-pgfile` pgf,
  307          `NPL-DBsection` dbsc, `NPL-DBchapter` dbc, `NPL-DBsubject` dbsj $kw1
  308         WHERE dbsj.DBsubject_id = dbc.DBsubject_id AND
  309               dbc.DBchapter_id = dbsc.DBchapter_id AND
  310               dbsc.DBsection_id = pgf.DBsection_id
  311               \n $extrawhere
  312               $kw2";
  313   if($haveTextInfo) {
  314       $query = "SELECT $selectwhat from `NPL-pgfile` pgf,
  315         `NPL-DBsection` dbsc, `NPL-DBchapter` dbc, `NPL-DBsubject` dbsj,
  316     `NPL-pgfile-problem` pgp, `NPL-problem` prob, `NPL-textbook` tbk ,
  317     `NPL-chapter` tc, `NPL-section` ts $kw1
  318         WHERE dbsj.DBsubject_id = dbc.DBsubject_id AND
  319               dbc.DBchapter_id = dbsc.DBchapter_id AND
  320               dbsc.DBsection_id = pgf.DBsection_id AND
  321               pgf.pgfile_id = pgp.pgfile_id AND
  322               pgp.problem_id = prob.problem_id AND
  323               tc.textbook_id = tbk.textbook_id AND
  324               ts.chapter_id = tc.chapter_id AND
  325               prob.section_id = ts.section_id \n $extrawhere \n $textextrawhere
  326               $kw2";
  327      }
  328 #$query =~ s/\n/ /g;
  329 #warn $query;
  330   my $pg_id_ref = $dbh->selectall_arrayref($query);
  331   my @pg_ids = map { $_->[0] } @{$pg_id_ref};
  332   if($amcounter) {
  333     return(@pg_ids[0]);
  334   }
  335   my @results=();
  336   for my $pgid (@pg_ids) {
  337     $query = "SELECT path, filename FROM `NPL-pgfile` pgf, `NPL-path` p
  338           WHERE p.path_id = pgf.path_id AND pgf.pgfile_id=\"$pgid\"";
  339     my $row = $dbh->selectrow_arrayref($query);
  340     push @results, {'path' => $row->[0], 'filename' => $row->[1] };
  341 
  342   }
  343   return @results;
  344 }
  345 
  346 sub countDBListings {
  347   my $r = shift;
  348   return (getDBListings($r,1));
  349 }
  350 
  351 ##############################################################################
  352 # input expected: keywords,<keywords>,chapter,<chapter>,section,<section>,path,<path>,filename,<filename>,author,<author>,instituition,<instituition>,history,<history>
  353 #
  354 #
  355 # Warning - this function is out of date (but currently unused)
  356 #
  357 
  358 sub createListing {
  359   my $ce = shift;
  360   my %listing_data = @_;
  361   my $classify_id;
  362   my $dbh = getDB($ce);
  363   # my $dbh = WeBWorK::ProblemLibrary::DB::getDB();
  364   my $query = "INSERT INTO classify
  365     (filename,chapter,section,keywords)
  366     VALUES
  367     ($listing_data{filename},$listing_data{chapter},$listing_data{section},$listing_data{keywords})";
  368   $dbh->do($query);  #TODO: watch out for comma delimited keywords, sections, chapters!
  369 
  370   $query = "SELECT id FROM classify WHERE filename = $listing_data{filename}";
  371   my $sth = $dbh->prepare($query);
  372   $sth->execute();
  373   if ($sth->rows())
  374   {
  375     ($classify_id) = $sth->fetchrow_array;
  376   }
  377   else
  378   {
  379     #print STDERR "ListingDB::createListingPGfiles: $listing_data{filename} failed insert into classify table";
  380     return 0;
  381   };
  382 
  383   $query = "INSERT INTO pgfiles
  384    (
  385    classify_id,
  386    path,
  387    author,
  388    institution,
  389    history
  390    )
  391    VALUES
  392   (
  393    $classify_id,
  394    $listing_data{path},
  395    $listing_data{author},
  396    $listing_data{institution},
  397    $listing_data{history}
  398    )";
  399 
  400   $dbh->do($query);
  401   return 1;
  402 }
  403 
  404 ##############################################################################
  405 # input expected any pair of: keywords,<keywords data>,chapter,<chapter data>,section,<section data>,filename,<filename data>,author,<author data>,instituition,<instituition data>
  406 # returns an array of hash references
  407 #
  408 # Warning - out of date (and unusued)
  409 #
  410 
  411 sub searchListings {
  412   my $ce = shift;
  413   my %searchterms = @_;
  414   #print STDERR "ListingDB::searchListings  input array @_\n";
  415   my @results;
  416   my ($row,$key);
  417   my $dbh = getDB($ce);
  418   my $query = "SELECT c.filename, p.path
  419     FROM classify c, pgfiles p
  420     WHERE c.id = p.classify_id";
  421   foreach $key (keys %searchterms) {
  422     $query .= " AND c.$key = $searchterms{$key}";
  423   };
  424   my $sth = $dbh->prepare($query);
  425   $sth->execute();
  426   if ($sth->rows())
  427   {
  428     while (1)
  429     {
  430       $row = $sth->fetchrow_hashref();
  431       if (!defined($row))
  432       {
  433         last;
  434       }
  435       else
  436       {
  437         #print STDERR "ListingDB::searchListings(): found $row->{id}\n";
  438         my $listing = $row;
  439         push @results, $listing;
  440       }
  441     }
  442   }
  443   return @results;
  444 }
  445 ##############################################################################
  446 # returns a list of chapters
  447 #
  448 # Warning - out of date
  449 #
  450 
  451 sub getAllChapters {
  452   #print STDERR "ListingDB::getAllChapters\n";
  453   my $ce = shift;
  454   my @results=();
  455   my ($row,$listing);
  456   my $query = "SELECT DISTINCT chapter FROM classify";
  457   my $dbh = getDB($ce);
  458   my $sth = $dbh->prepare($query);
  459   $sth->execute();
  460   while (1)
  461   {
  462     $row = $sth->fetchrow_array;
  463     if (!defined($row))
  464     {
  465       last;
  466     }
  467     else
  468     {
  469       my $listing = $row;
  470       push @results, $listing;
  471       #print STDERR "ListingDB::getAllChapters $listing\n";
  472     }
  473   }
  474   return @results;
  475 }
  476 ##############################################################################
  477 # input chapter
  478 # returns a list of sections
  479 #
  480 # Warning - out of date (and unused)
  481 #
  482 
  483 sub getAllSections {
  484   #print STDERR "ListingDB::getAllSections\n";
  485   my $ce = shift;
  486   my $chapter = shift;
  487   my @results=();
  488   my ($row,$listing);
  489   my $query = "SELECT DISTINCT section FROM classify
  490         WHERE chapter = \'$chapter\'";
  491   my $dbh = getDB($ce);
  492   my $sth = $dbh->prepare($query);
  493   $sth->execute();
  494   while (1)
  495   {
  496     $row = $sth->fetchrow_array;
  497     if (!defined($row))
  498     {
  499       last;
  500     }
  501     else
  502     {
  503       my $listing = $row;
  504       push @results, $listing;
  505       #print STDERR "ListingDB::getAllSections $listing\n";
  506     }
  507   }
  508   return @results;
  509 }
  510 
  511 ##############################################################################
  512 # returns an array of hash references
  513 #
  514 # Warning - out of date (and unused)
  515 #
  516 
  517 sub getAllListings {
  518   #print STDERR "ListingDB::getAllListings\n";
  519   my $ce = shift;
  520   my @results;
  521   my ($row,$key);
  522   my $dbh = getDB($ce);
  523   my $query = "SELECT c.*, p.path
  524       FROM classify c, pgfiles p
  525       WHERE c.pgfiles_id = p.pgfiles_id";
  526   my $sth = $dbh->prepare($query);
  527   $sth->execute();
  528   while (1)
  529   {
  530     $row = $sth->fetchrow_hashref();
  531     last if (!defined($row));
  532     my $listing = $row;
  533     push @results, $listing;
  534     #print STDERR "ListingDB::getAllListings $listing\n";
  535   }
  536   return @results;
  537 }
  538 
  539 ##############################################################################
  540 # input chapter, section
  541 # returns an array of hash references.
  542 # if section is omitted, get all from the chapter
  543 sub getSectionListings  {
  544   #print STDERR "ListingDB::getSectionListings(chapter,section)\n";
  545   my $r = shift;
  546   my $ce = $r->ce;
  547   my $version = $ce->{problemLibrary}->{version} || 1;
  548   if($version == 2) { return(getDBListings($r, 0))}
  549   my $subj = $r->param('library_subjects') || "";
  550   my $chap = $r->param('library_chapters') || "";
  551   my $sec = $r->param('library_sections') || "";
  552 
  553   my $chapstring = '';
  554   if($chap) {
  555     $chap =~ s/'/\\'/g;
  556     $chapstring = " c.chapter = \'$chap\' AND ";
  557   }
  558   my $secstring = '';
  559   if($sec) {
  560     $sec =~ s/'/\\'/g;
  561     $secstring = " c.section = \'$sec\' AND ";
  562   }
  563 
  564   my @results; #returned
  565   my $query = "SELECT c.*, p.path
  566   FROM classify c, pgfiles p
  567   WHERE $chapstring $secstring c.pgfiles_id = p.pgfiles_id";
  568   my $dbh = getDB($ce);
  569   my $sth = $dbh->prepare($query);
  570 
  571   $sth->execute();
  572   while (1)
  573   {
  574     my $row = $sth->fetchrow_hashref();
  575     if (!defined($row))
  576     {
  577       last;
  578     }
  579     else
  580     {
  581       push @results, $row;
  582       #print STDERR "ListingDB::getSectionListings $row\n";
  583     }
  584   }
  585   return @results;
  586 }
  587 
  588 ###############################################################################
  589 # INPUT:
  590 #  listing id number
  591 # RETURN:
  592 #  1 = all ok
  593 #
  594 # not implemented yet
  595 sub deleteListing {
  596   my $ce = shift;
  597   my $listing_id = shift;
  598   #print STDERR "ListingDB::deleteListing(): listing == '$listing_id'\n";
  599 
  600   my $dbh = getDB($ce);
  601 
  602   return undef;
  603 }
  604 
  605 
  606 # Use sortByName($aref, @b) to sort list @b using parallel list @a.
  607 # Here, $aref is a reference to the array @a
  608 
  609 sub indirectSortByName {
  610   my $aref = shift ;
  611   my @a = @$aref;
  612   my @b = @_;
  613   my %pairs ;
  614   for my $j (1..scalar(@a)) {
  615     $pairs{$a[$j-1]} = $b[$j-1];
  616   }
  617   my @list = sortByName(undef, @a);
  618   @list = map { $pairs{$_} } @list;
  619   return(@list);
  620 }
  621 
  622 
  623 
  624 ##############################################################################
  625 1;
  626 
  627 __END__
  628 
  629 =head1 DESCRIPTION
  630 
  631 This module provides access to the database of classify in the
  632 system. This includes the filenames, along with the table of
  633 search terms.
  634 
  635 =head1 FUNCTION REFERENCE
  636 
  637 =over 4
  638 
  639 =item $result = createListing( %listing_data );
  640 
  641 Creates a new listing populated with data from %listing_data. On
  642 success, 1 is returned, 0 is returned on failure. The %listing_data
  643 hash has the following format:
  644 =cut
  645 
  646 =back
  647 
  648 =head1 AUTHOR
  649 
  650 Written by Bill Ziemer.
  651 Modified by John Jones.
  652 
  653 =cut
  654 
  655 
  656 ##############################################################################
  657 # end of ListingDB.pm
  658 ##############################################################################

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9