Search:

CWIS Developers Documentation

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

Classification.php

Go to the documentation of this file.
00001 <?PHP
00002 
00003 #
00004 #   FILE:  Classification.php
00005 #   AUTHOR:  Edward Almasy
00006 #
00007 #   Part of the Scout Portal Toolkit
00008 #   Copyright 2002-2003 Internet Scout Project
00009 #   http://scout.wisc.edu
00010 #
00011 
00015 class Classification {
00016 
00017     # ---- PUBLIC INTERFACE --------------------------------------------------
00018 
00019     # error status codes
00020     const CLASSSTAT_OK = 0;
00021     const CLASSSTAT_INVALIDID = 1;
00022     const CLASSSTAT_INVALIDPARENTID = 2;
00023     const CLASSSTAT_DUPLICATENAME = 3;
00024 
00036     function Classification($ClassId, $Name = NULL, $FieldId = NULL, $ParentId = NULL)
00037     {
00038         static $IdCache;
00039 
00040         # assume everything will turn out okay
00041         $this->ErrorStatus = Classification::CLASSSTAT_OK;
00042         
00043         # create DB handle for our use
00044         $this->DB = new SPTDatabase();
00045         $DB = $this->DB;
00046 
00047         # if class ID not given (indicating class must be created)
00048         if ($ClassId === NULL)
00049         {
00050             # if parent class supplied
00051             if ($ParentId !== NULL)
00052             {
00053                 # if parent ID was invalid
00054                 if (($ParentId != -1) 
00055                     && ($DB->Query("SELECT COUNT(*) AS NumberFound"
00056                                    ." FROM Classifications"
00057                                    ." WHERE ClassificationId = ".intval($ParentId),
00058                                    "NumberFound") < 1))
00059                 {
00060                     # set error code for bad parent ID
00061                     $this->ErrorStatus = Classification::CLASSSTAT_INVALIDPARENTID;
00062                 }
00063                 else
00064                 {
00065                     # if name already exists
00066                     $Name = trim($Name);
00067                     if ($FieldId === NULL)
00068                     {
00069                         # If we know what field we're trying to add a classifcation for,
00070                         # Check just within that field
00071                         $Count = $DB->Query("SELECT COUNT(*) AS NumberFound FROM Classifications"
00072                                 ." WHERE ParentId = ".intval($ParentId)
00073                                 ." AND LOWER(SegmentName) = '"
00074                                         .addslashes(strtolower($Name))."'",
00075                                             "NumberFound");
00076                     }
00077                     else
00078                     {
00079                         # Otherwise, check all classifications for all fields
00080                         $Count = $DB->Query("SELECT COUNT(*) AS NumberFound FROM Classifications"
00081                                             ." WHERE ParentId = ".intval($ParentId)
00082                                             ." AND FieldId = ".intval($FieldId)
00083                                             ." AND LOWER(SegmentName) = '"
00084                                             .addslashes(strtolower($Name))."'",
00085                                             "NumberFound");
00086                     }
00087 
00088                     if ($Count > 0)
00089                     {
00090                         # set error code for duplicate class name
00091                         $this->ErrorStatus = Classification::CLASSSTAT_DUPLICATENAME;
00092                     }
00093                     else
00094                     {
00095                         # add class to database
00096                         $ParentId = intval($ParentId);
00097                         if ($ParentId == -1)
00098                         {
00099                             $NewName = $Name;
00100                             $NewDepth = 0;
00101                         }
00102                         else
00103                         {
00104                             $DB->Query("SELECT ClassificationName, Depth"
00105                                     ." FROM Classifications"
00106                                     ." WHERE ClassificationId = ".$ParentId);
00107                             $ParentInfo = $DB->FetchRow();
00108                             $NewName = $ParentInfo["ClassificationName"]." -- ".$Name;
00109                             $NewDepth = $ParentInfo["Depth"] + 1;
00110                         }
00111                         $DB->Query("INSERT INTO Classifications"
00112                                 ." (FieldId, ParentId, SegmentName, ResourceCount,"
00113                                         ." Depth, ClassificationName) VALUES"
00114                                 ." (".intval($FieldId).", ".$ParentId.","
00115                                         ." '".addslashes($Name)."', 0, "
00116                                         .$NewDepth.", '".addslashes($NewName)."')");
00117 
00118                         # retrieve ID of new class
00119                         $this->Id = $DB->LastInsertId("Classifications");
00120                     }
00121                 }
00122             }
00123             else
00124             {
00125                 # parse classification name into separate segments
00126                 $Segments = preg_split("/--/", $Name);
00127     
00128                 # start out with top as parent
00129                 $ParentId = -1;
00130     
00131                 # for each segment
00132                 $CurrentDepth = -1;
00133                 $CurrentFullName = "";
00134                 foreach ($Segments as $Segment)
00135                 {
00136                     # track segment depth and full classification name for use in adding new entries
00137                     $Segment = trim($Segment);
00138                     $CurrentDepth++;
00139                     $CurrentFullName .= (($CurrentFullName == "") ? "" : " -- ").$Segment;
00140     
00141                     # if we have added classifications
00142                     $Segment = addslashes($Segment);
00143                     if ($this->SegmentsCreated)
00144                     {
00145                         # we know that current segment will not be found
00146                         $ClassId = NULL;
00147                     }
00148                     else
00149                     {
00150                         # look up classification with current parent and segment name
00151                         if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
00152                         {
00153                             if ($ParentId == -1)
00154                             {
00155                                 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
00156                                         "SELECT ClassificationId FROM Classifications"
00157                                         ." WHERE ParentId = -1"
00158                                         ." AND SegmentName = '".addslashes($Segment)."'"
00159                                         ." AND FieldId = ".intval($FieldId),
00160                                         "ClassificationId");
00161                             }
00162                             else
00163                             {
00164                                 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
00165                                         "SELECT ClassificationId FROM Classifications "
00166                                         ."WHERE ParentId = ".intval($ParentId)
00167                                         ." AND SegmentName = '".addslashes($Segment)."'",
00168                                         "ClassificationId");
00169                             }
00170                         }
00171                         $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
00172                     }
00173     
00174                     # if classification not found
00175                     if ($ClassId === NULL)
00176                     {
00177                         # add new classification
00178                         $DB->Query("INSERT INTO Classifications "
00179                                  ."(FieldId, ParentId, SegmentName,"
00180                                         ." ClassificationName, Depth, ResourceCount) "
00181                                  ."VALUES (".intval($FieldId).", "
00182                                     .intval($ParentId).", "
00183                                     ."'".addslashes($Segment)."', "
00184                                     ."'".addslashes($CurrentFullName)."', "
00185                                     .intval($CurrentDepth).", 0)");
00186                         $ClassId = $DB->LastInsertId("Classifications");
00187                         $IdCache[$FieldId][$ParentId][$Segment] = $ClassId;
00188     
00189                         # track total number of new classification segments created
00190                         $this->SegmentsCreated++;
00191                     }
00192     
00193                     # set parent to created or found class
00194                     $PreviousParentId = $ParentId;
00195                     $ParentId = $ClassId;
00196                 }
00197     
00198                 # our class ID is the one that was last found
00199                 $this->Id = $ClassId;
00200             }
00201         }
00202         else
00203         {
00204             # our class ID is the one that was supplied by caller
00205             $this->Id = intval($ClassId);
00206         }
00207 
00208         # if no error encountered
00209         if ($this->ErrorStatus == Classification::CLASSSTAT_OK)
00210         {
00211             # load in attributes from database
00212             $DB->Query("SELECT * FROM Classifications"
00213                        ." WHERE ClassificationId = ".intval($this->Id));
00214             $this->DBFields = $DB->NumRowsSelected()>0 ? $DB->FetchRow() : NULL ;
00215             
00216             # set error status if class info not loaded
00217             if ($this->DBFields === NULL ||
00218                 $this->DBFields["ClassificationId"] != $this->Id)
00219             {
00220                 $this->ErrorStatus = Classification::CLASSSTAT_INVALIDID;
00221             }
00222         }
00223     }
00224     
00229     function Status() {  return $this->ErrorStatus;  }
00230 
00235     function Id()            {  return $this->Id;  }
00236 
00241     function FullName()      {  return stripslashes($this->DBFields["ClassificationName"]);  }
00242 
00247     function Name()          {  return $this->FullName();  }
00248 
00253     function VariantName()   {  return NULL;  }
00254 
00259     function Depth()         {  return $this->DBFields["Depth"];  }
00260 
00266     function ResourceCount() {  return $this->DBFields["ResourceCount"];  }
00267 
00272     function SegmentsCreated() { return $this->SegmentsCreated; }
00273 
00278     function ParentId()      {  return $this->DBFields["ParentId"];  }
00279 
00285     function SegmentName($NewValue = DB_NOVALUE) {  
00286             return stripslashes($this->UpdateValue("SegmentName", $NewValue));  }
00287 
00295     function LinkString($NewValue = DB_NOVALUE) {  
00296             return stripslashes($this->UpdateValue("LinkString", $NewValue));  }
00297 
00304     function QualifierId($NewValue = DB_NOVALUE) {  
00305             return $this->UpdateValue("QualifierId", $NewValue);  }
00306 
00312     function FieldId($NewValue = DB_NOVALUE) {  
00313             return $this->UpdateValue("FieldId", $NewValue);  }
00314 
00321     function Qualifier($NewValue = DB_NOVALUE)
00322     {
00323         # if new qualifier supplied
00324         if ($NewValue !== DB_NOVALUE) 
00325         {
00326             # set new qualifier ID
00327             $this->QualifierId($NewValue->Id());
00328 
00329             # use new qualifier for return value
00330             $Qualifier = $NewValue;
00331         }
00332         else
00333         {
00334             # if qualifier is available
00335             if ($this->QualifierId() !== NULL)
00336             {   
00337                 # create qualifier object using stored ID
00338                 $Qualifier = new Qualifier($this->QualifierId());
00339             }
00340             else
00341             {
00342                 # return NULL to indicate no qualifier
00343                 $Qualifier = NULL;
00344             }
00345         }
00346 
00347         # return qualifier to caller
00348         return $Qualifier;
00349     }
00350 
00356     function RecalcDepthAndFullName()
00357     {
00358         $DB = $this->DB;
00359 
00360         # start with full classification name set to our segment name
00361         $FullClassName = $this->DBFields["SegmentName"];
00362 
00363         # assume to begin with that we're at the top of the hierarchy
00364         $Depth = 0;
00365 
00366         # while parent available
00367         $ParentId = $this->DBFields["ParentId"];
00368         while ($ParentId != -1)
00369         {
00370             # retrieve classification information
00371             $DB->Query("SELECT SegmentName, ParentId "
00372                     ."FROM Classifications "
00373                     ."WHERE ClassificationId=".$ParentId);
00374             $Record = $DB->FetchRow();
00375 
00376             # prepend segment name to full classification name
00377             $FullClassName = stripslashes($Record["SegmentName"])
00378                     ." -- ".$FullClassName;
00379 
00380             # increment depth value
00381             $Depth++;
00382 
00383             # move to parent of current classification
00384             $ParentId = $Record["ParentId"];
00385         }
00386 
00387         # for each child
00388         $DB->Query("SELECT ClassificationId "
00389                 ."FROM Classifications "
00390                 ."WHERE ParentId=".intval($this->Id));
00391         while ($Record = $DB->FetchRow())
00392         {
00393             # perform depth and name recalc
00394             $Child = new Classification($Record["ClassificationId"]);
00395             $Child->RecalcDepthAndFullName();
00396         }
00397 
00398         # save new depth and full classification name
00399         $DB->Query("UPDATE Classifications SET "
00400                 ."Depth=".intval($Depth).", "
00401                 ."ClassificationName='".addslashes($FullClassName)."' "
00402                 ."WHERE ClassificationId=".intval($this->Id));
00403         $this->DBFields["ClassificationName"] = $FullClassName;
00404         $this->DBFields["Depth"] = $Depth;
00405     }
00406 
00414     function RecalcResourceCount($IdsToSkip = NULL)
00415     {
00416         $IdsUpdated = array();
00417         
00418         # if we don't have a skip list or we aren't in the skip list
00419         if (!$IdsToSkip || !in_array($this->Id, $IdsToSkip))
00420         {
00421             # retrieve new count of resources directly associated with class
00422             $this->DB->Query("SELECT COUNT(*) AS ResourceCount"
00423                     ." FROM ResourceClassInts, Resources"
00424                     ." WHERE ClassificationId=".intval($this->Id)
00425                     ." AND ResourceClassInts.ResourceId = Resources.ResourceId"
00426                     ." AND ReleaseFlag = 1");
00427             $Record = $this->DB->FetchRow();
00428             $ResourceCount = $Record["ResourceCount"];
00429 
00430             # add on resources associated with all children
00431             $ResourceCount += $this->DB->Query(
00432                     "SELECT SUM(ResourceCount) AS ResourceCountTotal "
00433                         ."FROM Classifications "
00434                         ."WHERE ParentId = ".intval($this->Id),
00435                     "ResourceCountTotal");
00436 
00437             # save new count to database
00438             $this->DB->Query("UPDATE Classifications SET "
00439                     ."ResourceCount=".$ResourceCount." "
00440                     ."WHERE ClassificationId=".intval($this->Id));
00441 
00442             # save new count to our local cache
00443             $this->DBFields["ResourceCount"] = $ResourceCount;
00444 
00445             # add our ID to list of IDs that have been recalculated
00446             $IdsUpdated[] = $this->Id;
00447         }
00448 
00449         # update resource count for our parent (if any)
00450         if (($this->DBFields["ParentId"] != -1)
00451             && (!$IdsToSkip || !in_array($this->DBFields["ParentId"], $IdsToSkip)) )
00452         {
00453             $Class = new Classification($this->DBFields["ParentId"]);
00454             if ($Class->Status() == Classification::CLASSSTAT_OK)
00455             {
00456                 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
00457             }
00458         }
00459 
00460         # return list of IDs of updated classifications to caller
00461         return $IdsUpdated;
00462     }
00463 
00468     function ChildCount()
00469     {
00470         # return count of classifications that have this one as parent
00471         return $this->DB->Query("SELECT COUNT(*) AS ClassCount "
00472                     ."FROM Classifications "
00473                     ."WHERE ParentId=".intval($this->Id),
00474                 "ClassCount");
00475     }
00476 
00482     # this also returns grandchildren, great grandchildren, etc.
00483     function ChildList()
00484     {
00485         $ChildList = array();
00486         
00487         $this->DB->Query("SELECT ClassificationId  "
00488                     ."FROM Classifications "
00489                     ."WHERE ParentId=".intval($this->Id));
00490 
00491          while ($Entry = $this->DB->FetchRow())
00492          {
00493             $ChildList[] = $Entry["ClassificationId"];
00494             $Child = new Classification($Entry["ClassificationId"]);
00495             if($Child->ChildCount() > 0)
00496             {
00497                 $GrandChildList = $Child->ChildList();
00498                 $ChildList = array_merge($GrandChildList, $ChildList);
00499             }
00500          }
00501          return $ChildList;
00502     }
00503     
00510     function Delete($DeleteParents = FALSE, 
00511             $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
00512     {
00513         $DB = $this->DB;
00514 
00515         # if no resources or okay to delete with resources
00516         #         and no children or okay to delete with children
00517         if (($DeleteIfHasResources || ($this->ResourceCount() == 0))
00518                 && ($DeleteIfHasChildren || ($this->ChildCount() == 0)))
00519         {
00520             $ParentId = $this->DBFields["ParentId"];
00521 
00522             if ($DeleteIfHasResources)
00523             {
00524                 $DB->Query("DELETE FROM ResourceClassInts "
00525                         ."WHERE ClassificationId=".intval($this->Id));
00526                 $this->RecalcResourceCount();        
00527             }
00528             # delete this classification
00529             $DB->Query("DELETE FROM Classifications "
00530                     ."WHERE ClassificationId=".intval($this->Id));
00531 
00532             # delete parent classification (if requested)
00533             if (($DeleteParents) && ($this->DBFields["ParentId"] != -1))
00534             {
00535                 $Parent = new Classification($this->DBFields["ParentId"]);
00536                 $Parent->Delete(
00537                         TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
00538             }
00539         }
00540     }
00541 
00542 
00543     # ---- PRIVATE INTERFACE -------------------------------------------------
00544 
00545     private $DB;
00546     private $DBFields;
00547     private $Id;
00548     private $ErrorStatus;
00549     private $SegmentsCreated;
00550 
00551     # convenience function to supply parameters to Database->UpdateValue()
00552     private function UpdateValue($FieldName, $NewValue)
00553     {
00554         return $this->DB->UpdateValue("Classifications", $FieldName, $NewValue,
00555                                "ClassificationId = ".intval($this->Id),
00556                                $this->DBFields, TRUE);
00557     }
00558 }
00559 
00560 
00561 ?>
CWIS logo doxygen
Copyright 2009 Internet Scout