Search:

CWIS Developers Documentation

  • Main Page
  • Classes
  • Files
  • File List
  • File Members

ItemFactory.php

Go to the documentation of this file.
00001 <?PHP
00002 
00003 #
00004 #   FILE:  SPT--ItemFactory.php
00005 #
00006 #   METHODS PROVIDED:
00007 #       ItemFactory()
00008 #           - constructor
00009 #       Status()
00010 #           - return current error status
00011 #       GetLastTempItem()
00012 #           - retrieve temp item based on user ID and last modified date
00013 #                     (returns NULL if no temp item found for that ID)
00014 #       CleanOutStaleTempItems()
00015 #           - clear out any temp items more than one week old
00016 #
00017 #   NOTES:
00018 #       - for a derived class to use the temp methods the item record in the
00019 #             database must include "DateLastModified" and "LastModifiedById"
00020 #             fields, and the item object must include a "Delete()" method
00021 #
00022 #   AUTHOR:  Edward Almasy
00023 #
00024 #   Part of the Collection Workflow Integration System
00025 #   Copyright 2007 Edward Almasy and Internet Scout
00026 #   http://scout.wisc.edu
00027 #
00028 
00029 
00030 class ItemFactory {
00031 
00032     # ---- PUBLIC INTERFACE --------------------------------------------------
00033 
00034     # object constructor
00035     function ItemFactory($ItemClassName, $ItemTableName, $ItemIdFieldName, 
00036             $ItemNameFieldName = NULL, $FieldId = NULL, $OrderOpsAllowed = FALSE)
00037     {
00038         # save item access names
00039         $this->ItemClassName = $ItemClassName;
00040         $this->ItemTableName = $ItemTableName;
00041         $this->ItemIdFieldName = $ItemIdFieldName;
00042         $this->ItemNameFieldName = $ItemNameFieldName;
00043 
00044         # save field ID (if specified)
00045         if ($FieldId !== NULL) {  $this->FieldId = intval($FieldId);  }
00046 
00047         # save flag indicating whether item type allows ordering operations
00048         $this->OrderOpsAllowed = $OrderOpsAllowed;
00049         if ($OrderOpsAllowed)
00050         {  
00051             $this->OrderList = new DoublyLinkedItemList(
00052                     $ItemTableName, $ItemIdFieldName);
00053             $this->SetOrderOpsCondition(NULL);
00054         }
00055  
00056         # grab our own database handle
00057         $this->DB = new SPTDatabase();
00058         
00059         # assume everything will be okay
00060         $this->ErrorStatus = 0;
00061     }
00062     
00063     # return current error status
00064     function Status() {  return $this->ErrorStatus;  }
00065     
00066     # get ID of currently edited item
00067     function GetCurrentEditedItemId()
00068     {
00069         # if ID available in session variable
00070         global $Session;
00071         if ($EditedIds = $Session->Get($this->ItemClassName."EditedIds"))
00072         {
00073             # look up value in session variable
00074             $ItemId = $EditedIds[0];
00075         }
00076         else
00077         {
00078             # attempt to look up last temp item ID
00079             $ItemId = $this->GetLastTempItemId();
00080 
00081             # store it in session variable
00082             $EditedIds = array($ItemId);
00083             $Session->RegisterVariable($this->ItemClassName."EditedIds", $EditedIds);
00084         }
00085 
00086         # return ID (if any) to caller
00087         return $ItemId;
00088     }
00089 
00090     # set ID of currently edited item
00091     function SetCurrentEditedItemId($NewId)
00092     {
00093         # if edited ID array already stored for session
00094         global $Session;
00095         if ($EditedIds = $Session->Get($this->ItemClassName."EditedIds"))
00096         {
00097             # prepend new value to array
00098             array_unshift($EditedIds, $NewId);
00099         }
00100         else
00101         {
00102             # start with fresh array
00103             $EditedIds = array($NewId);
00104         }
00105 
00106         # save in session variable
00107         $Session->RegisterVariable($this->ItemClassName."EditedIds", $EditedIds);
00108     }
00109 
00110     # clear currently edited item ID
00111     function ClearCurrentEditedItemId()
00112     {
00113         # if edited item IDs available in a session variable
00114         global $Session;
00115         $SessionVarName = $this->ItemClassName."EditedIds";
00116         if ($EditedIds = $Session->Get($SessionVarName))
00117         {
00118             # remove current item from edited item ID array
00119             array_shift($EditedIds);
00120 
00121             # if no further edited items
00122             if (count($EditedIds) < 1)
00123             {
00124                 # destroy session variable
00125                 $Session->UnregisterVariable($SessionVarName);
00126             }
00127             else
00128             {
00129                 # save new shorter edited item ID array to session variable
00130                 $Session->RegisterVariable($SessionVarName, $EditedIds);
00131             }
00132         }
00133     }
00134 
00135     # clear currently edited item ID and item
00136     function ClearCurrentEditedItem()
00137     {
00138         # if current edited item is temp item
00139         $CurrentEditedItemId = $this->GetCurrentEditedItemId();
00140         if ($CurrentEditedItemId < 0)
00141         {
00142             # delete temp item from DB
00143             $this->DB->Query("DELETE FROM ".$this->ItemTableName
00144                              ." WHERE ".$this->ItemIdFieldName." = ".$CurrentEditedItemId);
00145         }
00146         
00147         # clear current edited item ID
00148         $this->ClearCurrentEditedItemId();
00149     }
00150 
00151     # clear out any temp items more than one week old
00152     function CleanOutStaleTempItems()
00153     {
00154         # load array of stale items
00155         $this->DB->Query("SELECT ".$this->ItemIdFieldName." FROM ".$this->ItemTableName
00156                    ." WHERE ".$this->ItemIdFieldName." < 0"
00157                    ." AND DateLastModified < DATE_SUB(NOW(), INTERVAL 7 DAY)");
00158         $ItemIds = $this->DB->FetchColumn($this->ItemIdFieldName);
00159         
00160         # delete stale items
00161         foreach ($ItemIds as $ItemId)
00162         {
00163             $Item = new $this->ItemClassName($ItemId);
00164             $Item->Delete();
00165         }
00166     }
00167     
00168     # retrieve most recent temp item ID based on user ID
00169     # (returns NULL if no temp item found for that user ID)
00170     function GetLastTempItemId()
00171     {
00172         # retrieve ID of most recently modified temp item for this user
00173         global $User;
00174         $ItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName." FROM ".$this->ItemTableName
00175                                  ." WHERE LastModifiedById = '".$User->Get("UserId")."'"
00176                                  ." AND ".$this->ItemIdFieldName." < 0"
00177                                  ." ORDER BY ".$this->ItemIdFieldName." ASC"
00178                                  ." LIMIT 1",
00179                                  $this->ItemIdFieldName);
00180         
00181         # return item to caller (or NULL if none found)
00182         return $ItemId;
00183     }
00184     
00185     # return next item ID
00186     function GetNextItemId()
00187     {
00188         # if no highest item ID found
00189         $HighestItemId = $this->GetHighestItemId();
00190         if ($HighestItemId <= 0)
00191         {
00192             # start with item ID 1
00193             $ItemId = 1;
00194         }
00195         else
00196         {
00197             # else use next ID available after highest
00198             $ItemId = $HighestItemId + 1;
00199         }
00200 
00201         # return next ID to caller
00202         return $ItemId;
00203     }
00204 
00205     # return highest item ID ($Condition should not include "WHERE")
00206     function GetHighestItemId($Condition = NULL, $IncludeTempItems = FALSE)
00207     {
00208         # if temp items are supposed to be included
00209         if ($IncludeTempItems)
00210         {
00211             # condition is only as supplied
00212             $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00213         }
00214         else
00215         {
00216             # condition is non-negative IDs plus supplied condition
00217             $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0"
00218                        .(($Condition == NULL) ? "" : " AND ".$Condition);
00219         }
00220 
00221         # return highest item ID to caller
00222         return $this->DB->Query("SELECT ".$this->ItemIdFieldName
00223                                     ." FROM ".$this->ItemTableName
00224                                     .$ConditionString
00225                                     ." ORDER BY ".$this->ItemIdFieldName
00226                                     ." DESC LIMIT 1",
00227                                 $this->ItemIdFieldName);
00228     }
00229     
00230     # return next temp item ID
00231     function GetNextTempItemId()
00232     {
00233         $LowestItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName
00234                                          ." FROM ".$this->ItemTableName
00235                                          ." ORDER BY ".$this->ItemIdFieldName
00236                                          ." ASC LIMIT 1", 
00237                                          $this->ItemIdFieldName);
00238         if ($LowestItemId > 0)
00239         {
00240             $ItemId = -1;
00241         }
00242         else
00243         {
00244             $ItemId = $LowestItemId - 1;
00245         }
00246         return $ItemId;
00247     }
00248 
00249     # return count of items
00250     function GetItemCount($Condition = NULL, $IncludeTempItems = FALSE)
00251     {
00252         # if condition was supplied
00253         if ($Condition != NULL)
00254         {
00255             # use condition
00256             $ConditionString = " WHERE ".$Condition;
00257         }
00258         else
00259         {
00260             # if field ID is available
00261             if (isset($this->FieldId))
00262             {
00263                 # use condition for matching field ID
00264                 $ConditionString = " WHERE FieldId = ".intval($this->FieldId);
00265             }
00266             else
00267             {
00268                 # use no condition
00269                 $ConditionString = "";
00270             }
00271         }
00272 
00273         # if temp items are to be excluded
00274         if (!$IncludeTempItems)
00275         {
00276             # if a condition was previously set
00277             if (strlen($ConditionString))
00278             {
00279                 # add in condition to exclude temp items
00280                 $ConditionString .= " AND (".$this->ItemIdFieldName." >= 0)";
00281             }
00282             else
00283             {
00284                 # use condition to exclude temp items
00285                 $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0";
00286             }
00287         }
00288 
00289         # retrieve item count
00290         $Count = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
00291                                       ." FROM ".$this->ItemTableName
00292                                       .$ConditionString,
00293                                   "RecordCount");
00294 
00295         # return count to caller
00296         return $Count;
00297     }
00298 
00299     # return array of item IDs ($Condition should not include "WHERE")
00300     function GetItemIds($Condition = NULL, $IncludeTempItems = FALSE)
00301     {
00302         # if temp items are supposed to be included
00303         if ($IncludeTempItems)
00304         {
00305             # condition is only as supplied
00306             $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00307         }
00308         else
00309         {
00310             # condition is non-negative IDs plus supplied condition
00311             $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0"
00312                        .(($Condition == NULL) ? "" : " AND ".$Condition);
00313         }
00314 
00315         # get item IDs
00316         $this->DB->Query("SELECT ".$this->ItemIdFieldName
00317                                       ." FROM ".$this->ItemTableName
00318                                       .$ConditionString);
00319         $ItemIds = $this->DB->FetchColumn($this->ItemIdFieldName);
00320 
00321         # return IDs to caller
00322         return $ItemIds;
00323     }
00324 
00325     # return latest modification date ($Condition should not include "WHERE")
00326     function GetLatestModificationDate($Condition = NULL)
00327     {
00328         # return modification date for item most recently changed
00329         $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00330         return $this->DB->Query("SELECT MAX(DateLastModified) AS LastChangeDate"
00331                                     ." FROM ".$this->ItemTableName.$ConditionString,
00332                                 "LastChangeDate");
00333     }
00334 
00335     # retrieve item by item ID
00336     function GetItem($ItemId)
00337     {
00338         return new $this->ItemClassName($ItemId);
00339     }
00340     
00341     # retrieve item by name
00342     function GetItemByName($Name, $IgnoreCase = FALSE)
00343     {
00344         # error out if this is an illegal operation for this item type
00345         if ($this->ItemNameFieldName == NULL)
00346         {
00347             exit("<br>SPT - ERROR: attempt to get item by name on item type"
00348                     ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00349         }
00350 
00351         # query database for item ID
00352         $Comparison = $IgnoreCase
00353                 ? "LOWER(".$this->ItemNameFieldName.") = '"
00354                         .addslashes(strtolower($Name))."'"
00355                 : $this->ItemNameFieldName." = '" .addslashes($Name)."'";
00356         $ItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName
00357                                       ." FROM ".$this->ItemTableName
00358                                       ." WHERE ".$Comparison
00359                                             .(isset($this->FieldId)
00360                                                     ? " AND FieldId = ".$this->FieldId
00361                                                     : ""),
00362                                    $this->ItemIdFieldName);
00363 
00364         # if item ID was not found
00365         if ($ItemId === NULL)
00366         {
00367             # return NULL to caller
00368             $Item = NULL;
00369         }
00370         else
00371         {
00372             # generate new item object
00373             $Item = $this->GetItem($ItemId);
00374         }
00375         
00376         # return new object to caller
00377         return $Item;
00378     }
00379 
00380     # retrieve array of item names indexed by IDs and sorted by name
00381     function GetItemNames()
00382     {
00383         # error out if this is an illegal operation for this item type
00384         if ($this->ItemNameFieldName == NULL)
00385         {
00386             exit("<br>SPT - ERROR: attempt to get array of item names on item type"
00387                     ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00388         }
00389 
00390         # query database for item names
00391         $this->DB->Query("SELECT ".$this->ItemIdFieldName
00392                                             .", ".$this->ItemNameFieldName
00393                                         ." FROM ".$this->ItemTableName
00394                                         .(isset($this->FieldId)
00395                                                 ? " WHERE FieldId = ".$this->FieldId
00396                                                 : "")
00397                                         ." ORDER BY ".$this->ItemNameFieldName);
00398         $Names = $this->DB->FetchColumn("Name", "Id");
00399 
00400         # return item names to caller
00401         return $Names;
00402     }
00403 
00404     # retrieve names of items matching search string (array index is IDs)
00405     # (NOTE:  IncludeVariants parameter is NOT YET SUPPORTED!)
00406     function SearchForItemNames($SearchString, $NumberOfResults = 100, 
00407             $IncludeVariants = FALSE, $UseBooleanMode = TRUE)
00408     {
00409         # error out if this is an illegal operation for this item type
00410         if ($this->ItemNameFieldName == NULL)
00411         {
00412             exit("<br>SPT - ERROR: attempt to search for item names on item type"
00413                     ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00414         }
00415 
00416         # return no results if empty search string passed in
00417         if (!strlen(trim($SearchString))) {  return array();  }
00418 
00419         # construct SQL query
00420         $QueryString = "SELECT ".$this->ItemIdFieldName.",".$this->ItemNameFieldName
00421                 ." FROM ".$this->ItemTableName." WHERE";
00422         if ($this->FieldId)
00423         {
00424             $QueryString .= " FieldId = ".$this->FieldId." AND";
00425         }
00426         if ($UseBooleanMode)
00427         {
00428             $SearchString = preg_replace("/[)\(><]+/", "", $SearchString);
00429             $Words = preg_split("/[\s]+/", trim($SearchString));
00430             $NewSearchString = "";
00431             $InQuotedString = FALSE;
00432             foreach ($Words as $Word)
00433             {
00434                 if ($InQuotedString == FALSE) {  $NewSearchString .= "+";  }
00435                 if (preg_match("/^\"/", $Word)) {  $InQuotedString = TRUE;  }
00436                 if (preg_match("/\"$/", $Word)) {  $InQuotedString = FALSE;  }
00437                 $NewSearchString .= $Word." ";
00438             }
00439             $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00440                     ." AGAINST ('".addslashes(trim($NewSearchString))."'"
00441                     ." IN BOOLEAN MODE)";
00442         }
00443         else
00444         {
00445             $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00446                     ." AGAINST ('".addslashes(trim($SearchString))."')";
00447         }
00448         $QueryString .= " LIMIT ".$NumberOfResults;
00449 
00450         # perform query and retrieve names and IDs of items found by query
00451         $DB = new SPTDatabase();
00452         $DB->Query($QueryString);
00453         $Names = $DB->FetchColumn($this->ItemNameFieldName, $this->ItemIdFieldName);
00454 
00455         # return names to caller
00456         return $Names;
00457     }
00458 
00467     function AddItems($ItemNames, $Qualifier = NULL)
00468     {
00469         # for each supplied item name
00470         $ItemCount = 0;
00471         foreach ($ItemNames as $Name)
00472         {
00473             # if item does not exist with this name
00474             $Name = trim($Name);
00475             if ($this->GetItemByName($Name) === NULL)
00476             {
00477                 # add item
00478                 $NewItem = new $this->ItemClassName(NULL, $Name, $this->FieldId);
00479                 $ItemCount++;
00480 
00481                 # assign qualifier to item if supplied
00482                 if ($Qualifier !== NULL)
00483                 {
00484                     $NewItem->Qualifier($Qualifier);
00485                 }
00486             }
00487         }
00488 
00489         # return count of items added to caller
00490         return $ItemCount;
00491     }
00492 
00493     # ---- order operations --------------------------------------------------
00494 
00495     # set SQL condition (added to WHERE clause) used to select items for ordering ops
00496     # (use NULL to clear any previous condition)
00497     function SetOrderOpsCondition($Condition)
00498     {
00499         # condition is non-negative IDs (non-temp items) plus supplied condition
00500         $NewCondition = $this->ItemIdFieldName." >= 0"
00501                    .(($Condition) ? " AND ".$Condition : "");
00502         $this->OrderList->SqlCondition($NewCondition);
00503     }
00504 
00505     # insert/move item to before specified item
00506     function InsertBefore($SourceItemOrItemId, $TargetItemOrItemId)
00507     {
00508         # error out if ordering operations are not allowed for this item type
00509         if (!$this->OrderOpsAllowed)
00510         {
00511             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00512                     ." (InsertBefore()) on item type"
00513                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00514         }
00515 
00516         # insert/move item
00517         $this->OrderList->InsertBefore($SourceItemOrItemId, $TargetItemOrItemId);
00518     }
00519 
00520     # insert/move item to after specified item
00521     function InsertAfter($SourceItemOrItemId, $TargetItemOrItemId)
00522     {
00523         # error out if ordering operations are not allowed for this item type
00524         if (!$this->OrderOpsAllowed)
00525         {
00526             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00527                     ." (InsertAfter()) on item type"
00528                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00529         }
00530 
00531         # insert/move item
00532         $this->OrderList->InsertAfter($SourceItemOrItemId, $TargetItemOrItemId);
00533     }
00534 
00535     # add/move item to beginning of list
00536     function Prepend($ItemOrItemId)
00537     {
00538         # error out if ordering operations are not allowed for this item type
00539         if (!$this->OrderOpsAllowed)
00540         {
00541             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00542                     ." (Prepend()) on item type"
00543                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00544         }
00545 
00546         # prepend item
00547         $this->OrderList->Prepend($ItemOrItemId);
00548     }
00549 
00550     # add/move item to end of list
00551     function Append($ItemOrItemId)
00552     {
00553         # error out if ordering operations are not allowed for this item type
00554         if (!$this->OrderOpsAllowed)
00555         {
00556             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00557                     ." (Append()) on item type"
00558                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00559         }
00560 
00561         # add/move item
00562         $this->OrderList->Append($ItemOrItemId);
00563     }
00564 
00565     # retrieve list of item IDs in order
00566     function GetItemIdsInOrder($AddStrayItemsToOrder = TRUE)
00567     {
00568         # error out if ordering operations are not allowed for this item type
00569         if (!$this->OrderOpsAllowed)
00570         {
00571             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00572                     ." (GetItemIdsInOrder()) on item type"
00573                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00574         }
00575 
00576         # retrieve list of IDs
00577         return $this->OrderList->GetIds($AddStrayItemsToOrder);
00578     }
00579 
00580     # remove item from existing order
00581     function RemoveItemFromOrder($ItemId)
00582     {
00583         # error out if ordering operations are not allowed for this item type
00584         if (!$this->OrderOpsAllowed)
00585         {
00586             exit("<br>SPT - ERROR: attempt to perform ordering operation"
00587                     ." (RemoveItemFromOrder()) on item type"
00588                     ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00589         }
00590 
00591         # remove item
00592         $this->OrderList->Remove($ItemId);
00593     }
00594 
00595 
00596     # ---- PRIVATE INTERFACE -------------------------------------------------
00597 
00598     var $ItemClassName;
00599     var $ItemTableName;
00600     var $ItemIdFieldName;
00601     var $ItemNameFieldName;
00602     var $DB;
00603     var $ErrorStatus;
00604     var $FieldId;
00605     var $OrderOpsAllowed;
00606     var $OrderList;
00607  
00608     # get/set ordering values
00609     function GetPreviousItemId($ItemId)
00610     {
00611         return $this->DB->Query("SELECT Previous".$this->ItemIdFieldName
00612                     ." FROM ".$this->ItemTableName
00613                     ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId), 
00614                 "Previous".$this->ItemIdFieldName);
00615     }
00616     function GetNextItemIdInOrder($ItemId)
00617     {
00618         return $this->DB->Query("SELECT Next".$this->ItemIdFieldName
00619                     ." FROM ".$this->ItemTableName
00620                     ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId), 
00621                 "Next".$this->ItemIdFieldName);
00622     }
00623     function SetPreviousItemId($ItemId, $NewValue)
00624     {
00625         $this->DB->Query("UPDATE ".$this->ItemTableName
00626                 ." SET Previous".$this->ItemIdFieldName." = ".intval($NewValue)
00627                 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00628     }
00629     function SetNextItemId($ItemId, $NewValue)
00630     {
00631         $this->DB->Query("UPDATE ".$this->ItemTableName
00632                 ." SET Next".$this->ItemIdFieldName." = ".intval($NewValue)
00633                 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00634     }
00635     function SetPreviousAndNextItemIds($ItemId, $NewPreviousId, $NewNextId)
00636     {
00637         $this->DB->Query("UPDATE ".$this->ItemTableName
00638                 ." SET Previous".$this->ItemIdFieldName." = ".intval($NewPreviousId)
00639                         .", Next".$this->ItemIdFieldName." = ".intval($NewNextId)
00640                 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00641     }
00642 }
00643 
00644 
00645 ?>
CWIS logo doxygen
Copyright 2009 Internet Scout