CWIS Developer Documentation

- Home
- Main Page
- Classes
- Files

- File List
- File Members

Classification.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: Classification.php
4 #
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/
8 #
9
13 class Classification {
14
15 # ---- PUBLIC INTERFACE --------------------------------------------------
16
18 const CLASSSTAT_OK = 0;
20 const CLASSSTAT_INVALIDID = 1;
22 const CLASSSTAT_INVALIDPARENTID = 2;
24 const CLASSSTAT_DUPLICATENAME = 3;
25
42 function Classification($ClassId, $Name = NULL, $FieldId = NULL, $ParentId = NULL)
43 {
44 static $IdCache;
45
46 # assume everything will turn out okay
47 $this->ErrorStatus = self::CLASSSTAT_OK;
48
49 # create DB handle for our use
50 $this->DB = new Database();
51 $DB = $this->DB;
52
53 # if class ID not given (indicating class must be created)
54 if ($ClassId === NULL)
55 {
56 # if parent class supplied
57 if ($ParentId !== NULL)
58 {
59 # if parent ID was invalid
60 if (($ParentId != -1)
61 && ($DB->Query("SELECT COUNT(*) AS NumberFound"
62 ." FROM Classifications"
63 ." WHERE ClassificationId = ".intval($ParentId),
64 "NumberFound") < 1))
65 {
66 # set error code for bad parent ID
67 $this->ErrorStatus = self::CLASSSTAT_INVALIDPARENTID;
68 }
69 else
70 {
71 # if name already exists
72 $Name = trim($Name);
73 if ($FieldId === NULL)
74 {
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))."'",
81 "NumberFound");
82 }
83 else
84 {
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))."'",
91 "NumberFound");
92 }
93
94 if ($Count > 0)
95 {
96 # set error code for duplicate class name
97 $this->ErrorStatus = self::CLASSSTAT_DUPLICATENAME;
98 }
99 else
100 {
101 # add class to database
102 $ParentId = intval($ParentId);
103 if ($ParentId == -1)
104 {
105 $NewName = $Name;
106 $NewDepth = 0;
107 }
108 else
109 {
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;
116 }
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)."')");
123
124 # retrieve ID of new class
125 $this->Id = $DB->LastInsertId();
126 }
127 }
128 }
129 else
130 {
131 # parse classification name into separate segments
132 $Segments = preg_split("/--/", $Name);
133
134 # start out with top as parent
135 $ParentId = -1;
136
137 # for each segment
138 $CurrentDepth = -1;
139 $CurrentFullName = "";
140 foreach ($Segments as $Segment)
141 {
142 # track segment depth and full classification name for use in adding new entries
143 $Segment = trim($Segment);
144 $CurrentDepth++;
145 $CurrentFullName .= (($CurrentFullName == "") ? "" : " -- ").$Segment;
146
147 # if we have added classifications
148 $Segment = addslashes($Segment);
149 if ($this->SegmentsCreated)
150 {
151 # we know that current segment will not be found
152 $ClassId = NULL;
153 }
154 else
155 {
156 # look up classification with current parent and segment name
157 if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
158 {
159 if ($ParentId == -1)
160 {
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),
166 "ClassificationId");
167 }
168 else
169 {
170 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
171 "SELECT ClassificationId FROM Classifications "
172 ."WHERE ParentId = ".intval($ParentId)
173 ." AND SegmentName = '".addslashes($Segment)."'",
174 "ClassificationId");
175 }
176 }
177 $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
178 }
179
180 # if classification not found
181 if ($ClassId === NULL)
182 {
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;
194
195 # track total number of new classification segments created
196 $this->SegmentsCreated++;
197 }
198
199 # set parent to created or found class
200 $PreviousParentId = $ParentId;
201 $ParentId = $ClassId;
202 }
203
204 # our class ID is the one that was last found
205 $this->Id = $ClassId;
206 }
207 }
208 else
209 {
210 # our class ID is the one that was supplied by caller
211 $this->Id = intval($ClassId);
212 }
213
214 # if no error encountered
215 if ($this->ErrorStatus == self::CLASSSTAT_OK)
216 {
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 ;
221
222 # set error status if class info not loaded
223 if ($this->DBFields === NULL ||
224 $this->DBFields["ClassificationId"] != $this->Id)
225 {
226 $this->ErrorStatus = self::CLASSSTAT_INVALIDID;
227 }
228 }
229 }
230
235 function Status() { return $this->ErrorStatus; }
236
241 function Id() { return $this->Id; }
242
247 function FullName()
248 {
249 return $this->DBFields["ClassificationName"];
250 }
251
256 function Name() { return $this->FullName(); }
257
262 function VariantName() { return NULL; }
263
268 function Depth() { return $this->DBFields["Depth"]; }
269
275 function ResourceCount() { return $this->DBFields["ResourceCount"]; }
276
283 function FullResourceCount() { return $this->DBFields["FullResourceCount"]; }
284
289 function SegmentsCreated() { return $this->SegmentsCreated; }
290
295 function ParentId() { return $this->DBFields["ParentId"]; }
296
302 function SegmentName($NewValue = DB_NOVALUE) {
303 return $this->UpdateValue("SegmentName", $NewValue); }
304
312 function LinkString($NewValue = DB_NOVALUE) {
313 return $this->UpdateValue("LinkString", $NewValue); }
314
321 function QualifierId($NewValue = DB_NOVALUE) {
322 return $this->UpdateValue("QualifierId", $NewValue); }
323
329 function FieldId($NewValue = DB_NOVALUE) {
330 return $this->UpdateValue("FieldId", $NewValue); }
331
338 function Qualifier($NewValue = DB_NOVALUE)
339 {
340 # if new qualifier supplied
341 if ($NewValue !== DB_NOVALUE)
342 {
343 # set new qualifier ID
344 $this->QualifierId($NewValue->Id());
345
346 # use new qualifier for return value
347 $Qualifier = $NewValue;
348 }
349 else
350 {
351 # if qualifier is available
352 if ($this->QualifierId() !== NULL)
353 {
354 # create qualifier object using stored ID
355 $Qualifier = new Qualifier($this->QualifierId());
356 }
357 else
358 {
359 # return NULL to indicate no qualifier
360 $Qualifier = NULL;
361 }
362 }
363
364 # return qualifier to caller
365 return $Qualifier;
366 }
367
373 function RecalcDepthAndFullName()
374 {
375 $DB = $this->DB;
376
377 # start with full classification name set to our segment name
378 $FullClassName = $this->DBFields["SegmentName"];
379
380 # assume to begin with that we're at the top of the hierarchy
381 $Depth = 0;
382
383 # while parent available
384 $ParentId = $this->DBFields["ParentId"];
385 while ($ParentId != -1)
386 {
387 # retrieve classification information
388 $DB->Query("SELECT SegmentName, ParentId "
389 ."FROM Classifications "
390 ."WHERE ClassificationId=".$ParentId);
391 $Record = $DB->FetchRow();
392
393 # prepend segment name to full classification name
394 $FullClassName = $Record["SegmentName"]." -- ".$FullClassName;
395
396 # increment depth value
397 $Depth++;
398
399 # move to parent of current classification
400 $ParentId = $Record["ParentId"];
401 }
402
403 # for each child
404 $DB->Query("SELECT ClassificationId "
405 ."FROM Classifications "
406 ."WHERE ParentId=".intval($this->Id));
407 while ($Record = $DB->FetchRow())
408 {
409 # perform depth and name recalc
410 $Child = new Classification($Record["ClassificationId"]);
411 $Child->RecalcDepthAndFullName();
412 }
413
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;
421 }
422
430 function RecalcResourceCount($IdsToSkip = NULL)
431 {
432 $IdsUpdated = array();
433
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))
436 {
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"];
446
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");
453
454 # save new count to database
455 $this->DB->Query("UPDATE Classifications SET "
456 ."ResourceCount=".$ResourceCount." "
457 ."WHERE ClassificationId=".intval($this->Id));
458
459 # save new count to our local cache
460 $this->DBFields["ResourceCount"] = $ResourceCount;
461
462 # add our ID to list of IDs that have been recalculated
463 $IdsUpdated[] = $this->Id;
464 }
465
466 # update resource count for our parent (if any)
467 if (($this->DBFields["ParentId"] != -1)
468 && (!$IdsToSkip || !in_array($this->DBFields["ParentId"], $IdsToSkip)) )
469 {
470 $Class = new Classification($this->DBFields["ParentId"]);
471 if ($Class->Status() == self::CLASSSTAT_OK)
472 {
473 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
474 }
475 }
476
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)."'
482 AND R.ResourceId > 0
483 AND I.ResourceId = R.ResourceId",
484 "ResourceCount");
485
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");
492
493 # save new count to database
494 $this->DB->Query("
495 UPDATE Classifications
496 SET FullResourceCount = '".intval($FullCount)."'
497 WHERE ClassificationId = '".intval($this->Id)."'");
498
499 # save new count to our local cache
500 $this->DBFields["FullResourceCount"] = $FullCount;
501
502 # return list of IDs of updated classifications to caller
503 return $IdsUpdated;
504 }
505
510 function ChildCount()
511 {
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),
516 "ClassCount");
517 }
518
524 function ChildList()
525 {
526 $ChildList = array();
527
528 $this->DB->Query("SELECT ClassificationId "
529 ."FROM Classifications "
530 ."WHERE ParentId=".intval($this->Id));
531
532 while ($Entry = $this->DB->FetchRow())
533 {
534 $ChildList[] = $Entry["ClassificationId"];
535 $Child = new Classification($Entry["ClassificationId"]);
536 if($Child->ChildCount() > 0)
537 {
538 $GrandChildList = $Child->ChildList();
539 $ChildList = array_merge($GrandChildList, $ChildList);
540 }
541 }
542 return $ChildList;
543 }
544
557 function Delete($DeleteParents = FALSE,
558 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
559 {
560 $DB = $this->DB;
561
562 # if no resources or okay to delete with resources
563 # and no children or okay to delete with children
564 if (($DeleteIfHasResources || ($this->ResourceCount() == 0))
565 && ($DeleteIfHasChildren || ($this->ChildCount() == 0)))
566 {
567 $ParentId = $this->DBFields["ParentId"];
568
569 if ($DeleteIfHasResources)
570 {
571 $DB->Query("DELETE FROM ResourceClassInts "
572 ."WHERE ClassificationId=".intval($this->Id));
573 $this->RecalcResourceCount();
574 }
575 # delete this classification
576 $DB->Query("DELETE FROM Classifications "
577 ."WHERE ClassificationId=".intval($this->Id));
578
579 # delete parent classification (if requested)
580 if (($DeleteParents) && ($this->DBFields["ParentId"] != -1))
581 {
582 $Parent = new Classification($this->DBFields["ParentId"]);
583 $Parent->Delete(
584 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
585 }
586 }
587 }
588
589
590 # ---- PRIVATE INTERFACE -------------------------------------------------
591
592 private $DB;
593 private $DBFields;
594 private $Id;
595 private $ErrorStatus;
596 private $SegmentsCreated;
597
605 private function UpdateValue($FieldName, $NewValue)
606 {
607 return $this->DB->UpdateValue("Classifications", $FieldName, $NewValue,
608 "ClassificationId = ".intval($this->Id),
609 $this->DBFields, TRUE);
610 }
611 }
Classification\LinkString
LinkString($NewValue=DB_NOVALUE)
Get or set the stored link string for the Classification.
Definition: Classification.php:312
Classification\CLASSSTAT_INVALIDPARENTID
const CLASSSTAT_INVALIDPARENTID
Status code indicating an invalid parent classification ID was specified.
Definition: Classification.php:22
Classification\FullName
FullName()
Get full classification name (all segments).
Definition: Classification.php:247
Classification\FullResourceCount
FullResourceCount()
Get number of all resources (minus temporary ones) having this classification assigned to them...
Definition: Classification.php:283
Database
SQL database abstraction object with smart query caching.
Definition: Axis--Database.php:22
Classification\CLASSSTAT_INVALIDID
const CLASSSTAT_INVALIDID
Status code indicating an invalid classification ID was specified.
Definition: Classification.php:20
DB_NOVALUE
const DB_NOVALUE
Definition: Axis--Database.php:1180
Classification\FieldId
FieldId($NewValue=DB_NOVALUE)
Get or set the ID of the MetadataField for the Classification.
Definition: Classification.php:329
Classification\VariantName
VariantName()
Get variant name of classification, if any.
Definition: Classification.php:262
Classification\Qualifier
Qualifier($NewValue=DB_NOVALUE)
Get or set the Qualifier associated with the Classification.
Definition: Classification.php:338
Classification\ChildCount
ChildCount()
Get number of classifications that have this Classification as their direct parent.
Definition: Classification.php:510
Classification\Classification
Classification($ClassId, $Name=NULL, $FieldId=NULL, $ParentId=NULL)
Class constructor.
Definition: Classification.php:42
Classification\RecalcResourceCount
RecalcResourceCount($IdsToSkip=NULL)
Recalculate number of resources assigned to class and any parent classes.
Definition: Classification.php:430
Classification\Name
Name()
Get name of classification segment.
Definition: Classification.php:256
Classification\ParentId
ParentId()
Get ID of parent Classification.
Definition: Classification.php:295
PHP
PHP
Definition: OAIClient.php:39
Classification\SegmentsCreated
SegmentsCreated()
Get number of new segments (Classifications) generated when creating a new Classification with a full...
Definition: Classification.php:289
Classification\RecalcDepthAndFullName
RecalcDepthAndFullName()
Rebuild classification full name and recalculate depth in hierarchy.
Definition: Classification.php:373
Classification\Status
Status()
Returns success/failure code for last call (where applicable).
Definition: Classification.php:235
Classification\Depth
Depth()
Get depth of classification in hierarchy.
Definition: Classification.php:268
Classification\CLASSSTAT_DUPLICATENAME
const CLASSSTAT_DUPLICATENAME
Status code indicating a duplicate classification name was specified.
Definition: Classification.php:24
Classification\ResourceCount
ResourceCount()
Get number of released resources having this classification assigned to them.
Definition: Classification.php:275
Classification\Delete
Delete($DeleteParents=FALSE, $DeleteIfHasResources=FALSE, $DeleteIfHasChildren=FALSE)
Remove Classification (and accompanying associations) from database.
Definition: Classification.php:557
Classification\CLASSSTAT_OK
const CLASSSTAT_OK
Status code indicating operation completed successfully.
Definition: Classification.php:18
Classification
Metadata type representing hierarchical (&quot;Tree&quot;) controlled vocabulary values.
Definition: Classification.php:13
Classification\QualifierId
QualifierId($NewValue=DB_NOVALUE)
Get or set the Qualifier associated with the Classification by ID.
Definition: Classification.php:321
Classification\ChildList
ChildList()
Get list of IDs of Classifications that have this class as an &quot;ancestor&quot; (parent, grandparent...
Definition: Classification.php:524
Classification\SegmentName
SegmentName($NewValue=DB_NOVALUE)
Get or set the segment name.
Definition: Classification.php:302
Classification\Id
Id()
Get Classification ID.
Definition: Classification.php:241