3 # FILE: Classification.php 5 # Part of the Collection Workflow Integration System (CWIS) 6 # Copyright 2002-2016 Edward Almasy and Internet Scout Research Group 7 # http://scout.wisc.edu/cwis/ 15 # ---- PUBLIC INTERFACE -------------------------------------------------- 31 public static function Create($Name, $FieldId, $ParentId = NULL)
35 # initialize state for creation 36 self::$SegmentsCreated = 0;
38 # if parent class supplied 40 if ($ParentId !== NULL)
42 # error out if parent ID is invalid 43 if ($ParentId != self::NOPARENT)
45 if (
$DB->Query(
"SELECT COUNT(*) AS NumberFound" 46 .
" FROM Classifications" 47 .
" WHERE ClassificationId = ".intval($ParentId),
50 throw new InvalidArgumentException(
"Invalid parent ID" 51 .
" specified (".$ParentId.
").");
55 # error out if name already exists 57 $Count =
$DB->Query(
"SELECT COUNT(*) AS NumberFound" 58 .
" FROM Classifications" 59 .
" WHERE ParentId = ".intval($ParentId)
60 .
" AND FieldId = ".intval($FieldId)
61 .
" AND LOWER(SegmentName) = '" 62 .addslashes(strtolower($Name)).
"'",
66 throw new Exception(
"Duplicate name specified for" 67 .
" new classification (".$Name.
").");
70 # determine full name and depth for new classification 71 if ($ParentId == self::NOPARENT)
78 $DB->Query(
"SELECT ClassificationName, Depth" 79 .
" FROM Classifications" 80 .
" WHERE ClassificationId = ".intval($ParentId));
81 $ParentInfo =
$DB->FetchRow();
82 $NewName = $ParentInfo[
"ClassificationName"].
" -- ".$Name;
83 $NewDepth = $ParentInfo[
"Depth"] + 1;
86 # add classification to database 87 $InitialValues = array(
88 "FieldId" => $FieldId,
89 "ParentId" => $ParentId,
90 "SegmentName" => $Name,
93 "ClassificationName" => $NewName);
94 $NewItem = parent::CreateWithValues($InitialValues);
98 # parse classification name into separate segments 99 $Segments = preg_split(
"/--/", $Name);
101 # start out with top as parent 102 $ParentId = self::NOPARENT;
104 # start off assuming we won't create anything 109 $CurrentFullName =
"";
110 foreach ($Segments as $Segment)
112 # track segment depth and full classification name for use 113 # in adding new entries 114 $Segment = trim($Segment);
116 $CurrentFullName .= (($CurrentFullName ==
"") ?
"" :
" -- ").$Segment;
118 # if we have added classifications 119 $Segment = addslashes($Segment);
120 if (self::$SegmentsCreated)
122 # we know that current segment will not be found 127 # look up classification with current parent and segment name 128 if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
130 if ($ParentId == self::NOPARENT)
132 $IdCache[$FieldId][$ParentId][$Segment] =
$DB->Query(
133 "SELECT ClassificationId FROM Classifications" 134 .
" WHERE ParentId = ".self::NOPARENT
135 .
" AND SegmentName = '".addslashes($Segment).
"'" 136 .
" AND FieldId = ".intval($FieldId),
141 $IdCache[$FieldId][$ParentId][$Segment] =
$DB->Query(
142 "SELECT ClassificationId FROM Classifications " 143 .
"WHERE ParentId = ".intval($ParentId)
144 .
" AND SegmentName = '".addslashes($Segment).
"'",
148 $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
151 # if classification not found 152 if ($ClassId === NULL)
154 # add new classification 155 $InitialValues = array(
156 "FieldId" => $FieldId,
157 "ParentId" => $ParentId,
158 "SegmentName" => $Segment,
159 "ResourceCount" => 0,
160 "Depth" => $CurrentDepth,
161 "ClassificationName" => $CurrentFullName);
162 $NewItem = parent::CreateWithValues($InitialValues);
163 $ClassId = $NewItem->Id();
164 $IdCache[$FieldId][$ParentId][$Segment] = $ClassId;
166 # track total number of new classification segments created 167 self::$SegmentsCreated++;
170 # set parent to created or found class 171 $ParentId = $ClassId;
174 # if it wasn't actually necessary to create anything 175 if ($NewItem === NULL)
178 "Duplicate name specified for" 179 .
" new classification (".$Name.
").");
183 # return new classification to caller 184 return new self($NewItem->Id());
202 return $this->ValueCache[
"ClassificationName"];
215 throw new InvalidArgumentException(
"Illegal argument supplied.");
235 return $this->ValueCache[
"Depth"];
245 return $this->ValueCache[
"ResourceCount"];
256 return $this->ValueCache[
"FullResourceCount"];
265 return self::$SegmentsCreated;
274 return $this->ValueCache[
"ParentId"];
284 return $this->
UpdateValue(
"SegmentName", $NewValue);
296 return $this->
UpdateValue(
"LinkString", $NewValue);
307 return $this->
UpdateValue(
"QualifierId", $NewValue);
328 # if new qualifier supplied 331 # set new qualifier ID 334 # use new qualifier for return value 335 $Qualifier = $NewValue;
339 # if qualifier is available 343 # create qualifier object using stored ID 348 # return NULL to indicate no qualifier 353 # return qualifier to caller 364 # start with full classification name set to our segment name 365 $FullClassName = $this->ValueCache[
"SegmentName"];
367 # assume to begin with that we're at the top of the hierarchy 370 # while parent available 371 $ParentId = $this->ValueCache[
"ParentId"];
372 while ($ParentId != self::NOPARENT)
374 # retrieve classification information 375 $this->DB->Query(
"SELECT SegmentName, ParentId " 376 .
"FROM Classifications " 377 .
"WHERE ClassificationId=".$ParentId);
378 $Record = $this->DB->FetchRow();
380 # prepend segment name to full classification name 381 $FullClassName = $Record[
"SegmentName"].
" -- ".$FullClassName;
383 # increment depth value 386 # move to parent of current classification 387 $ParentId = $Record[
"ParentId"];
391 $this->DB->Query(
"SELECT ClassificationId FROM Classifications" 392 .
" WHERE ParentId = ".intval($this->
Id));
393 while ($Record = $this->DB->FetchRow())
395 # perform depth and name recalc 397 $Child->RecalcDepthAndFullName();
400 # save new depth and full classification name 402 $this->
UpdateValue(
"ClassificationName", $FullClassName);
410 $this->DB->Query(
"UPDATE Classifications SET LastAssigned=NOW() " 411 .
"WHERE ClassificationId=".intval($this->
Id));
423 $IdsUpdated = array();
425 # if we don't have a skip list or we aren't in the skip list 426 if (!$IdsToSkip || !in_array($this->
Id, $IdsToSkip))
428 # retrieve new count of resources directly associated with class 429 $this->DB->Query(
"SELECT R.ResourceId AS ResourceId, SchemaId" 430 .
" FROM ResourceClassInts RCI, Resources R" 431 .
" WHERE RCI.ClassificationId=".intval($this->
Id)
432 .
" AND RCI.ResourceId = R.ResourceId" 433 .
" AND R.ResourceId > 0");
435 # pull out resources and bin them by schema 436 $Resources = array();
437 while ($Row = $this->DB->FetchRow())
439 $Resources[$Row[
"SchemaId"]][]= $Row[
"ResourceId"];
442 # filter out non-viewable resources from each schema 443 foreach ($Resources as $SchemaId => $ResourceIds)
446 $Resources[$SchemaId] = $RFactory->FilterNonViewableResources(
450 # total up resources from each schema 452 foreach ($Resources as $SchemaId => $ResourceIds)
454 $ResourceCount += count($ResourceIds);
457 # add on resources associated with all children 458 $ResourceCount += $this->DB->Query(
459 "SELECT SUM(ResourceCount) AS ResourceCountTotal " 460 .
"FROM Classifications " 461 .
"WHERE ParentId = ".intval($this->
Id),
462 "ResourceCountTotal");
465 $this->
UpdateValue(
"ResourceCount", $ResourceCount);
467 # add our ID to list of IDs that have been recalculated 471 # update resource count for our parent (if any) 472 if (($this->ValueCache[
"ParentId"] != self::NOPARENT)
473 && (!$IdsToSkip || !in_array($this->ValueCache[
"ParentId"], $IdsToSkip)) )
476 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
479 # retrieve new count of all resources directly associated with class 480 $FullCount = $this->DB->Query(
"SELECT COUNT(*) AS ResourceCount" 481 .
" FROM ResourceClassInts I, Resources R" 482 .
" WHERE I.ClassificationId = ".intval($this->
Id)
483 .
" AND R.ResourceId > 0" 484 .
" AND I.ResourceId = R.ResourceId",
487 # add on resources associated with all children 488 $FullCount += $this->DB->Query(
489 "SELECT SUM(ResourceCount) AS ResourceCountTotal" 490 .
" FROM Classifications" 491 .
" WHERE ParentId = ".intval($this->
Id),
492 "ResourceCountTotal");
494 # save new full count 495 $this->
UpdateValue(
"FullResourceCount", $ResourceCount);
497 # return list of IDs of updated classifications to caller 507 # return count of classifications that have this one as parent 508 return $this->DB->Query(
"SELECT COUNT(*) AS ClassCount " 509 .
"FROM Classifications " 510 .
"WHERE ParentId=".intval($this->
Id),
521 $ChildList = array();
523 $this->DB->Query(
"SELECT ClassificationId " 524 .
"FROM Classifications " 525 .
"WHERE ParentId=".intval($this->
Id));
527 while ($Entry = $this->DB->FetchRow())
529 $ChildList[] = $Entry[
"ClassificationId"];
531 if($Child->ChildCount() > 0)
533 $GrandChildList = $Child->ChildList();
534 $ChildList = array_merge($GrandChildList, $ChildList);
537 return array_unique($ChildList);
553 public function Delete($DeleteParents = FALSE,
554 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
556 # if no resources or okay to delete with resources 557 # and no children or okay to delete with children 560 && ($DeleteIfHasChildren || ($this->
ChildCount() == 0)))
564 $this->DB->Query(
"DELETE FROM ResourceClassInts" 565 .
" WHERE ClassificationId = ".intval($this->
Id));
569 # delete this classification 573 # delete parent classification (if requested) 574 $ParentId = $this->ValueCache[
"ParentId"];
575 if (($DeleteParents) && ($ParentId != self::NOPARENT))
578 $DeleteCount += $Parent->Delete(
579 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
583 # return total number of classifications deleted to caller 588 # ---- PRIVATE INTERFACE ------------------------------------------------- 590 static private $SegmentsCreated;
LinkString($NewValue=DB_NOVALUE)
Get or set the stored link string for the Classification.
static GetAnonymousUser()
Get the anonymous user (i.e., the User object that exists when no user is logged in), useful when a permission check needs to know if something should be visible to the general public.
static SegmentsCreated()
Get number of new segments (Classifications) generated when creating a new Classification with a full...
FullName()
Get full classification name (all segments).
FullResourceCount()
Get number of all resources (minus temporary ones) having this classification assigned to them...
UpdateValue($ColumnName, $NewValue=DB_NOVALUE)
Convenience function to supply parameters to Database::UpdateValue().
SQL database abstraction object with smart query caching.
static Create($Name, $FieldId, $ParentId=NULL)
Add new classification to the hierarchy.
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.
const NOPARENT
Parent value for classifications with no parent.
ParentId()
Get ID of parent Classification.
RecalcDepthAndFullName()
Rebuild classification full name and recalculate depth in hierarchy.
Common base class for persistent items store in database.
Depth()
Get depth of classification in hierarchy.
Name($NewValue=DB_NOVALUE)
Get full classification name (all segments).
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.
UpdateLastAssigned()
Update the LastAssigned timestamp for this classification.
Metadata type representing hierarchical ("Tree") controlled vocabulary values.
static ItemExists($Id)
Check whether an item exists with the specified ID.
Factory for Resource objects.
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.