3 # FILE: Classification.php 5 # Part of the Collection Workflow Integration System (CWIS) 6 # Copyright 2002-2013 Edward Almasy and Internet Scout Research Group 7 # http://scout.wisc.edu/cwis/ 16 # ---- PUBLIC INTERFACE -------------------------------------------------- 43 public function __construct($ClassId, $Name = NULL, $FieldId = NULL, $ParentId = NULL)
47 # assume everything will turn out okay 48 $this->ErrorStatus = self::CLASSSTAT_OK;
50 # create DB handle for our use 54 # if class ID not given (indicating class must be created) 55 if ($ClassId === NULL)
59 throw new Exception(
"Cannot create a new 60 classification without specifying a field.");
62 # if parent class supplied 63 if ($ParentId !== NULL)
65 # if parent ID was invalid 67 && ($DB->Query(
"SELECT COUNT(*) AS NumberFound" 68 .
" FROM Classifications" 69 .
" WHERE ClassificationId = ".intval($ParentId),
72 # set error code for bad parent ID 73 $this->ErrorStatus = self::CLASSSTAT_INVALIDPARENTID;
77 # if name already exists 79 if ($FieldId === NULL)
81 # If we know what field we're trying to add a classifcation for, 82 # Check just within that field 83 $Count = $DB->Query(
"SELECT COUNT(*) AS NumberFound" 84 .
" FROM Classifications" 85 .
" WHERE ParentId = ".intval($ParentId)
86 .
" AND LOWER(SegmentName) = '" 87 .addslashes(strtolower($Name)).
"'",
92 # Otherwise, check all classifications for all fields 93 $Count = $DB->Query(
"SELECT COUNT(*) AS NumberFound" 94 .
" FROM Classifications" 95 .
" WHERE ParentId = ".intval($ParentId)
96 .
" AND FieldId = ".intval($FieldId)
97 .
" AND LOWER(SegmentName) = '" 98 .addslashes(strtolower($Name)).
"'",
104 # set error code for duplicate class name 105 $this->ErrorStatus = self::CLASSSTAT_DUPLICATENAME;
109 # add class to database 110 $ParentId = intval($ParentId);
118 $DB->Query(
"SELECT ClassificationName, Depth" 119 .
" FROM Classifications" 120 .
" WHERE ClassificationId = ".$ParentId);
121 $ParentInfo = $DB->FetchRow();
122 $NewName = $ParentInfo[
"ClassificationName"].
" -- ".$Name;
123 $NewDepth = $ParentInfo[
"Depth"] + 1;
125 $DB->Query(
"INSERT INTO Classifications" 126 .
" (FieldId, ParentId, SegmentName, ResourceCount," 127 .
" Depth, ClassificationName) VALUES" 128 .
" (".intval($FieldId).
", ".$ParentId.
"," 129 .
" '".addslashes($Name).
"', 0, " 130 .$NewDepth.
", '".addslashes($NewName).
"')");
132 # retrieve ID of new class 133 $this->
Id = $DB->LastInsertId();
139 # parse classification name into separate segments 140 $Segments = preg_split(
"/--/", $Name);
142 # start out with top as parent 147 $CurrentFullName =
"";
148 foreach ($Segments as $Segment)
150 # track segment depth and full classification name for use 151 # in adding new entries 152 $Segment = trim($Segment);
154 $CurrentFullName .= (($CurrentFullName ==
"") ?
"" :
" -- ").$Segment;
156 # if we have added classifications 157 $Segment = addslashes($Segment);
160 # we know that current segment will not be found 165 # look up classification with current parent and segment name 166 if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
170 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
171 "SELECT ClassificationId FROM Classifications" 172 .
" WHERE ParentId = -1" 173 .
" AND SegmentName = '".addslashes($Segment).
"'" 174 .
" AND FieldId = ".intval($FieldId),
179 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
180 "SELECT ClassificationId FROM Classifications " 181 .
"WHERE ParentId = ".intval($ParentId)
182 .
" AND SegmentName = '".addslashes($Segment).
"'",
186 $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
189 # if classification not found 190 if ($ClassId === NULL)
192 # add new classification 193 $DB->Query(
"INSERT INTO Classifications " 194 .
"(FieldId, ParentId, SegmentName," 195 .
" ClassificationName, Depth, ResourceCount) " 196 .
"VALUES (".intval($FieldId).
", " 197 .intval($ParentId).
", " 198 .
"'".addslashes($Segment).
"', " 199 .
"'".addslashes($CurrentFullName).
"', " 200 .intval($CurrentDepth).
", 0)");
201 $ClassId = $DB->LastInsertId();
202 $IdCache[$FieldId][$ParentId][$Segment] = $ClassId;
204 # track total number of new classification segments created 208 # set parent to created or found class 209 $ParentId = $ClassId;
212 # our class ID is the one that was last found 213 $this->
Id = $ClassId;
218 # our class ID is the one that was supplied by caller 219 $this->
Id = intval($ClassId);
222 # if no error encountered 223 if ($this->ErrorStatus == self::CLASSSTAT_OK)
225 # load in attributes from database 226 $DB->Query(
"SELECT * FROM Classifications" 227 .
" WHERE ClassificationId = ".intval($this->
Id));
228 $this->DBFields = $DB->NumRowsSelected()>0 ? $DB->FetchRow() : NULL ;
230 # set error status if class info not loaded 231 if ($this->DBFields === NULL ||
232 $this->DBFields[
"ClassificationId"] != $this->
Id)
234 $this->ErrorStatus = self::CLASSSTAT_INVALIDID;
245 return $this->ErrorStatus;
263 return $this->DBFields[
"ClassificationName"];
290 return $this->DBFields[
"Depth"];
300 return $this->DBFields[
"ResourceCount"];
311 return $this->DBFields[
"FullResourceCount"];
320 return $this->SegmentsCreated;
329 return $this->DBFields[
"ParentId"];
339 return $this->UpdateValue(
"SegmentName", $NewValue);
351 return $this->UpdateValue(
"LinkString", $NewValue);
362 return $this->UpdateValue(
"QualifierId", $NewValue);
372 return $this->UpdateValue(
"FieldId", $NewValue);
383 # if new qualifier supplied 386 # set new qualifier ID 389 # use new qualifier for return value 390 $Qualifier = $NewValue;
394 # if qualifier is available 397 # create qualifier object using stored ID 402 # return NULL to indicate no qualifier 407 # return qualifier to caller 420 # start with full classification name set to our segment name 421 $FullClassName = $this->DBFields[
"SegmentName"];
423 # assume to begin with that we're at the top of the hierarchy 426 # while parent available 427 $ParentId = $this->DBFields[
"ParentId"];
428 while ($ParentId != -1)
430 # retrieve classification information 431 $DB->Query(
"SELECT SegmentName, ParentId " 432 .
"FROM Classifications " 433 .
"WHERE ClassificationId=".$ParentId);
434 $Record = $DB->FetchRow();
436 # prepend segment name to full classification name 437 $FullClassName = $Record[
"SegmentName"].
" -- ".$FullClassName;
439 # increment depth value 442 # move to parent of current classification 443 $ParentId = $Record[
"ParentId"];
447 $DB->Query(
"SELECT ClassificationId " 448 .
"FROM Classifications " 449 .
"WHERE ParentId=".intval($this->
Id));
450 while ($Record = $DB->FetchRow())
452 # perform depth and name recalc 454 $Child->RecalcDepthAndFullName();
457 # save new depth and full classification name 458 $DB->Query(
"UPDATE Classifications SET " 459 .
"Depth=".intval($Depth).
", " 460 .
"ClassificationName='".addslashes($FullClassName).
"' " 461 .
"WHERE ClassificationId=".intval($this->
Id));
462 $this->DBFields[
"ClassificationName"] = $FullClassName;
463 $this->DBFields[
"Depth"] = $Depth;
471 $this->DB->Query(
"UPDATE Classifications SET LastAssigned=NOW() " 472 .
"WHERE ClassificationId=".intval($this->
Id));
484 $IdsUpdated = array();
486 # if we don't have a skip list or we aren't in the skip list 487 if (!$IdsToSkip || !in_array($this->
Id, $IdsToSkip))
489 # retrieve new count of resources directly associated with class 490 $this->DB->Query(
"SELECT COUNT(*) AS ResourceCount" 491 .
" FROM ResourceClassInts, Resources" 492 .
" WHERE ClassificationId=".intval($this->
Id)
493 .
" AND ResourceClassInts.ResourceId = Resources.ResourceId" 494 .
" AND Resources.ResourceId > 0" 495 .
" AND ReleaseFlag = 1");
496 $Record = $this->DB->FetchRow();
497 $ResourceCount = $Record[
"ResourceCount"];
499 # add on resources associated with all children 500 $ResourceCount += $this->DB->Query(
501 "SELECT SUM(ResourceCount) AS ResourceCountTotal " 502 .
"FROM Classifications " 503 .
"WHERE ParentId = ".intval($this->
Id),
504 "ResourceCountTotal");
506 # save new count to database 507 $this->DB->Query(
"UPDATE Classifications SET " 508 .
"ResourceCount=".$ResourceCount.
" " 509 .
"WHERE ClassificationId=".intval($this->
Id));
511 # save new count to our local cache 512 $this->DBFields[
"ResourceCount"] = $ResourceCount;
514 # add our ID to list of IDs that have been recalculated 515 $IdsUpdated[] = $this->Id;
518 # update resource count for our parent (if any) 519 if (($this->DBFields[
"ParentId"] != -1)
520 && (!$IdsToSkip || !in_array($this->DBFields[
"ParentId"], $IdsToSkip)) )
523 if ($Class->Status() == self::CLASSSTAT_OK)
525 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
529 # retrieve new count of all resources directly associated with class 530 $FullCount = $this->DB->Query(
" 531 SELECT COUNT(*) AS ResourceCount 532 FROM ResourceClassInts I, Resources R 533 WHERE I.ClassificationId = '".intval($this->
Id).
"' 535 AND I.ResourceId = R.ResourceId",
538 # add on resources associated with all children 539 $FullCount += $this->DB->Query(
" 540 SELECT SUM(ResourceCount) AS ResourceCountTotal 542 WHERE ParentId = '".intval($this->
Id).
"'",
543 "ResourceCountTotal");
545 # save new count to database 547 UPDATE Classifications 548 SET FullResourceCount = '".intval($FullCount).
"' 549 WHERE ClassificationId = '".intval($this->
Id).
"'");
551 # save new count to our local cache 552 $this->DBFields[
"FullResourceCount"] = $FullCount;
554 # return list of IDs of updated classifications to caller 564 # return count of classifications that have this one as parent 565 return $this->DB->Query(
"SELECT COUNT(*) AS ClassCount " 566 .
"FROM Classifications " 567 .
"WHERE ParentId=".intval($this->
Id),
578 $ChildList = array();
580 $this->DB->Query(
"SELECT ClassificationId " 581 .
"FROM Classifications " 582 .
"WHERE ParentId=".intval($this->
Id));
584 while ($Entry = $this->DB->FetchRow())
586 $ChildList[] = $Entry[
"ClassificationId"];
588 if($Child->ChildCount() > 0)
590 $GrandChildList = $Child->ChildList();
591 $ChildList = array_merge($GrandChildList, $ChildList);
594 return array_unique($ChildList);
609 public function Delete($DeleteParents = FALSE,
610 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
614 # if no resources or okay to delete with resources 615 # and no children or okay to delete with children 617 && ($DeleteIfHasChildren || ($this->
ChildCount() == 0)))
619 if ($DeleteIfHasResources)
621 $DB->Query(
"DELETE FROM ResourceClassInts " 622 .
"WHERE ClassificationId=".intval($this->
Id));
625 # delete this classification 626 $DB->Query(
"DELETE FROM Classifications " 627 .
"WHERE ClassificationId=".intval($this->
Id));
629 # delete parent classification (if requested) 630 $ParentId = $this->DBFields[
"ParentId"];
631 if (($DeleteParents) && ($ParentId != -1))
635 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
641 # ---- PRIVATE INTERFACE ------------------------------------------------- 646 private $ErrorStatus;
647 private $SegmentsCreated;
656 private function UpdateValue($FieldName, $NewValue)
658 return $this->DB->UpdateValue(
"Classifications", $FieldName, $NewValue,
659 "ClassificationId = ".intval($this->
Id),
660 $this->DBFields, TRUE);
LinkString($NewValue=DB_NOVALUE)
Get or set the stored link string for the Classification.
__construct($ClassId, $Name=NULL, $FieldId=NULL, $ParentId=NULL)
Class constructor.
const CLASSSTAT_INVALIDPARENTID
Status code indicating an invalid parent classification ID was specified.
FullName()
Get full classification name (all segments).
FullResourceCount()
Get number of all resources (minus temporary ones) having this classification assigned to them...
SQL database abstraction object with smart query caching.
const CLASSSTAT_INVALIDID
Status code indicating an invalid classification ID was specified.
FieldId($NewValue=DB_NOVALUE)
Get or set the ID of the MetadataField for the Classification.
VariantName()
Get variant name of classification, if any.
Qualifier($NewValue=DB_NOVALUE)
Get or set the Qualifier associated with the Classification.
ChildCount()
Get number of classifications that have this Classification as their direct parent.
RecalcResourceCount($IdsToSkip=NULL)
Recalculate number of resources assigned to class and any parent classes.
Name()
Get name of classification segment.
ParentId()
Get ID of parent Classification.
SegmentsCreated()
Get number of new segments (Classifications) generated when creating a new Classification with a full...
RecalcDepthAndFullName()
Rebuild classification full name and recalculate depth in hierarchy.
Status()
Returns success/failure code for last call (where applicable).
Depth()
Get depth of classification in hierarchy.
const CLASSSTAT_DUPLICATENAME
Status code indicating a duplicate classification name was specified.
ResourceCount()
Get number of released resources having this classification assigned to them.
Delete($DeleteParents=FALSE, $DeleteIfHasResources=FALSE, $DeleteIfHasChildren=FALSE)
Remove Classification (and accompanying associations) from database.
const CLASSSTAT_OK
Status code indicating operation completed successfully.
UpdateLastAssigned()
Update the LastAssigned timestamp for this classification.
Metadata type representing hierarchical ("Tree") controlled vocabulary values.
QualifierId($NewValue=DB_NOVALUE)
Get or set the Qualifier associated with the Classification by ID.
ChildList()
Get list of IDs of Classifications that have this class as an "ancestor" (parent, grandparent...
SegmentName($NewValue=DB_NOVALUE)
Get or set the segment name.
Id()
Get Classification ID.