CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- 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
16 # ---- PUBLIC INTERFACE --------------------------------------------------
17
19 const CLASSSTAT_OK = 0;
21 const CLASSSTAT_INVALIDID = 1;
23 const CLASSSTAT_INVALIDPARENTID = 2;
25 const CLASSSTAT_DUPLICATENAME = 3;
26
43 public function __construct($ClassId, $Name = NULL, $FieldId = NULL, $ParentId = NULL)
44 {
45 static $IdCache;
46
47 # assume everything will turn out okay
48 $this->ErrorStatus = self::CLASSSTAT_OK;
49
50 # create DB handle for our use
51 $this->DB = new Database();
52 $DB = $this->DB;
53
54 # if class ID not given (indicating class must be created)
55 if ($ClassId === NULL)
56 {
57 if($FieldId === NULL)
58 {
59 throw new Exception("Cannot create a new
60 classification without specifying a field.");
61 }
62 # if parent class supplied
63 if ($ParentId !== NULL)
64 {
65 # if parent ID was invalid
66 if (($ParentId != -1)
67 && ($DB->Query("SELECT COUNT(*) AS NumberFound"
68 ." FROM Classifications"
69 ." WHERE ClassificationId = ".intval($ParentId),
70 "NumberFound") < 1))
71 {
72 # set error code for bad parent ID
73 $this->ErrorStatus = self::CLASSSTAT_INVALIDPARENTID;
74 }
75 else
76 {
77 # if name already exists
78 $Name = trim($Name);
79 if ($FieldId === NULL)
80 {
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))."'",
88 "NumberFound");
89 }
90 else
91 {
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))."'",
99 "NumberFound");
100 }
101
102 if ($Count > 0)
103 {
104 # set error code for duplicate class name
105 $this->ErrorStatus = self::CLASSSTAT_DUPLICATENAME;
106 }
107 else
108 {
109 # add class to database
110 $ParentId = intval($ParentId);
111 if ($ParentId == -1)
112 {
113 $NewName = $Name;
114 $NewDepth = 0;
115 }
116 else
117 {
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;
124 }
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)."')");
131
132 # retrieve ID of new class
133 $this->Id = $DB->LastInsertId();
134 }
135 }
136 }
137 else
138 {
139 # parse classification name into separate segments
140 $Segments = preg_split("/--/", $Name);
141
142 # start out with top as parent
143 $ParentId = -1;
144
145 # for each segment
146 $CurrentDepth = -1;
147 $CurrentFullName = "";
148 foreach ($Segments as $Segment)
149 {
150 # track segment depth and full classification name for use
151 # in adding new entries
152 $Segment = trim($Segment);
153 $CurrentDepth++;
154 $CurrentFullName .= (($CurrentFullName == "") ? "" : " -- ").$Segment;
155
156 # if we have added classifications
157 $Segment = addslashes($Segment);
158 if ($this->SegmentsCreated)
159 {
160 # we know that current segment will not be found
161 $ClassId = NULL;
162 }
163 else
164 {
165 # look up classification with current parent and segment name
166 if (!isset($IdCache[$FieldId][$ParentId][$Segment]))
167 {
168 if ($ParentId == -1)
169 {
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),
175 "ClassificationId");
176 }
177 else
178 {
179 $IdCache[$FieldId][$ParentId][$Segment] = $DB->Query(
180 "SELECT ClassificationId FROM Classifications "
181 ."WHERE ParentId = ".intval($ParentId)
182 ." AND SegmentName = '".addslashes($Segment)."'",
183 "ClassificationId");
184 }
185 }
186 $ClassId = $IdCache[$FieldId][$ParentId][$Segment];
187 }
188
189 # if classification not found
190 if ($ClassId === NULL)
191 {
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;
203
204 # track total number of new classification segments created
205 $this->SegmentsCreated++;
206 }
207
208 # set parent to created or found class
209 $ParentId = $ClassId;
210 }
211
212 # our class ID is the one that was last found
213 $this->Id = $ClassId;
214 }
215 }
216 else
217 {
218 # our class ID is the one that was supplied by caller
219 $this->Id = intval($ClassId);
220 }
221
222 # if no error encountered
223 if ($this->ErrorStatus == self::CLASSSTAT_OK)
224 {
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 ;
229
230 # set error status if class info not loaded
231 if ($this->DBFields === NULL ||
232 $this->DBFields["ClassificationId"] != $this->Id)
233 {
234 $this->ErrorStatus = self::CLASSSTAT_INVALIDID;
235 }
236 }
237 }
238
243 public function Status()
244 {
245 return $this->ErrorStatus;
246 }
247
252 public function Id()
253 {
254 return $this->Id;
255 }
256
261 public function FullName()
262 {
263 return $this->DBFields["ClassificationName"];
264 }
265
270 public function Name()
271 {
272 return $this->FullName();
273 }
274
279 public function VariantName()
280 {
281 return NULL;
282 }
283
288 public function Depth()
289 {
290 return $this->DBFields["Depth"];
291 }
292
298 public function ResourceCount()
299 {
300 return $this->DBFields["ResourceCount"];
301 }
302
309 public function FullResourceCount()
310 {
311 return $this->DBFields["FullResourceCount"];
312 }
313
318 public function SegmentsCreated()
319 {
320 return $this->SegmentsCreated;
321 }
322
327 public function ParentId()
328 {
329 return $this->DBFields["ParentId"];
330 }
331
337 public function SegmentName($NewValue = DB_NOVALUE)
338 {
339 return $this->UpdateValue("SegmentName", $NewValue);
340 }
341
349 public function LinkString($NewValue = DB_NOVALUE)
350 {
351 return $this->UpdateValue("LinkString", $NewValue);
352 }
353
360 public function QualifierId($NewValue = DB_NOVALUE)
361 {
362 return $this->UpdateValue("QualifierId", $NewValue);
363 }
364
370 public function FieldId($NewValue = DB_NOVALUE)
371 {
372 return $this->UpdateValue("FieldId", $NewValue);
373 }
374
381 public function Qualifier($NewValue = DB_NOVALUE)
382 {
383 # if new qualifier supplied
384 if ($NewValue !== DB_NOVALUE)
385 {
386 # set new qualifier ID
387 $this->QualifierId($NewValue->Id());
388
389 # use new qualifier for return value
390 $Qualifier = $NewValue;
391 }
392 else
393 {
394 # if qualifier is available
395 if ($this->QualifierId() !== NULL)
396 {
397 # create qualifier object using stored ID
398 $Qualifier = new Qualifier($this->QualifierId());
399 }
400 else
401 {
402 # return NULL to indicate no qualifier
403 $Qualifier = NULL;
404 }
405 }
406
407 # return qualifier to caller
408 return $Qualifier;
409 }
410
416 public function RecalcDepthAndFullName()
417 {
418 $DB = $this->DB;
419
420 # start with full classification name set to our segment name
421 $FullClassName = $this->DBFields["SegmentName"];
422
423 # assume to begin with that we're at the top of the hierarchy
424 $Depth = 0;
425
426 # while parent available
427 $ParentId = $this->DBFields["ParentId"];
428 while ($ParentId != -1)
429 {
430 # retrieve classification information
431 $DB->Query("SELECT SegmentName, ParentId "
432 ."FROM Classifications "
433 ."WHERE ClassificationId=".$ParentId);
434 $Record = $DB->FetchRow();
435
436 # prepend segment name to full classification name
437 $FullClassName = $Record["SegmentName"]." -- ".$FullClassName;
438
439 # increment depth value
440 $Depth++;
441
442 # move to parent of current classification
443 $ParentId = $Record["ParentId"];
444 }
445
446 # for each child
447 $DB->Query("SELECT ClassificationId "
448 ."FROM Classifications "
449 ."WHERE ParentId=".intval($this->Id));
450 while ($Record = $DB->FetchRow())
451 {
452 # perform depth and name recalc
453 $Child = new Classification($Record["ClassificationId"]);
454 $Child->RecalcDepthAndFullName();
455 }
456
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;
464 }
465
469 public function UpdateLastAssigned()
470 {
471 $this->DB->Query("UPDATE Classifications SET LastAssigned=NOW() "
472 ."WHERE ClassificationId=".intval($this->Id));
473 }
474
482 public function RecalcResourceCount($IdsToSkip = NULL)
483 {
484 $IdsUpdated = array();
485
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))
488 {
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"];
498
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");
505
506 # save new count to database
507 $this->DB->Query("UPDATE Classifications SET "
508 ."ResourceCount=".$ResourceCount." "
509 ."WHERE ClassificationId=".intval($this->Id));
510
511 # save new count to our local cache
512 $this->DBFields["ResourceCount"] = $ResourceCount;
513
514 # add our ID to list of IDs that have been recalculated
515 $IdsUpdated[] = $this->Id;
516 }
517
518 # update resource count for our parent (if any)
519 if (($this->DBFields["ParentId"] != -1)
520 && (!$IdsToSkip || !in_array($this->DBFields["ParentId"], $IdsToSkip)) )
521 {
522 $Class = new Classification($this->DBFields["ParentId"]);
523 if ($Class->Status() == self::CLASSSTAT_OK)
524 {
525 $IdsUpdated = array_merge($IdsUpdated, $Class->RecalcResourceCount());
526 }
527 }
528
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)."'
534 AND R.ResourceId > 0
535 AND I.ResourceId = R.ResourceId",
536 "ResourceCount");
537
538 # add on resources associated with all children
539 $FullCount += $this->DB->Query("
540 SELECT SUM(ResourceCount) AS ResourceCountTotal
541 FROM Classifications
542 WHERE ParentId = '".intval($this->Id)."'",
543 "ResourceCountTotal");
544
545 # save new count to database
546 $this->DB->Query("
547 UPDATE Classifications
548 SET FullResourceCount = '".intval($FullCount)."'
549 WHERE ClassificationId = '".intval($this->Id)."'");
550
551 # save new count to our local cache
552 $this->DBFields["FullResourceCount"] = $FullCount;
553
554 # return list of IDs of updated classifications to caller
555 return $IdsUpdated;
556 }
557
562 public function ChildCount()
563 {
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),
568 "ClassCount");
569 }
570
576 public function ChildList()
577 {
578 $ChildList = array();
579
580 $this->DB->Query("SELECT ClassificationId "
581 ."FROM Classifications "
582 ."WHERE ParentId=".intval($this->Id));
583
584 while ($Entry = $this->DB->FetchRow())
585 {
586 $ChildList[] = $Entry["ClassificationId"];
587 $Child = new Classification($Entry["ClassificationId"]);
588 if($Child->ChildCount() > 0)
589 {
590 $GrandChildList = $Child->ChildList();
591 $ChildList = array_merge($GrandChildList, $ChildList);
592 }
593 }
594 return array_unique($ChildList);
595 }
596
609 public function Delete($DeleteParents = FALSE,
610 $DeleteIfHasResources = FALSE, $DeleteIfHasChildren = FALSE)
611 {
612 $DB = $this->DB;
613
614 # if no resources or okay to delete with resources
615 # and no children or okay to delete with children
616 if (($DeleteIfHasResources || ($this->ResourceCount() == 0))
617 && ($DeleteIfHasChildren || ($this->ChildCount() == 0)))
618 {
619 if ($DeleteIfHasResources)
620 {
621 $DB->Query("DELETE FROM ResourceClassInts "
622 ."WHERE ClassificationId=".intval($this->Id));
623 $this->RecalcResourceCount();
624 }
625 # delete this classification
626 $DB->Query("DELETE FROM Classifications "
627 ."WHERE ClassificationId=".intval($this->Id));
628
629 # delete parent classification (if requested)
630 $ParentId = $this->DBFields["ParentId"];
631 if (($DeleteParents) && ($ParentId != -1))
632 {
633 $Parent = new Classification($ParentId);
634 $Parent->Delete(
635 TRUE, $DeleteIfHasResources, $DeleteIfHasChildren);
636 }
637 }
638 }
639
640
641 # ---- PRIVATE INTERFACE -------------------------------------------------
642
643 private $DB;
644 private $DBFields;
645 private $Id;
646 private $ErrorStatus;
647 private $SegmentsCreated;
648
656 private function UpdateValue($FieldName, $NewValue)
657 {
658 return $this->DB->UpdateValue("Classifications", $FieldName, $NewValue,
659 "ClassificationId = ".intval($this->Id),
660 $this->DBFields, TRUE);
661 }
662 }
Classification\LinkString
LinkString($NewValue=DB_NOVALUE)
Get or set the stored link string for the Classification.
Definition: Classification.php:349
Classification\__construct
__construct($ClassId, $Name=NULL, $FieldId=NULL, $ParentId=NULL)
Class constructor.
Definition: Classification.php:43
Classification\CLASSSTAT_INVALIDPARENTID
const CLASSSTAT_INVALIDPARENTID
Status code indicating an invalid parent classification ID was specified.
Definition: Classification.php:23
Classification\FullName
FullName()
Get full classification name (all segments).
Definition: Classification.php:261
Classification\FullResourceCount
FullResourceCount()
Get number of all resources (minus temporary ones) having this classification assigned to them...
Definition: Classification.php:309
Database
SQL database abstraction object with smart query caching.
Definition: Database.php:22
Classification\CLASSSTAT_INVALIDID
const CLASSSTAT_INVALIDID
Status code indicating an invalid classification ID was specified.
Definition: Classification.php:21
Classification\FieldId
FieldId($NewValue=DB_NOVALUE)
Get or set the ID of the MetadataField for the Classification.
Definition: Classification.php:370
Classification\VariantName
VariantName()
Get variant name of classification, if any.
Definition: Classification.php:279
Classification\Qualifier
Qualifier($NewValue=DB_NOVALUE)
Get or set the Qualifier associated with the Classification.
Definition: Classification.php:381
Classification\ChildCount
ChildCount()
Get number of classifications that have this Classification as their direct parent.
Definition: Classification.php:562
Classification\RecalcResourceCount
RecalcResourceCount($IdsToSkip=NULL)
Recalculate number of resources assigned to class and any parent classes.
Definition: Classification.php:482
Classification\Name
Name()
Get name of classification segment.
Definition: Classification.php:270
Classification\ParentId
ParentId()
Get ID of parent Classification.
Definition: Classification.php:327
Classification\SegmentsCreated
SegmentsCreated()
Get number of new segments (Classifications) generated when creating a new Classification with a full...
Definition: Classification.php:318
Classification\RecalcDepthAndFullName
RecalcDepthAndFullName()
Rebuild classification full name and recalculate depth in hierarchy.
Definition: Classification.php:416
PHP
PHP
Definition: RSSClient--Test.php:12
DB_NOVALUE
const DB_NOVALUE
Definition: Database.php:1396
Classification\Status
Status()
Returns success/failure code for last call (where applicable).
Definition: Classification.php:243
Classification\Depth
Depth()
Get depth of classification in hierarchy.
Definition: Classification.php:288
Classification\CLASSSTAT_DUPLICATENAME
const CLASSSTAT_DUPLICATENAME
Status code indicating a duplicate classification name was specified.
Definition: Classification.php:25
Classification\ResourceCount
ResourceCount()
Get number of released resources having this classification assigned to them.
Definition: Classification.php:298
Classification\Delete
Delete($DeleteParents=FALSE, $DeleteIfHasResources=FALSE, $DeleteIfHasChildren=FALSE)
Remove Classification (and accompanying associations) from database.
Definition: Classification.php:609
Classification\CLASSSTAT_OK
const CLASSSTAT_OK
Status code indicating operation completed successfully.
Definition: Classification.php:19
Classification\UpdateLastAssigned
UpdateLastAssigned()
Update the LastAssigned timestamp for this classification.
Definition: Classification.php:469
Classification
Metadata type representing hierarchical ("Tree") 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:360
Classification\ChildList
ChildList()
Get list of IDs of Classifications that have this class as an "ancestor" (parent, grandparent...
Definition: Classification.php:576
Classification\SegmentName
SegmentName($NewValue=DB_NOVALUE)
Get or set the segment name.
Definition: Classification.php:337
Classification\Id
Id()
Get Classification ID.
Definition: Classification.php:252