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/
15 # ---- PUBLIC INTERFACE --------------------------------------------------
42 function Classification($ClassId, $Name = NULL, $FieldId = NULL, $ParentId = NULL)
46 # assume everything will turn out okay
47 $this->ErrorStatus = self::CLASSSTAT_OK;
49 # create DB handle for our use
53 # if class ID not given (indicating class must be created)
54 if ($ClassId === NULL)
56 # if parent class supplied
57 if ($ParentId !== NULL)
59 # if parent ID was invalid
61 && ($DB->Query(
"SELECT COUNT(*) AS NumberFound"
62 .
" FROM Classifications"
63 .
" WHERE ClassificationId = ".intval($ParentId),
66 # set error code for bad parent ID
67 $this->ErrorStatus = self::CLASSSTAT_INVALIDPARENTID;
71 # if name already exists
73 if ($FieldId === NULL)
75 # If we know what field we're trying to add a classifcation for,
76 # Check just within that field
77 $Count = $DB->Query(
"SELECT COUNT(*) AS NumberFound FROM Classifications"
78 .
" WHERE ParentId = ".intval($ParentId)
79 .
" AND LOWER(SegmentName) = '"
80 .addslashes(strtolower($Name)).
"'",
85 # Otherwise, check all classifications for all fields
86 $Count = $DB->Query(
"SELECT COUNT(*) AS NumberFound FROM Classifications"
87 .
" WHERE ParentId = ".intval($ParentId)
88 .
" AND FieldId = ".intval($FieldId)
89 .
" AND LOWER(SegmentName) = '"
90 .addslashes(strtolower($Name)).
"'",
96 # set error code for duplicate class name
97 $this->ErrorStatus = self::CLASSSTAT_DUPLICATENAME;
101 # add class to database
102 $ParentId = intval($ParentId);
110 $DB->Query(
"SELECT ClassificationName, Depth"
111 .
" FROM Classifications"
112 .
" WHERE ClassificationId = ".$ParentId);
113 $ParentInfo = $DB->FetchRow();
114 $NewName = $ParentInfo[
"ClassificationName"].
" -- ".$Name;
115 $NewDepth = $ParentInfo[
"Depth"] + 1;
117 $DB->Query(
"INSERT INTO Classifications"
118 .
" (FieldId, ParentId, SegmentName, ResourceCount,"
119 .
" Depth, ClassificationName) VALUES"
120 .
" (".intval($FieldId).
", ".$ParentId.
","
121 .
" '".addslashes($Name).
"', 0, "
122 .$NewDepth.
", '".addslashes($NewName).
"')");
124 # retrieve ID of new class
125 $this->
Id = $DB->LastInsertId();
131 # parse classification name into separate segments
132 $Segments = preg_split(
"/--/", $Name);
134 # start out with top as parent
139 $CurrentFullName =
"";
140 foreach ($Segments as $Segment)
142 # track segment depth and full classification name for use in adding new entries
143 $Segment = trim($Segment);
145 $CurrentFullName .= (($CurrentFullName ==
"") ?
"" :
" -- ").$Segment;
147 # if we have added classifications
148 $Segment = addslashes($Segment);
151 # we know that current segment will not be found
156 # look up classification with current parent and segment name
157 if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
161 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
162 "SELECT ClassificationId FROM Classifications"
163 .
" WHERE ParentId = -1"
164 .
" AND SegmentName = '".addslashes($Segment).
"'"
165 .
" AND FieldId = ".intval($FieldId),
170 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
171 "SELECT ClassificationId FROM Classifications "
172 .
"WHERE ParentId = ".intval($ParentId)
173 .
" AND SegmentName = '".addslashes($Segment).
"'",
177 $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
180 # if classification not found
181 if ($ClassId === NULL)
183 # add new classification
184 $DB->Query(
"INSERT INTO Classifications "
185 .
"(FieldId, ParentId, SegmentName,"
186 .
" ClassificationName, Depth, ResourceCount) "
187 .
"VALUES (".intval($FieldId).
", "
188 .intval($ParentId).
", "
189 .
"'".addslashes($Segment).
"', "
190 .
"'".addslashes($CurrentFullName).
"', "
191 .intval($CurrentDepth).
", 0)");
192 $ClassId = $DB->LastInsertId();
193 $IdCache[$FieldId][$ParentId][$Segment] = $ClassId;
195 # track total number of new classification segments created
199 # set parent to created or found class
200 $PreviousParentId = $ParentId;
201 $ParentId = $ClassId;
204 # our class ID is the one that was last found
205 $this->
Id = $ClassId;
210 # our class ID is the one that was supplied by caller
211 $this->
Id = intval($ClassId);
214 # if no error encountered
215 if ($this->ErrorStatus == self::CLASSSTAT_OK)
217 # load in attributes from database
218 $DB->Query(
"SELECT * FROM Classifications"
219 .
" WHERE ClassificationId = ".intval($this->
Id));
220 $this->DBFields = $DB->NumRowsSelected()>0 ? $DB->FetchRow() : NULL ;
222 # set error status if class info not loaded
223 if ($this->DBFields === NULL ||
224 $this->DBFields[
"ClassificationId"] != $this->
Id)
226 $this->ErrorStatus = self::CLASSSTAT_INVALIDID;
235 function Status() {
return $this->ErrorStatus; }
241 function Id() {
return $this->Id; }
249 return $this->DBFields[
"ClassificationName"];
268 function Depth() {
return $this->DBFields[
"Depth"]; }
295 function ParentId() {
return $this->DBFields[
"ParentId"]; }
303 return $this->UpdateValue(
"SegmentName", $NewValue); }
313 return $this->UpdateValue(
"LinkString", $NewValue); }
322 return $this->UpdateValue(
"QualifierId", $NewValue); }
330 return $this->UpdateValue(
"FieldId", $NewValue); }
340 # if new qualifier supplied
343 # set new qualifier ID
346 # use new qualifier for return value
347 $Qualifier = $NewValue;
351 # if qualifier is available
354 # create qualifier object using stored ID
359 # return NULL to indicate no qualifier
364 # return qualifier to caller
377 # start with full classification name set to our segment name
378 $FullClassName = $this->DBFields[
"SegmentName"];
380 # assume to begin with that we're at the top of the hierarchy
383 # while parent available
384 $ParentId = $this->DBFields[
"ParentId"];
385 while ($ParentId != -1)
387 # retrieve classification information
388 $DB->Query(
"SELECT SegmentName, ParentId "
389 .
"FROM Classifications "
390 .
"WHERE ClassificationId=".$ParentId);
391 $Record = $DB->FetchRow();
393 # prepend segment name to full classification name
394 $FullClassName = $Record[
"SegmentName"].
" -- ".$FullClassName;
396 # increment depth value
399 # move to parent of current classification
400 $ParentId = $Record[
"ParentId"];
404 $DB->Query(
"SELECT ClassificationId "
405 .
"FROM Classifications "
406 .
"WHERE ParentId=".intval($this->
Id));
407 while ($Record = $DB->FetchRow())
409 # perform depth and name recalc
411 $Child->RecalcDepthAndFullName();
414 # save new depth and full classification name
415 $DB->Query(
"UPDATE Classifications SET "
416 .
"Depth=".intval($Depth).
", "
417 .
"ClassificationName='".addslashes($FullClassName).
"' "
418 .
"WHERE ClassificationId=".intval($this->
Id));
419 $this->DBFields[
"ClassificationName"] = $FullClassName;
420 $this->DBFields[
"Depth"] = $Depth;
432 $IdsUpdated = array();
434 # if we don't have a skip list or we aren't in the skip list
435 if (!$IdsToSkip || !in_array($this->
Id, $IdsToSkip))
437 # retrieve new count of resources directly associated with class
438 $this->DB->Query(
"SELECT COUNT(*) AS ResourceCount"
439 .
" FROM ResourceClassInts, Resources"
440 .
" WHERE ClassificationId=".intval($this->
Id)
441 .
" AND ResourceClassInts.ResourceId = Resources.ResourceId"
442 .
" AND Resources.ResourceId > 0"
443 .
" AND ReleaseFlag = 1");
444 $Record = $this->DB->FetchRow();
445 $ResourceCount = $Record[
"ResourceCount"];
447 # add on resources associated with all children
448 $ResourceCount += $this->DB->Query(
449 "SELECT SUM(ResourceCount) AS ResourceCountTotal "
450 .
"FROM Classifications "
451 .
"WHERE ParentId = ".intval($this->
Id),
452 "ResourceCountTotal");
454 # save new count to database
455 $this->DB->Query(
"UPDATE Classifications SET "
456 .
"ResourceCount=".$ResourceCount.
" "
457 .
"WHERE ClassificationId=".intval($this->
Id));
459 # save new count to our local cache
460 $this->DBFields[
"ResourceCount"] = $ResourceCount;
462 # add our ID to list of IDs that have been recalculated
463 $IdsUpdated[] = $this->Id;
466 # update resource count for our parent (if any)
467 if (($this->DBFields[
"ParentId"] != -1)
468 && (!$IdsToSkip || !in_array($this->DBFields[
"ParentId"], $IdsToSkip)) )
471 if ($Class->Status() == self::CLASSSTAT_OK)
473 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
477 # retrieve new count of all resources directly associated with class
478 $FullCount = $this->DB->Query(
"
479 SELECT COUNT(*) AS ResourceCount
480 FROM ResourceClassInts I, Resources R
481 WHERE I.ClassificationId = '".intval($this->
Id).
"'
483 AND I.ResourceId = R.ResourceId",
486 # add on resources associated with all children
487 $FullCount += $this->DB->Query(
"
488 SELECT SUM(ResourceCount) AS ResourceCountTotal
490 WHERE ParentId = '".intval($this->
Id).
"'",
491 "ResourceCountTotal");
493 # save new count to database
495 UPDATE Classifications
496 SET FullResourceCount = '".intval($FullCount).
"'
497 WHERE ClassificationId = '".intval($this->
Id).
"'");
499 # save new count to our local cache
500 $this->DBFields[
"FullResourceCount"] = $FullCount;
502 # return list of IDs of updated classifications to caller
512 # return count of classifications that have this one as parent
513 return $this->DB->Query(
"SELECT COUNT(*) AS ClassCount "
514 .
"FROM Classifications "
515 .
"WHERE ParentId=".intval($this->
Id),
526 $ChildList = array();
528 $this->DB->Query(
"SELECT ClassificationId "
529 .
"FROM Classifications "
530 .
"WHERE ParentId=".intval($this->
Id));
532 while ($Entry = $this->DB->FetchRow())
534 $ChildList[] = $Entry[
"ClassificationId"];
536 if($Child->ChildCount() > 0)
538 $GrandChildList = $Child->ChildList();
539 $ChildList = array_merge($GrandChildList, $ChildList);
558 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
562 # if no resources or okay to delete with resources
563 # and no children or okay to delete with children
565 && ($DeleteIfHasChildren || ($this->
ChildCount() == 0)))
567 $ParentId = $this->DBFields[
"ParentId"];
569 if ($DeleteIfHasResources)
571 $DB->Query(
"DELETE FROM ResourceClassInts "
572 .
"WHERE ClassificationId=".intval($this->
Id));
575 # delete this classification
576 $DB->Query(
"DELETE FROM Classifications "
577 .
"WHERE ClassificationId=".intval($this->
Id));
579 # delete parent classification (if requested)
580 if (($DeleteParents) && ($this->DBFields[
"ParentId"] != -1))
584 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
590 # ---- PRIVATE INTERFACE -------------------------------------------------
595 private $ErrorStatus;
596 private $SegmentsCreated;
605 private function UpdateValue($FieldName, $NewValue)
607 return $this->DB->UpdateValue(
"Classifications", $FieldName, $NewValue,
608 "ClassificationId = ".intval($this->
Id),
609 $this->DBFields, TRUE);
LinkString($NewValue=DB_NOVALUE)
Get or set the stored link string for the Classification.
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.
Classification($ClassId, $Name=NULL, $FieldId=NULL, $ParentId=NULL)
Class constructor.
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.
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.