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 342 # create qualifier object using stored ID 347 # return NULL to indicate no qualifier 352 # return qualifier to caller 363 # start with full classification name set to our segment name 364 $FullClassName = $this->ValueCache[
"SegmentName"];
366 # assume to begin with that we're at the top of the hierarchy 369 # while parent available 370 $ParentId = $this->ValueCache[
"ParentId"];
371 while ($ParentId != self::NOPARENT)
373 # retrieve classification information 374 $this->DB->Query(
"SELECT SegmentName, ParentId " 375 .
"FROM Classifications " 376 .
"WHERE ClassificationId=".$ParentId);
377 $Record = $this->DB->FetchRow();
379 # prepend segment name to full classification name 380 $FullClassName = $Record[
"SegmentName"].
" -- ".$FullClassName;
382 # increment depth value 385 # move to parent of current classification 386 $ParentId = $Record[
"ParentId"];
390 $this->DB->Query(
"SELECT ClassificationId FROM Classifications" 391 .
" WHERE ParentId = ".intval($this->
Id));
392 while ($Record = $this->DB->FetchRow())
394 # perform depth and name recalc 396 $Child->RecalcDepthAndFullName();
399 # save new depth and full classification name 401 $this->
UpdateValue(
"ClassificationName", $FullClassName);
409 $this->DB->Query(
"UPDATE Classifications SET LastAssigned=NOW() " 410 .
"WHERE ClassificationId=".intval($this->
Id));
422 $IdsUpdated = array();
424 # if we don't have a skip list or we aren't in the skip list 425 if (!$IdsToSkip || !in_array($this->
Id, $IdsToSkip))
427 # retrieve new count of resources directly associated with class 428 $this->DB->Query(
"SELECT R.ResourceId AS ResourceId, SchemaId" 429 .
" FROM ResourceClassInts RCI, Resources R" 430 .
" WHERE RCI.ClassificationId=".intval($this->
Id)
431 .
" AND RCI.ResourceId = R.ResourceId" 432 .
" AND R.ResourceId > 0");
434 # pull out resources and bin them by schema 435 $Resources = array();
436 while ($Row = $this->DB->FetchRow())
438 $Resources[$Row[
"SchemaId"]][]= $Row[
"ResourceId"];
441 # filter out non-viewable resources from each schema 442 foreach ($Resources as $SchemaId => $ResourceIds)
445 $Resources[$SchemaId] = $RFactory->FilterNonViewableResources(
449 # total up resources from each schema 451 foreach ($Resources as $SchemaId => $ResourceIds)
453 $ResourceCount += count($ResourceIds);
456 # add on resources associated with all children 457 $ResourceCount += $this->DB->Query(
458 "SELECT SUM(ResourceCount) AS ResourceCountTotal " 459 .
"FROM Classifications " 460 .
"WHERE ParentId = ".intval($this->
Id),
461 "ResourceCountTotal");
464 $this->
UpdateValue(
"ResourceCount", $ResourceCount);
466 # add our ID to list of IDs that have been recalculated 470 # update resource count for our parent (if any) 471 if (($this->ValueCache[
"ParentId"] != self::NOPARENT)
472 && (!$IdsToSkip || !in_array($this->ValueCache[
"ParentId"], $IdsToSkip)) )
475 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
478 # retrieve new count of all resources directly associated with class 479 $FullCount = $this->DB->Query(
"SELECT COUNT(*) AS ResourceCount" 480 .
" FROM ResourceClassInts I, Resources R" 481 .
" WHERE I.ClassificationId = ".intval($this->
Id)
482 .
" AND R.ResourceId > 0" 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" 489 .
" FROM Classifications" 490 .
" WHERE ParentId = ".intval($this->
Id),
491 "ResourceCountTotal");
493 # save new full count 494 $this->
UpdateValue(
"FullResourceCount", $ResourceCount);
496 # return list of IDs of updated classifications to caller 506 # return count of classifications that have this one as parent 507 return $this->DB->Query(
"SELECT COUNT(*) AS ClassCount " 508 .
"FROM Classifications " 509 .
"WHERE ParentId=".intval($this->
Id),
520 $ChildList = array();
522 $this->DB->Query(
"SELECT ClassificationId " 523 .
"FROM Classifications " 524 .
"WHERE ParentId=".intval($this->
Id));
526 while ($Entry = $this->DB->FetchRow())
528 $ChildList[] = $Entry[
"ClassificationId"];
530 if($Child->ChildCount() > 0)
532 $GrandChildList = $Child->ChildList();
533 $ChildList = array_merge($GrandChildList, $ChildList);
536 return array_unique($ChildList);
552 public function Delete($DeleteParents = FALSE,
553 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
555 # if no resources or okay to delete with resources 556 # and no children or okay to delete with children 559 && ($DeleteIfHasChildren || ($this->
ChildCount() == 0)))
563 $this->DB->Query(
"DELETE FROM ResourceClassInts" 564 .
" WHERE ClassificationId = ".intval($this->
Id));
568 # delete this classification 572 # delete parent classification (if requested) 573 $ParentId = $this->ValueCache[
"ParentId"];
574 if (($DeleteParents) && ($ParentId != self::NOPARENT))
577 $DeleteCount += $Parent->Delete(
578 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
582 # return total number of classifications deleted to caller 587 # ---- PRIVATE INTERFACE ------------------------------------------------- 589 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.
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.