00001 <?PHP
00002
00003 #
00004 # FILE: ItemFactory.php
00005 #
00006 # NOTES:
00007 # - for a derived class to use the temp methods the item record in the
00008 # database must include "DateLastModified" and "LastModifiedById"
00009 # fields, and the item object must include a "Delete()" method
00010 #
00011 # Copyright 2007-2010 Edward Almasy and Internet Scout
00012 # http://scout.wisc.edu
00013 #
00014
00015 class ItemFactory {
00016
00017 # ---- PUBLIC INTERFACE --------------------------------------------------
00018
00019 # object constructor
00020 function ItemFactory($ItemClassName, $ItemTableName, $ItemIdFieldName,
00021 $ItemNameFieldName = NULL, $FieldId = NULL, $OrderOpsAllowed = FALSE)
00022 {
00023 # save item access names
00024 $this->ItemClassName = $ItemClassName;
00025 $this->ItemTableName = $ItemTableName;
00026 $this->ItemIdFieldName = $ItemIdFieldName;
00027 $this->ItemNameFieldName = $ItemNameFieldName;
00028
00029 # save field ID (if specified)
00030 if ($FieldId !== NULL) { $this->FieldId = intval($FieldId); }
00031
00032 # save flag indicating whether item type allows ordering operations
00033 $this->OrderOpsAllowed = $OrderOpsAllowed;
00034 if ($OrderOpsAllowed)
00035 {
00036 $this->OrderList = new DoublyLinkedItemList(
00037 $ItemTableName, $ItemIdFieldName);
00038 $this->SetOrderOpsCondition(NULL);
00039 }
00040
00041 # grab our own database handle
00042 $this->DB = new Database();
00043
00044 # assume everything will be okay
00045 $this->ErrorStatus = 0;
00046 }
00047
00048 # return current error status
00049 function Status() { return $this->ErrorStatus; }
00050
00051 # get ID of currently edited item
00052 function GetCurrentEditedItemId()
00053 {
00054 # if ID available in session variable
00055 global $Session;
00056 if ($EditedIds = $Session->Get($this->ItemClassName."EditedIds"))
00057 {
00058 # look up value in session variable
00059 $ItemId = $EditedIds[0];
00060 }
00061 else
00062 {
00063 # attempt to look up last temp item ID
00064 $ItemId = $this->GetLastTempItemId();
00065
00066 # store it in session variable
00067 $EditedIds = array($ItemId);
00068 $Session->RegisterVariable($this->ItemClassName."EditedIds", $EditedIds);
00069 }
00070
00071 # return ID (if any) to caller
00072 return $ItemId;
00073 }
00074
00075 # set ID of currently edited item
00076 function SetCurrentEditedItemId($NewId)
00077 {
00078 # if edited ID array already stored for session
00079 global $Session;
00080 if ($EditedIds = $Session->Get($this->ItemClassName."EditedIds"))
00081 {
00082 # prepend new value to array
00083 array_unshift($EditedIds, $NewId);
00084 }
00085 else
00086 {
00087 # start with fresh array
00088 $EditedIds = array($NewId);
00089 }
00090
00091 # save in session variable
00092 $Session->RegisterVariable($this->ItemClassName."EditedIds", $EditedIds);
00093 }
00094
00095 # clear currently edited item ID
00096 function ClearCurrentEditedItemId()
00097 {
00098 # if edited item IDs available in a session variable
00099 global $Session;
00100 $SessionVarName = $this->ItemClassName."EditedIds";
00101 if ($EditedIds = $Session->Get($SessionVarName))
00102 {
00103 # remove current item from edited item ID array
00104 array_shift($EditedIds);
00105
00106 # if no further edited items
00107 if (count($EditedIds) < 1)
00108 {
00109 # destroy session variable
00110 $Session->UnregisterVariable($SessionVarName);
00111 }
00112 else
00113 {
00114 # save new shorter edited item ID array to session variable
00115 $Session->RegisterVariable($SessionVarName, $EditedIds);
00116 }
00117 }
00118 }
00119
00120 # clear currently edited item ID and item
00121 function ClearCurrentEditedItem()
00122 {
00123 # if current edited item is temp item
00124 $CurrentEditedItemId = $this->GetCurrentEditedItemId();
00125 if ($CurrentEditedItemId < 0)
00126 {
00127 # delete temp item from DB
00128 $this->DB->Query("DELETE FROM ".$this->ItemTableName
00129 ." WHERE ".$this->ItemIdFieldName." = ".$CurrentEditedItemId);
00130 }
00131
00132 # clear current edited item ID
00133 $this->ClearCurrentEditedItemId();
00134 }
00135
00143 function CleanOutStaleTempItems($MinutesUntilStale = 10080)
00144 {
00145 # load array of stale items
00146 $MinutesUntilStale = max($MinutesUntilStale, 1);
00147 $this->DB->Query("SELECT ".$this->ItemIdFieldName." FROM ".$this->ItemTableName
00148 ." WHERE ".$this->ItemIdFieldName." < 0"
00149 ." AND DateLastModified < DATE_SUB(NOW(), "
00150 ." INTERVAL ".intval($MinutesUntilStale)." MINUTE)");
00151 $ItemIds = $this->DB->FetchColumn($this->ItemIdFieldName);
00152
00153 # delete stale items
00154 foreach ($ItemIds as $ItemId)
00155 {
00156 $Item = new $this->ItemClassName($ItemId);
00157 $Item->Delete();
00158 }
00159
00160 # report number of items deleted to caller
00161 return count($ItemIds);
00162 }
00163
00164 # retrieve most recent temp item ID based on user ID
00165 # (returns NULL if no temp item found for that user ID)
00166 function GetLastTempItemId()
00167 {
00168 # retrieve ID of most recently modified temp item for this user
00169 global $User;
00170 $ItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName." FROM ".$this->ItemTableName
00171 ." WHERE LastModifiedById = '".$User->Get("UserId")."'"
00172 ." AND ".$this->ItemIdFieldName." < 0"
00173 ." ORDER BY ".$this->ItemIdFieldName." ASC"
00174 ." LIMIT 1",
00175 $this->ItemIdFieldName);
00176
00177 # return item to caller (or NULL if none found)
00178 return $ItemId;
00179 }
00180
00181 # return next item ID
00182 function GetNextItemId()
00183 {
00184 # if no highest item ID found
00185 $HighestItemId = $this->GetHighestItemId();
00186 if ($HighestItemId <= 0)
00187 {
00188 # start with item ID 1
00189 $ItemId = 1;
00190 }
00191 else
00192 {
00193 # else use next ID available after highest
00194 $ItemId = $HighestItemId + 1;
00195 }
00196
00197 # return next ID to caller
00198 return $ItemId;
00199 }
00200
00201 # return highest item ID ($Condition should not include "WHERE")
00202 function GetHighestItemId($Condition = NULL, $IncludeTempItems = FALSE)
00203 {
00204 # if temp items are supposed to be included
00205 if ($IncludeTempItems)
00206 {
00207 # condition is only as supplied
00208 $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00209 }
00210 else
00211 {
00212 # condition is non-negative IDs plus supplied condition
00213 $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0"
00214 .(($Condition == NULL) ? "" : " AND ".$Condition);
00215 }
00216
00217 # return highest item ID to caller
00218 return $this->DB->Query("SELECT ".$this->ItemIdFieldName
00219 ." FROM ".$this->ItemTableName
00220 .$ConditionString
00221 ." ORDER BY ".$this->ItemIdFieldName
00222 ." DESC LIMIT 1",
00223 $this->ItemIdFieldName);
00224 }
00225
00226 # return next temp item ID
00227 function GetNextTempItemId()
00228 {
00229 $LowestItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName
00230 ." FROM ".$this->ItemTableName
00231 ." ORDER BY ".$this->ItemIdFieldName
00232 ." ASC LIMIT 1",
00233 $this->ItemIdFieldName);
00234 if ($LowestItemId > 0)
00235 {
00236 $ItemId = -1;
00237 }
00238 else
00239 {
00240 $ItemId = $LowestItemId - 1;
00241 }
00242 return $ItemId;
00243 }
00244
00245 # return count of items
00246 function GetItemCount($Condition = NULL, $IncludeTempItems = FALSE)
00247 {
00248 # if condition was supplied
00249 if ($Condition != NULL)
00250 {
00251 # use condition
00252 $ConditionString = " WHERE ".$Condition;
00253 }
00254 else
00255 {
00256 # if field ID is available
00257 if (isset($this->FieldId))
00258 {
00259 # use condition for matching field ID
00260 $ConditionString = " WHERE FieldId = ".intval($this->FieldId);
00261 }
00262 else
00263 {
00264 # use no condition
00265 $ConditionString = "";
00266 }
00267 }
00268
00269 # if temp items are to be excluded
00270 if (!$IncludeTempItems)
00271 {
00272 # if a condition was previously set
00273 if (strlen($ConditionString))
00274 {
00275 # add in condition to exclude temp items
00276 $ConditionString .= " AND (".$this->ItemIdFieldName." >= 0)";
00277 }
00278 else
00279 {
00280 # use condition to exclude temp items
00281 $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0";
00282 }
00283 }
00284
00285 # retrieve item count
00286 $Count = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
00287 ." FROM ".$this->ItemTableName
00288 .$ConditionString,
00289 "RecordCount");
00290
00291 # return count to caller
00292 return $Count;
00293 }
00294
00295 # return array of item IDs ($Condition should not include "WHERE")
00296 function GetItemIds($Condition = NULL, $IncludeTempItems = FALSE)
00297 {
00298 # if temp items are supposed to be included
00299 if ($IncludeTempItems)
00300 {
00301 # condition is only as supplied
00302 $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00303 }
00304 else
00305 {
00306 # condition is non-negative IDs plus supplied condition
00307 $ConditionString = " WHERE ".$this->ItemIdFieldName." >= 0"
00308 .(($Condition == NULL) ? "" : " AND ".$Condition);
00309 }
00310
00311 # get item IDs
00312 $this->DB->Query("SELECT ".$this->ItemIdFieldName
00313 ." FROM ".$this->ItemTableName
00314 .$ConditionString);
00315 $ItemIds = $this->DB->FetchColumn($this->ItemIdFieldName);
00316
00317 # return IDs to caller
00318 return $ItemIds;
00319 }
00320
00321 # return latest modification date ($Condition should not include "WHERE")
00322 function GetLatestModificationDate($Condition = NULL)
00323 {
00324 # return modification date for item most recently changed
00325 $ConditionString = ($Condition == NULL) ? "" : " WHERE ".$Condition;
00326 return $this->DB->Query("SELECT MAX(DateLastModified) AS LastChangeDate"
00327 ." FROM ".$this->ItemTableName.$ConditionString,
00328 "LastChangeDate");
00329 }
00330
00331 # retrieve item by item ID
00332 function GetItem($ItemId)
00333 {
00334 return new $this->ItemClassName($ItemId);
00335 }
00336
00341 function ItemExists($ItemId)
00342 {
00343 return $this->DB->Query("SELECT COUNT(*) AS ItemCount"
00344 ." FROM ".$this->ItemTableName
00345 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId), "ItemCount")
00346 > 0 ? TRUE : FALSE;
00347 }
00348
00349 # retrieve item by name
00350 function GetItemByName($Name, $IgnoreCase = FALSE)
00351 {
00352 # error out if this is an illegal operation for this item type
00353 if ($this->ItemNameFieldName == NULL)
00354 {
00355 exit("<br>ERROR: attempt to get item by name on item type"
00356 ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00357 }
00358
00359 # query database for item ID
00360 $Comparison = $IgnoreCase
00361 ? "LOWER(".$this->ItemNameFieldName.") = '"
00362 .addslashes(strtolower($Name))."'"
00363 : $this->ItemNameFieldName." = '" .addslashes($Name)."'";
00364 $ItemId = $this->DB->Query("SELECT ".$this->ItemIdFieldName
00365 ." FROM ".$this->ItemTableName
00366 ." WHERE ".$Comparison
00367 .(isset($this->FieldId)
00368 ? " AND FieldId = ".$this->FieldId
00369 : ""),
00370 $this->ItemIdFieldName);
00371
00372 # if item ID was not found
00373 if ($ItemId === NULL)
00374 {
00375 # return NULL to caller
00376 $Item = NULL;
00377 }
00378 else
00379 {
00380 # generate new item object
00381 $Item = $this->GetItem($ItemId);
00382 }
00383
00384 # return new object to caller
00385 return $Item;
00386 }
00387
00393 function GetItemNames($SqlCondition = NULL)
00394 {
00395 # error out if this is an illegal operation for this item type
00396 if ($this->ItemNameFieldName == NULL)
00397 {
00398 exit("<br>ERROR: attempt to get array of item names on item type"
00399 ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00400 }
00401
00402 # query database for item names
00403 $Condition = "";
00404 if ($this->FieldId || $SqlCondition)
00405 {
00406 $Condition = "WHERE ";
00407 if ($this->FieldId)
00408 $Condition .= "FieldId = ".intval($this->FieldId);
00409 if ($this->FieldId && $SqlCondition)
00410 $Condition .= " AND ";
00411 if ($SqlCondition)
00412 $Condition .= $SqlCondition;
00413 }
00414 $this->DB->Query("SELECT ".$this->ItemIdFieldName
00415 .", ".$this->ItemNameFieldName
00416 ." FROM ".$this->ItemTableName." "
00417 .$Condition
00418 ." ORDER BY ".$this->ItemNameFieldName);
00419 $Names = $this->DB->FetchColumn(
00420 $this->ItemNameFieldName, $this->ItemIdFieldName);
00421
00422 # return item names to caller
00423 return $Names;
00424 }
00425
00431 function GetItems($SqlCondition = NULL)
00432 {
00433 $Items = array();
00434 $Names = $this->GetItemNames($SqlCondition);
00435 foreach ($Names as $Id => $Name)
00436 {
00437 $Items[$Id] = $this->GetItem($Id);
00438 }
00439 return $Items;
00440 }
00441
00455 function GetItemsAsOptionList($OptionListName, $SelectedItemId = NULL,
00456 $SqlCondition = NULL, $DisplaySize = 1, $SubmitOnChange = FALSE)
00457 {
00458 # retrieve requested fields
00459 $ItemNames = $this->GetItemNames($SqlCondition);
00460
00461 # if multiple selections are allowed
00462 if ($DisplaySize > 1)
00463 {
00464 # begin multi-selection HTML option list
00465 $Html = "<select name=\"".htmlspecialchars($OptionListName)."[]\""
00466 .($SubmitOnChange ? " onChange=\"submit()\"" : "")
00467 ." multiple=\"multiple\" size=\"".$DisplaySize."\">\n";
00468 }
00469 else
00470 {
00471 # begin single-selection HTML option list
00472 $Html = "<select name=\"".htmlspecialchars($OptionListName)."\""
00473 .($SubmitOnChange ? " onChange=\"submit()\"" : "")
00474 ." size=\"1\">\n";
00475 $Html .= "<option value=\"-1\">--</option>\n";
00476 }
00477
00478 # for each metadata field
00479 foreach ($ItemNames as $Id => $Name)
00480 {
00481 # add entry for field to option list
00482 $Html .= "<option value=\"".$Id."\"";
00483 if (($Id == $SelectedItemId)
00484 || (is_array($SelectedItemId) && in_array($Id, $SelectedItemId)))
00485 {
00486 $Html .= " selected";
00487 }
00488 $Html .= ">".htmlspecialchars($Name)."</option>\n";
00489 }
00490
00491 # end HTML option list
00492 $Html .= "</select>\n";
00493
00494 # return constructed HTML to caller
00495 return $Html;
00496 }
00503 function NameIsInUse($Name, $IgnoreCase = FALSE)
00504 {
00505 $Condition = $IgnoreCase
00506 ? "LOWER(".$this->ItemNameFieldName.")"
00507 ." = '".addslashes(strtolower($Name))."'"
00508 : $this->ItemNameFieldName." = '".addslashes($Name)."'";
00509 $NameCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM "
00510 .$this->ItemTableName." WHERE ".$Condition, "RecordCount");
00511 return ($NameCount > 0) ? TRUE : FALSE;
00512 }
00513
00514 # retrieve names of items matching search string (array index is IDs)
00515 # (NOTE: IncludeVariants parameter is NOT YET SUPPORTED!)
00516 function SearchForItemNames($SearchString, $NumberOfResults = 100,
00517 $IncludeVariants = FALSE, $UseBooleanMode = TRUE, $Offset=0)
00518 {
00519 # error out if this is an illegal operation for this item type
00520 if ($this->ItemNameFieldName == NULL)
00521 {
00522 exit("<br>ERROR: attempt to search for item names on item type"
00523 ."(".$this->ItemClassName.") that has no name field specified<br>\n");
00524 }
00525
00526 # return no results if empty search string passed in
00527 if (!strlen(trim($SearchString))) { return array(); }
00528
00529 # construct SQL query
00530 $DB = new Database();
00531 $QueryString = "SELECT ".$this->ItemIdFieldName.",".$this->ItemNameFieldName
00532 ." FROM ".$this->ItemTableName." WHERE";
00533 if ($this->FieldId)
00534 {
00535 $QueryString .= " FieldId = ".$this->FieldId." AND";
00536 }
00537 if ($UseBooleanMode)
00538 {
00539 $SearchString = preg_replace("/[)\(><]+/", "", $SearchString);
00540 $Words = preg_split("/[\s]+/", trim($SearchString));
00541 $NewSearchString = "";
00542 $InQuotedString = FALSE;
00543 $SqlVarObj = new MysqlSystemVariables($DB);
00544 $StopWordList = $SqlVarObj->GetStopWords();
00545 $MinWordLen = $SqlVarObj->Get("ft_min_word_len");
00546 foreach ($Words as $Word)
00547 {
00548 # remove any query-specific terms, punctuation, etc.
00549 $JustTheWord = preg_replace("/[^a-zA-Z-]/", "", $Word);
00550
00551 # require (boolean AND) certain words
00552 if ($InQuotedString == FALSE
00553 && !in_array($JustTheWord, $StopWordList)
00554 && strlen($JustTheWord) >= $MinWordLen
00555 && $Word{0} != "+"
00556 && $Word{0} != "-")
00557 {
00558 $NewSearchString .= "+";
00559 }
00560
00561 if (preg_match("/^\"/", $Word)) { $InQuotedString = TRUE; }
00562 if (preg_match("/\"$/", $Word)) { $InQuotedString = FALSE; }
00563 $NewSearchString .= $Word." ";
00564 }
00565
00566 $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00567 ." AGAINST ('".addslashes(trim($NewSearchString))."'"
00568 ." IN BOOLEAN MODE)";
00569 }
00570 else
00571 {
00572 $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00573 ." AGAINST ('".addslashes(trim($SearchString))."')";
00574 }
00575 $QueryString .= " LIMIT ".intval($NumberOfResults)." OFFSET "
00576 .intval($Offset);
00577
00578 # perform query and retrieve names and IDs of items found by query
00579 $DB->Query($QueryString);
00580 $Names = $DB->FetchColumn($this->ItemNameFieldName, $this->ItemIdFieldName);
00581
00582 if ($UseBooleanMode)
00583 {
00584 foreach ($Words as $Word)
00585 {
00586 $TgtWord = preg_replace("/[^a-zA-Z]/", "", $Word);
00587 if ($Word{0} == "-" && strlen($TgtWord) < $MinWordLen)
00588 {
00589 $NewNames = array();
00590 foreach ($Names as $Id => $Name)
00591 {
00592 if (! preg_match('/\b'.$TgtWord.'/i', $Name))
00593 {
00594 $NewNames[$Id] = $Name;
00595 }
00596 }
00597 $Names = $NewNames;
00598 }
00599 }
00600 }
00601
00602 # return names to caller
00603 return $Names;
00604 }
00605
00606 # retrieve the count of names of items matching search string (array index
00607 # is IDs) (NOTE: IncludeVariants parameter is NOT YET SUPPORTED!)
00608 function GetCountForItemNames($SearchString, $IncludeVariants = FALSE,
00609 $UseBooleanMode = TRUE)
00610 {
00611 # return no results if empty search string passed in
00612 if (!strlen(trim($SearchString))) { return 0; }
00613
00614 # construct SQL query
00615 $DB = new Database();
00616 $QueryString = "SELECT COUNT(*) as ItemCount FROM "
00617 .$this->ItemTableName." WHERE";
00618 if ($this->FieldId)
00619 {
00620 $QueryString .= " FieldId = ".$this->FieldId." AND";
00621 }
00622 if ($UseBooleanMode)
00623 {
00624 $SearchString = preg_replace("/[)\(><]+/", "", $SearchString);
00625 $Words = preg_split("/[\s]+/", trim($SearchString));
00626 $NewSearchString = "";
00627 $InQuotedString = FALSE;
00628 $SqlVarObj = new MysqlSystemVariables($DB);
00629 $StopWordList = $SqlVarObj->GetStopWords();
00630 $MinWordLen = $SqlVarObj->Get("ft_min_word_len");
00631 foreach ($Words as $Word)
00632 {
00633 # remove any query-specific terms, punctuation, etc.
00634 $JustTheWord = preg_replace("/[^a-zA-Z-]/", "", $Word);
00635
00636 # require (boolean AND) certain words
00637 if ($InQuotedString == FALSE
00638 && !in_array($JustTheWord, $StopWordList)
00639 && strlen($JustTheWord) >= $MinWordLen
00640 && $Word{0} != "+"
00641 && $Word{0} != "-")
00642 {
00643 $NewSearchString .= "+";
00644 }
00645
00646 if (preg_match("/^\"/", $Word)) { $InQuotedString = TRUE; }
00647 if (preg_match("/\"$/", $Word)) { $InQuotedString = FALSE; }
00648 $NewSearchString .= $Word." ";
00649 }
00650
00651 $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00652 ." AGAINST ('".addslashes(trim($NewSearchString))."'"
00653 ." IN BOOLEAN MODE)";
00654 }
00655 else
00656 {
00657 $QueryString .= " MATCH (".$this->ItemNameFieldName.")"
00658 ." AGAINST ('".addslashes(trim($SearchString))."')";
00659 }
00660
00661 # perform query and retrieve names and IDs of items found by query
00662 $DB->Query($QueryString);
00663 return intval($DB->FetchField("ItemCount"));
00664 }
00665
00674 function AddItems($ItemNames, $Qualifier = NULL)
00675 {
00676 # for each supplied item name
00677 $ItemCount = 0;
00678 foreach ($ItemNames as $Name)
00679 {
00680 # if item does not exist with this name
00681 $Name = trim($Name);
00682 if ($this->GetItemByName($Name) === NULL)
00683 {
00684 # add item
00685 $NewItem = new $this->ItemClassName(NULL, $Name, $this->FieldId);
00686 $ItemCount++;
00687
00688 # assign qualifier to item if supplied
00689 if ($Qualifier !== NULL)
00690 {
00691 $NewItem->Qualifier($Qualifier);
00692 }
00693 }
00694 }
00695
00696 # return count of items added to caller
00697 return $ItemCount;
00698 }
00699
00700 # ---- order operations --------------------------------------------------
00701
00702 # set SQL condition (added to WHERE clause) used to select items for ordering ops
00703 # (use NULL to clear any previous condition)
00704 function SetOrderOpsCondition($Condition)
00705 {
00706 # condition is non-negative IDs (non-temp items) plus supplied condition
00707 $NewCondition = $this->ItemIdFieldName." >= 0"
00708 .(($Condition) ? " AND ".$Condition : "");
00709 $this->OrderList->SqlCondition($NewCondition);
00710 }
00711
00712 # insert/move item to before specified item
00713 function InsertBefore($SourceItemOrItemId, $TargetItemOrItemId)
00714 {
00715 # error out if ordering operations are not allowed for this item type
00716 if (!$this->OrderOpsAllowed)
00717 {
00718 exit("<br>ERROR: attempt to perform ordering operation"
00719 ." (InsertBefore()) on item type"
00720 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00721 }
00722
00723 # insert/move item
00724 $this->OrderList->InsertBefore($SourceItemOrItemId, $TargetItemOrItemId);
00725 }
00726
00727 # insert/move item to after specified item
00728 function InsertAfter($SourceItemOrItemId, $TargetItemOrItemId)
00729 {
00730 # error out if ordering operations are not allowed for this item type
00731 if (!$this->OrderOpsAllowed)
00732 {
00733 exit("<br>ERROR: attempt to perform ordering operation"
00734 ." (InsertAfter()) on item type"
00735 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00736 }
00737
00738 # insert/move item
00739 $this->OrderList->InsertAfter($SourceItemOrItemId, $TargetItemOrItemId);
00740 }
00741
00742 # add/move item to beginning of list
00743 function Prepend($ItemOrItemId)
00744 {
00745 # error out if ordering operations are not allowed for this item type
00746 if (!$this->OrderOpsAllowed)
00747 {
00748 exit("<br>ERROR: attempt to perform ordering operation"
00749 ." (Prepend()) on item type"
00750 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00751 }
00752
00753 # prepend item
00754 $this->OrderList->Prepend($ItemOrItemId);
00755 }
00756
00757 # add/move item to end of list
00758 function Append($ItemOrItemId)
00759 {
00760 # error out if ordering operations are not allowed for this item type
00761 if (!$this->OrderOpsAllowed)
00762 {
00763 exit("<br>ERROR: attempt to perform ordering operation"
00764 ." (Append()) on item type"
00765 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00766 }
00767
00768 # add/move item
00769 $this->OrderList->Append($ItemOrItemId);
00770 }
00771
00772 # retrieve list of item IDs in order
00773 function GetItemIdsInOrder($AddStrayItemsToOrder = TRUE)
00774 {
00775 # error out if ordering operations are not allowed for this item type
00776 if (!$this->OrderOpsAllowed)
00777 {
00778 exit("<br>ERROR: attempt to perform ordering operation"
00779 ." (GetItemIdsInOrder()) on item type"
00780 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00781 }
00782
00783 # retrieve list of IDs
00784 return $this->OrderList->GetIds($AddStrayItemsToOrder);
00785 }
00786
00787 # remove item from existing order
00788 function RemoveItemFromOrder($ItemId)
00789 {
00790 # error out if ordering operations are not allowed for this item type
00791 if (!$this->OrderOpsAllowed)
00792 {
00793 exit("<br>ERROR: attempt to perform ordering operation"
00794 ." (RemoveItemFromOrder()) on item type"
00795 ."(".$this->ItemClassName.") that does not support ordering<br>\n");
00796 }
00797
00798 # remove item
00799 $this->OrderList->Remove($ItemId);
00800 }
00801
00802
00803 # ---- PRIVATE INTERFACE -------------------------------------------------
00804
00805 protected $DB;
00806 protected $FieldId;
00807
00808 private $ItemClassName;
00809 private $ItemTableName;
00810 private $ItemIdFieldName;
00811 private $ItemNameFieldName;
00812 private $ErrorStatus;
00813 private $OrderOpsAllowed;
00814 private $OrderList;
00815
00816 # get/set ordering values
00817 private function GetPreviousItemId($ItemId)
00818 {
00819 return $this->DB->Query("SELECT Previous".$this->ItemIdFieldName
00820 ." FROM ".$this->ItemTableName
00821 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId),
00822 "Previous".$this->ItemIdFieldName);
00823 }
00824 private function GetNextItemIdInOrder($ItemId)
00825 {
00826 return $this->DB->Query("SELECT Next".$this->ItemIdFieldName
00827 ." FROM ".$this->ItemTableName
00828 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId),
00829 "Next".$this->ItemIdFieldName);
00830 }
00831 private function SetPreviousItemId($ItemId, $NewValue)
00832 {
00833 $this->DB->Query("UPDATE ".$this->ItemTableName
00834 ." SET Previous".$this->ItemIdFieldName." = ".intval($NewValue)
00835 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00836 }
00837 private function SetNextItemId($ItemId, $NewValue)
00838 {
00839 $this->DB->Query("UPDATE ".$this->ItemTableName
00840 ." SET Next".$this->ItemIdFieldName." = ".intval($NewValue)
00841 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00842 }
00843 private function SetPreviousAndNextItemIds($ItemId, $NewPreviousId, $NewNextId)
00844 {
00845 $this->DB->Query("UPDATE ".$this->ItemTableName
00846 ." SET Previous".$this->ItemIdFieldName." = ".intval($NewPreviousId)
00847 .", Next".$this->ItemIdFieldName." = ".intval($NewNextId)
00848 ." WHERE ".$this->ItemIdFieldName." = ".intval($ItemId));
00849 }
00850 }
00851
00852 ?>