Search:

# CWIS Developers Documentation

- Main Page
- Classes
- Files

- File List
- File Members

# Resource.php

Go to the documentation of this file.

    00001 <?PHP
    00002 #
    00003 #   FILE:  Resource.php
    00004 #
    00005 #   Part of the Collection Workflow Integration System (CWIS)
    00006 #   Copyright 2011 Edward Almasy and Internet Scout Project
    00007 #   http://scout.wisc.edu/
    00008 #
    00009
    00013 class Resource {
    00014
    00015     # ---- PUBLIC INTERFACE --------------------------------------------------
    00016
    00022     function Resource($ResourceId = NULL)
    00023     {
    00024         $this->DB = new SPTDatabase();
    00025         $DB = $this->DB;
    00026         $this->Schema = new MetadataSchema();
    00027
    00028         # if resource ID supplied
    00029         if ($ResourceId !== NULL)
    00030         {
    00031             # save resource ID
    00032             $this->Id = intval($ResourceId);
    00033
    00034             # locate resource in database
    00035             $DB->Query("SELECT * FROM Resources WHERE ResourceId = ".$this->Id);
    00036
    00037             # if unable to locate resource
    00038             $Record = $DB->FetchRow();
    00039             if ($Record == FALSE)
    00040             {
    00041                 # set status to -1 to indicate that creation failed
    00042                 $this->LastStatus = -1;
    00043             }
    00044             else
    00045             {
    00046                 # load in attributes from database
    00047                 $this->DBFields = $Record;
    00048                 $this->CumulativeRating = $Record["CumulativeRating"];
    00049
    00050                 # set status to 1 to indicate that creation succeeded
    00051                 $this->LastStatus = 1;
    00052             }
    00053         }
    00054         else
    00055         {
    00056             # clean out any temp resource records more than three days old
    00057             $RFactory = new ResourceFactory();
    00058             $RFactory->CleanOutStaleTempItems(60 * 24 * 3);
    00059
    00060             # lock DB tables to prevent next ID from being grabbed
    00061             $DB->Query(
    00062                 "LOCK TABLES Resources write, APUsers read, ".
    00063                 "APSessions write, APSessionData write");
    00064
    00065             # find next temp resource ID
    00066             $this->Id = $RFactory->GetNextTempItemId();
    00067
    00068             # write out new resource record with temp resource ID and user ID
    00069             global $User;
    00070             $DB->Query("INSERT INTO Resources (ResourceId, AddedById,"
    00071                     ." LastModifiedById, DateLastModified, DateOfRecordCreation)"
    00072                        ." VALUES (".$this->Id.", "
    00073                                    .$User->Get("UserId").", "
    00074                                    .$User->Get("UserId").", "
    00075                                    ."NOW(), NOW())");
    00076
    00077             # release DB tables
    00078             $DB->Query("UNLOCK TABLES");
    00079
    00080             # load in attributes from database
    00081             $DB->Query("SELECT * FROM Resources WHERE ResourceId = ".$this->Id);
    00082             $this->DBFields = $DB->FetchRow();
    00083             $this->CumulativeRating = $this->DBFields["CumulativeRating"];
    00084
    00085             # set any default values
    00086             $Schema = new MetadataSchema();
    00087             $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_OPTION
    00088                     |MetadataSchema::MDFTYPE_TEXT
    00089                     |MetadataSchema::MDFTYPE_FLAG
    00090                     |MetadataSchema::MDFTYPE_NUMBER
    00091                     |MetadataSchema::MDFTYPE_POINT);
    00092             foreach ($Fields as $Field)
    00093             {
    00094                 $DefaultValue = $Field->DefaultValue();
    00095
    00096                 # flip option default values to get into the form that
    00097                 # Resource::Set() expects
    00098                 if ($Field->Type() == MetadataSchema::MDFTYPE_OPTION
    00099                     && is_array($DefaultValue))
    00100                 {
    00101                     $DefaultValue = array_flip($DefaultValue);
    00102                 }
    00103
    00104                 $this->SetByField($Field, $DefaultValue);
    00105             }
    00106
    00107             # Update timestamps as required:
    00108             $TimestampFields = $Schema->GetFields(
    00109                 MetadataSchema::MDFTYPE_TIMESTAMP);
    00110             foreach ($TimestampFields as $Field)
    00111             {
    00112                 if ($Field->UpdateMethod() ==
    00113                     MetadataField::UPDATEMETHOD_ONRECORDCREATE)
    00114                 {
    00115                     $this->SetByField($Field, "now");
    00116                 }
    00117             }
    00118
    00119             # signal resource creation
    00120             $GLOBALS["AF"]->SignalEvent("EVENT_RESOURCE_CREATE", array(
    00121                     "Resource" => $this,
    00122                     ));
    00123
    00124             # set status to 1 to indicate that creation succeeded
    00125             $this->LastStatus = 1;
    00126         }
    00127     }
    00128
    00133     function Delete()
    00134     {
    00135         global $SysConfig;
    00136
    00137         # signal that resource deletion is about to occur
    00138         global $AF;
    00139         $AF->SignalEvent("EVENT_RESOURCE_DELETE", array(
    00140                 "Resource" => $this,
    00141                 ));
    00142
    00143         # grab list of classifications
    00144         $Classifications = $this->Classifications();
    00145
    00146         # delete resource/classification intersections
    00147         $DB = $this->DB;
    00148         $DB->Query("DELETE FROM ResourceClassInts WHERE ResourceId = ".$this->Id());
    00149
    00150         # for each classification type
    00151         foreach ($Classifications as $ClassType => $ClassesOfType)
    00152         {
    00153             # for each classification of that type
    00154             foreach ($ClassesOfType as $ClassId => $ClassName)
    00155             {
    00156                 # recalculate resource count for classification
    00157                 $Class = new Classification($ClassId);
    00158                 $Class->RecalcResourceCount();
    00159             }
    00160         }
    00161
    00162         # delete resource/name intersections
    00163         $DB->Query("DELETE FROM ResourceNameInts WHERE ResourceId = ".$this->Id());
    00164
    00165         # delete any associated images not in use by other resources
    00166         $Fields = $this->Schema->GetFields(MetadataSchema::MDFTYPE_IMAGE);
    00167         foreach ($Fields as $Field)
    00168         {
    00169             $ImageId = $DB->Query("SELECT `".$Field->DBFieldName()
    00170                                   ."` FROM Resources WHERE ResourceId = ".$this->Id(),
    00171                                   $Field->DBFieldName());
    00172             if ($ImageId > 0)
    00173             {
    00174                 $ImageCount = $DB->Query("SELECT COUNT(*) AS ImageCount FROM Resources"
    00175                                          ." WHERE ".$Field->DBFieldName()." = ".$ImageId,
    00176                                          "ImageCount");
    00177                 if ($ImageCount < 2)
    00178                 {
    00179                     $Image = new SPTImage($ImageId);
    00180                     $Image->Delete();
    00181                 }
    00182             }
    00183         }
    00184
    00185         # delete any associated files
    00186         $Factory = new FileFactory(NULL);
    00187         $Files = $Factory->GetFilesForResource($this->Id());
    00188         foreach ($Files as $File)
    00189         {
    00190             $File->Delete();
    00191         }
    00192
    00193         # delete resource record from database
    00194         $DB->Query("DELETE FROM Resources WHERE ResourceId = ".$this->Id());
    00195
    00196         # drop item from search engine and recommender system
    00197         if ($SysConfig->SearchDBEnabled())
    00198         {
    00199             $SearchEngine = new SPTSearchEngine();
    00200             $SearchEngine->DropItem($this->Id());
    00201         }
    00202         if ($SysConfig->RecommenderDBEnabled())
    00203         {
    00204             $Recommender = new SPTRecommender();
    00205             $Recommender->DropItem($this->Id());
    00206         }
    00207
    00208         # delete any resource comments
    00209         $DB->Query("DELETE FROM Messages WHERE ParentId = ".$this->Id);
    00210     }
    00211
    00216     function Status() {  return $this->LastStatus;  }
    00217
    00222     function Id() {  return $this->Id;  }
    00223
    00229     function IsTempResource($NewSetting = NULL)
    00230     {
    00231         # if new temp resource setting supplied
    00232         if (!is_null($NewSetting))
    00233         {
    00234             # if caller requested to switch
    00235             $DB = $this->DB;
    00236             if ((($this->Id() < 0) && ($NewSetting == FALSE))
    00237                     || (($this->Id() >= 0) && ($NewSetting == TRUE)))
    00238             {
    00239                 # lock DB tables to prevent next ID from being grabbed
    00240                 $DB->Query("LOCK TABLES Resources write");
    00241
    00242                 # get next resource ID as appropriate
    00243                 $OldResourceId = $this->Id;
    00244                 $Factory = new ResourceFactory();
    00245                 if ($NewSetting == TRUE)
    00246                 {
    00247                     $this->Id = $Factory->GetNextTempItemId();
    00248                 }
    00249                 else
    00250                 {
    00251                     $this->Id = $Factory->GetNextItemId();
    00252                 }
    00253
    00254                 # change resource ID
    00255                 $DB->Query("UPDATE Resources SET ResourceId = ".
    00256                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
    00257
    00258                 # release DB tables
    00259                 $DB->Query("UNLOCK TABLES");
    00260
    00261                 # change associations
    00262                 unset($this->ClassificationCache);
    00263                 $DB->Query("UPDATE ResourceClassInts SET ResourceId = ".
    00264                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
    00265                 unset($this->ControlledNameCache);
    00266                 unset($this->ControlledNameVariantCache);
    00267                 $DB->Query("UPDATE ResourceNameInts SET ResourceId = ".
    00268                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
    00269                 $DB->Query("UPDATE Files SET ResourceId = ".
    00270                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
    00271
    00272                 # signal event as appropriate
    00273                 if ($NewSetting === FALSE)
    00274                 {
    00275                     $GLOBALS["AF"]->SignalEvent("EVENT_RESOURCE_ADD", array(
    00276                             "Resource" => $this,
    00277                             ));
    00278                 }
    00279             }
    00280         }
    00281
    00282         # report to caller whether we are a temp resource
    00283         return ($this->Id() < 0) ? TRUE : FALSE;
    00284     }
    00285
    00286
    00287     # --- Generic Attribute Retrieval Methods -------------------------------
    00288
    00303     function Get($FieldNameOrObject, $ReturnObject = FALSE, $IncludeVariants = FALSE)
    00304     {
    00305         # load field object if needed
    00306         $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
    00307                 : $this->Schema->GetFieldByName($FieldNameOrObject);
    00308
    00309         # return no value found if we don't have a valid field
    00310         if ((get_class($Field) != "MetadataField")
    00311                 || ($Field->Status() != MetadataSchema::MDFSTAT_OK))
    00312                 {  return NULL;  }
    00313
    00314         # grab database field name
    00315         $DBFieldName = $Field->DBFieldName();
    00316
    00317         # format return value based on field type
    00318         switch ($Field->Type())
    00319         {
    00320             case MetadataSchema::MDFTYPE_TEXT:
    00321             case MetadataSchema::MDFTYPE_PARAGRAPH:
    00322             case MetadataSchema::MDFTYPE_NUMBER:
    00323             case MetadataSchema::MDFTYPE_FLAG:
    00324             case MetadataSchema::MDFTYPE_URL:
    00325                 if (isset($this->DBFields[$DBFieldName]))
    00326                 {
    00327                     $ReturnValue = $this->DBFields[$DBFieldName];
    00328                 }
    00329                 else
    00330                 {
    00331                     $ReturnValue = NULL;
    00332                 }
    00333                 break;
    00334
    00335             case MetadataSchema::MDFTYPE_POINT:
    00336                 $ReturnValue = array("X" => $this->DBFields[$DBFieldName."X"],
    00337                                      "Y" => $this->DBFields[$DBFieldName."Y"]);
    00338                 break;
    00339
    00340             case MetadataSchema::MDFTYPE_DATE:
    00341                 $Date = new Date($this->DBFields[$DBFieldName."Begin"],
    00342                                     $this->DBFields[$DBFieldName."End"],
    00343                                     $this->DBFields[$DBFieldName."Precision"]);
    00344                 if ($ReturnObject)
    00345                 {
    00346                     $ReturnValue = $Date;
    00347                 }
    00348                 else
    00349                 {
    00350                     $ReturnValue = $Date->Formatted();
    00351                 }
    00352                 break;
    00353
    00354             case MetadataSchema::MDFTYPE_TIMESTAMP:
    00355                 $ReturnValue = $this->DBFields[$DBFieldName];
    00356                 break;
    00357
    00358             case MetadataSchema::MDFTYPE_TREE:
    00359                 # start with empty array
    00360                 $ReturnValue = array();
    00361
    00362                 # if classification cache has not been loaded
    00363                 if (!isset($this->ClassificationCache))
    00364                 {
    00365                     # load all classifications associated with this resource into cache
    00366                     $this->ClassificationCache = array();
    00367                     $this->DB->Query("SELECT Classifications.ClassificationId,Classifications.FieldId,ClassificationName "
    00368                             ."FROM ResourceClassInts, Classifications  "
    00369                             ."WHERE ResourceClassInts.ResourceId = ".$this->Id." "
    00370                             ."AND ResourceClassInts.ClassificationId = Classifications.ClassificationId ");
    00371                     while ($Record = $this->DB->FetchRow())
    00372                     {
    00373                         $this->ClassificationCache[$Record["ClassificationId"]]["Name"] =
    00374                                 $Record["ClassificationName"];
    00375                         $this->ClassificationCache[$Record["ClassificationId"]]["FieldId"] =
    00376                                 $Record["FieldId"];
    00377                     }
    00378                 }
    00379
    00380                 # for each entry in classification cache
    00381                 foreach ($this->ClassificationCache as $ClassificationId => $ClassificationInfo)
    00382                 {
    00383                     # if classification ID matches field we are looking for
    00384                     if ($ClassificationInfo["FieldId"] == $Field->Id())
    00385                     {
    00386                         # add field to result
    00387                         if ($ReturnObject)
    00388                         {
    00389                             $ReturnValue[$ClassificationId] = new Classification($ClassificationId);
    00390                         }
    00391                         else
    00392                         {
    00393                             $ReturnValue[$ClassificationId] = $ClassificationInfo["Name"];
    00394                         }
    00395                     }
    00396                 }
    00397                 break;
    00398
    00399             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
    00400             case MetadataSchema::MDFTYPE_OPTION:
    00401                 # start with empty array
    00402                 $ReturnValue = array();
    00403
    00404                 # if controlled name cache has not been loaded
    00405                 if (!isset($this->ControlledNameCache))
    00406                 {
    00407                     # load all controlled names associated with this resource into cache
    00408                     $this->ControlledNameCache = array();
    00409                     $this->DB->Query("SELECT ControlledNames.ControlledNameId,ControlledNames.FieldId,ControlledName "
    00410                             ."FROM ResourceNameInts, ControlledNames  "
    00411                             ."WHERE ResourceNameInts.ResourceId = ".$this->Id." "
    00412                             ."AND ResourceNameInts.ControlledNameId = ControlledNames.ControlledNameId ");
    00413                     while ($Record = $this->DB->FetchRow())
    00414                     {
    00415                         $this->ControlledNameCache[$Record["ControlledNameId"]]["Name"] = $Record["ControlledName"];
    00416                         $this->ControlledNameCache[$Record["ControlledNameId"]]["FieldId"] = $Record["FieldId"];
    00417                     }
    00418                 }
    00419
    00420                 # if variant names requested and variant name cache has not been loaded
    00421                 if ($IncludeVariants && !isset($this->ControlledNameVariantCache))
    00422                 {
    00423                     # load all controlled names associated with this resource into cache
    00424                     $this->ControlledNameVariantCache = array();
    00425                     $this->DB->Query("SELECT ControlledNames.ControlledNameId,ControlledNames.FieldId,ControlledName,VariantName "
    00426                             ."FROM ResourceNameInts, ControlledNames, VariantNames  "
    00427                             ."WHERE ResourceNameInts.ResourceId = ".$this->Id." "
    00428                             ."AND ResourceNameInts.ControlledNameId = ControlledNames.ControlledNameId "
    00429                             ."AND VariantNames.ControlledNameId = ControlledNames.ControlledNameId");
    00430                     while ($Record = $this->DB->FetchRow())
    00431                     {
    00432                         $this->ControlledNameVariantCache[$Record["ControlledNameId"]][] = $Record["VariantName"];
    00433                     }
    00434                 }
    00435
    00436                 # for each entry in controlled name cache
    00437                 foreach ($this->ControlledNameCache as $ControlledNameId => $ControlledNameInfo)
    00438                 {
    00439                     # if controlled name type matches field we are looking for
    00440                     if ($ControlledNameInfo["FieldId"] == $Field->Id())
    00441                     {
    00442                         # if objects requested
    00443                         if ($ReturnObject)
    00444                         {
    00445                             $ReturnValue[$ControlledNameId] =
    00446                                     new ControlledName($ControlledNameId);
    00447                         }
    00448                         else
    00449                         {
    00450                             # if variant names requested
    00451                             if ($IncludeVariants)
    00452                             {
    00453                                 # add field to result
    00454                                 $ReturnValue[] = $ControlledNameInfo["Name"];
    00455
    00456                                 # add any variant names to result
    00457                                 if (isset($this->ControlledNameVariantCache[$ControlledNameId]))
    00458                                 {
    00459                                     $ReturnValue = array_merge($ReturnValue, $this->ControlledNameVariantCache[$ControlledNameId]);
    00460                                 }
    00461                             }
    00462                             else
    00463                             {
    00464                                 # add field with index to result
    00465                                 $ReturnValue[$ControlledNameId] = $ControlledNameInfo["Name"];
    00466                             }
    00467                         }
    00468                     }
    00469                 }
    00470                 break;
    00471
    00472             case MetadataSchema::MDFTYPE_USER:
    00473                 $User = new User($this->DB, (int)$this->DBFields[$DBFieldName]);
    00474                 if ($ReturnObject)
    00475                 {
    00476                     $ReturnValue = $User;
    00477                 }
    00478                 else
    00479                 {
    00480                     $ReturnValue = $User->Get("UserName");
    00481                 }
    00482                 break;
    00483
    00484             case MetadataSchema::MDFTYPE_IMAGE:
    00485                 if ($this->DBFields[$DBFieldName] > 0)
    00486                 {
    00487                     $ImageObject = new SPTImage($this->DBFields[$DBFieldName]);
    00488                     if ($ReturnObject)
    00489                     {
    00490                         $ReturnValue = $ImageObject;
    00491                     }
    00492                     else
    00493                     {
    00494                         $ReturnValue = $ImageObject->AltText();
    00495                     }
    00496                 }
    00497                 else
    00498                 {
    00499                     $ReturnValue = NULL;
    00500                 }
    00501                 break;
    00502
    00503             case MetadataSchema::MDFTYPE_FILE:
    00504                 # retrieve files using factory
    00505                 $Factory = new FileFactory($Field->Id());
    00506                 $ReturnValue = $Factory->GetFilesForResource(
    00507                         $this->Id, $ReturnObject);
    00508                 break;
    00509
    00510             default:
    00511                 # ERROR OUT
    00512                 exit("<br>SPT - ERROR: attempt to retrieve unknown resource field type (".$Field->Type().")<br>\n");
    00513                 break;
    00514         }
    00515
    00516         # return formatted value to caller
    00517         return $ReturnValue;
    00518     }
    00523     function GetByField($FieldNameOrObject,
    00524             $ReturnObject = FALSE, $IncludeVariants = FALSE)
    00525     {  return $this->Get($FieldNameOrObject, $ReturnObject, $IncludeVariants);  }
    00526
    00540     function GetByFieldId($FieldId, $ReturnObject = FALSE, $IncludeVariants = FALSE)
    00541     {
    00542         $Field = $this->Schema->GetField($FieldId);
    00543         return ($Field) ? $this->Get($Field, $ReturnObject, $IncludeVariants) : NULL;
    00544     }
    00545
    00558     function GetAsArray($IncludeDisabledFields = FALSE, $ReturnObjects = TRUE)
    00559     {
    00560         # retrieve field info
    00561         $Fields = $this->Schema->GetFields();
    00562
    00563         # for each field
    00564         foreach ($Fields as $Field)
    00565         {
    00566             # if field is enabled or caller requested disabled fields
    00567             if ($Field->Enabled() || $IncludeDisabledFields)
    00568             {
    00569                 # retrieve info and add it to the array
    00570                 $FieldStrings[$Field->Name()] = $this->Get($Field, $ReturnObjects);
    00571
    00572                 # if field uses qualifiers
    00573                 if ($Field->UsesQualifiers())
    00574                 {
    00575                     # get qualifier attributes and add to the array
    00576                     $FieldStrings[$Field->Name()." Qualifier"] =
    00577                             $this->GetQualifierByField($Field, $ReturnObjects);
    00578                 }
    00579             }
    00580         }
    00581
    00582         # add in internal values
    00583         $FieldStrings["ResourceId"] = $this->Id();
    00584         $FieldStrings["CumulativeRating"] = $this->CumulativeRating();
    00585
    00586         # return array to caller
    00587         return $FieldStrings;
    00588     }
    00589
    00604     function GetMapped($MappedName, $ReturnObject = FALSE, $IncludeVariants = FALSE)
    00605     {
    00606         return $this->Schema->StdNameToFieldMapping($MappedName)
    00607                 ? $this->GetByFieldId($this->Schema->StdNameToFieldMapping($MappedName),
    00608                         $ReturnObject, $IncludeVariants)
    00609                 : NULL;
    00610     }
    00611
    00620     function GetQualifier($FieldName, $ReturnObject = TRUE)
    00621     {
    00622         $Field = $this->Schema->GetFieldByName($FieldName);
    00623         return $this->GetQualifierByField($Field, $ReturnObject);
    00624     }
    00625
    00634     function GetQualifierByFieldId($FieldId, $ReturnObject = TRUE)
    00635     {
    00636         $Field = $this->Schema->GetField($FieldId);
    00637         return $this->GetQualifierByField($Field, $ReturnObject);
    00638     }
    00639
    00648     function GetQualifierByField($Field, $ReturnObject = TRUE)
    00649     {
    00650         # return NULL if field is invalid
    00651         if ((get_class($Field) != "MetadataField")
    00652                 || ($Field->Status() != MetadataSchema::MDFSTAT_OK))
    00653                 {  return NULL;  }
    00654
    00655         # assume no qualifiers if not otherwise determined
    00656         $ReturnValue = NULL;
    00657
    00658         # if field uses qualifiers
    00659         if ($Field->UsesQualifiers())
    00660         {
    00661             # retrieve qualifiers based on field type
    00662             switch ($Field->Type())
    00663             {
    00664                 case MetadataSchema::MDFTYPE_TREE:
    00665                 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
    00666                 case MetadataSchema::MDFTYPE_OPTION:
    00667                     # retrieve list of items
    00668                     $Items = $this->Get($Field);
    00669
    00670                     # if field uses item-level qualifiers
    00671                     if ($Field->HasItemLevelQualifiers())
    00672                     {
    00673                         # determine general item name in DB
    00674                         $TableName = ($Field->Type() == MetadataSchema::MDFTYPE_TREE)
    00675                                 ? "Classification" : "ControlledName";
    00676
    00677                         # for each item
    00678                         foreach ($Items as $ItemId => $ItemName)
    00679                         {
    00680                             # look up qualifier for item
    00681                             $QualId = $this->DB->Query(
    00682                                     "SELECT * FROM ".$TableName."s"
    00683                                     ." WHERE ".$TableName."Id = ".$ItemId
    00684                                     , "QualifierId");
    00685
    00686
    00687                             if ($QualId > 0)
    00688                             {
    00689                                 # if object was requested by caller
    00690                                 if ($ReturnObject)
    00691                                 {
    00692                                     # load qualifier and add to return value array
    00693                                     $ReturnValue[$ItemId] = new Qualifier($QualId);
    00694                                 }
    00695                                 else
    00696                                 {
    00697                                     # add qualifier ID to return value array
    00698                                     $ReturnValue[$ItemId] = $QualId;
    00699                                 }
    00700                             }
    00701                             else
    00702                             {
    00703                                 # add NULL to return value array for this item
    00704                                 $ReturnValue[$ItemId] = NULL;
    00705                             }
    00706                         }
    00707                     }
    00708                     else
    00709                     {
    00710                         # for each item
    00711                         foreach ($Items as $ItemId => $ItemName)
    00712                         {
    00713                             # if object was requested by caller
    00714                             if ($ReturnObject)
    00715                             {
    00716                                 # load default qualifier and add to return value array
    00717                                 $ReturnValue[$ItemId] = new Qualifier($Field->DefaultQualifier());
    00718                             }
    00719                             else
    00720                             {
    00721                                 # add default qualifier ID to return value array
    00722                                 $ReturnValue[$ItemId] = $Field->DefaultQualifier();
    00723                             }
    00724                         }
    00725                     }
    00726                     break;
    00727
    00728                 default:
    00729                     # if field uses item-level qualifiers
    00730                     if ($Field->HasItemLevelQualifiers())
    00731                     {
    00732                         # if qualifier available
    00733                         if ($this->DBFields[$Field->DBFieldName()."Qualifier"] > 0)
    00734                         {
    00735                             # if object was requested by caller
    00736                             if ($ReturnObject)
    00737                             {
    00738                                 # return qualifier for field
    00739                                 $ReturnValue = new Qualifier($this->DBFields[$Field->DBFieldName()."Qualifier"]);
    00740                             }
    00741                             else
    00742                             {
    00743                                 # return qualifier ID for field
    00744                                 $ReturnValue = $this->DBFields[$Field->DBFieldName()."Qualifier"];
    00745                             }
    00746                         }
    00747                     }
    00748                     else
    00749                     {
    00750                         # if default qualifier available
    00751                         if ($Field->DefaultQualifier() > 0)
    00752                         {
    00753                             # if object was requested by caller
    00754                             if ($ReturnObject)
    00755                             {
    00756                                 # return default qualifier
    00757                                 $ReturnValue = new Qualifier($Field->DefaultQualifier());
    00758                             }
    00759                             else
    00760                             {
    00761                                 # return default qualifier ID
    00762                                 $ReturnValue = $Field->DefaultQualifier();
    00763                             }
    00764                         }
    00765                     }
    00766                     break;
    00767             }
    00768         }
    00769
    00770         # return qualifier object or ID (or array of same) to caller
    00771         return $ReturnValue;
    00772     }
    00773
    00774
    00775     # --- Generic Attribute Setting Methods ---------------------------------
    00776
    00777     # set value using field name or field object
    00778     function Set($FieldNameOrObject, $NewValue)
    00779     {
    00780         # load field object if needed
    00781         $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
    00782                 : $this->Schema->GetFieldByName($FieldNameOrObject);
    00783
    00784         # grab commonly-used values for local use
    00785         $DB = $this->DB;
    00786         $ResourceId = $this->Id;
    00787
    00788         # grab database field name
    00789         $DBFieldName = $Field->DBFieldName();
    00790
    00791         # Flag to deterimine if we've actually changed anything.
    00792         $UpdateModTime = FALSE;
    00793
    00794         # store value in DB based on field type
    00795         switch ($Field->Type())
    00796         {
    00797             case MetadataSchema::MDFTYPE_TEXT:
    00798             case MetadataSchema::MDFTYPE_PARAGRAPH:
    00799             case MetadataSchema::MDFTYPE_URL:
    00800                 if ($this->DBFields[$DBFieldName] != $NewValue)
    00801                 {
    00802                     # save value directly to DB
    00803                     $DB->Query("UPDATE Resources SET `"
    00804                                .$DBFieldName."` = '".addslashes($NewValue)."' "
    00805                                ."WHERE ResourceId = ".$ResourceId);
    00806
    00807                     # save value locally
    00808                     $this->DBFields[$DBFieldName] = $NewValue;
    00809                     $UpdateModTime=TRUE;
    00810                 }
    00811                 break;
    00812
    00813             case MetadataSchema::MDFTYPE_NUMBER:
    00814                 if ( $this->DBFields[$DBFieldName] != $NewValue )
    00815                 {
    00816                     # save value directly to DB
    00817                     if (is_null($NewValue))
    00818                     {
    00819                         $DB->Query("UPDATE Resources SET `"
    00820                                    .$DBFieldName."` = NULL"
    00821                                    ." WHERE ResourceId = ".$ResourceId);
    00822                     }
    00823                     else
    00824                     {
    00825                         $DB->Query("UPDATE Resources SET `"
    00826                                    .$DBFieldName."` = ".intval($NewValue)
    00827                                    ." WHERE ResourceId = ".$ResourceId);
    00828                     }
    00829
    00830                     # save value locally
    00831                     $this->DBFields[$DBFieldName] = $NewValue;
    00832                     $UpdateModTime = TRUE;
    00833                 }
    00834                 break;
    00835
    00836
    00837             case MetadataSchema::MDFTYPE_POINT:
    00838                 if ($this->DBFields[$DBFieldName."X"] != $NewValue["X"] ||
    00839                     $this->DBFields[$DBFieldName."Y"] != $NewValue["Y"] )
    00840                 {
    00841                     if (is_null($NewValue))
    00842                     {
    00843                         $DB->Query("UPDATE Resources SET "
    00844                                    ."`".$DBFieldName."X` = NULL, "
    00845                                    ."`".$DBFieldName."Y` = NULL "
    00846                                    ."WHERE ResourceId = ".$ResourceId);
    00847                         $this->DBFields[$DBFieldName."X"] = NULL;
    00848                         $this->DBFields[$DBFieldName."Y"] = NULL;
    00849                     }
    00850                     else
    00851                     {
    00852                         $DB->Query("UPDATE Resources SET "
    00853                                    ."`".$DBFieldName."X` = ".(strlen($NewValue["X"])
    00854                                                               ? "'".$NewValue["X"]."'" : "NULL").", "
    00855                                    ."`".$DBFieldName."Y` = ".(strlen($NewValue["Y"])
    00856                                                               ? "'".$NewValue["Y"]."'" : "NULL")
    00857                                    ." WHERE ResourceId = ".$ResourceId);
    00858
    00859                         $Digits = $Field->PointDecimalDigits();
    00860
    00861                         $this->DBFields[$DBFieldName."X"] =
    00862                             strlen($NewValue["X"]) ? round($NewValue["X"], $Digits) : NULL;
    00863                         $this->DBFields[$DBFieldName."Y"] =
    00864                             strlen($NewValue["Y"]) ? round($NewValue["Y"], $Digits) : NULL;
    00865                     }
    00866                     $UpdateModTime = TRUE;
    00867                 }
    00868                 break;
    00869
    00870             case MetadataSchema::MDFTYPE_FLAG:
    00871                 if ($this->DBFields[$DBFieldName] != $NewValue)
    00872                 {
    00873                     # save value directly to DB
    00874                     if (is_null($NewValue))
    00875                     {
    00876                         $DB->Query("UPDATE Resources SET `"
    00877                                    .$DBFieldName."` = NULL"
    00878                                    ." WHERE ResourceId = ".$ResourceId);
    00879                     }
    00880                     else
    00881                     {
    00882                         $DB->Query("UPDATE Resources SET `"
    00883                                    .$DBFieldName."` = ".$NewValue
    00884                                    ." WHERE ResourceId = ".$ResourceId);
    00885                     }
    00886
    00887                     $this->DBFields[$DBFieldName] = $NewValue;
    00888
    00889                     # recalculate counts for any associated classifications if necessary
    00890                     if ($DBFieldName == "ReleaseFlag")
    00891                     {
    00892                         $DB->Query("SELECT ClassificationId FROM ResourceClassInts"
    00893                                 ." WHERE ResourceId = ".$ResourceId);
    00894                         while ($ClassId = $DB->FetchField("ClassificationId"))
    00895                         {
    00896                             $Class = new Classification($ClassId);
    00897                             $Class->RecalcResourceCount();
    00898                         }
    00899                     }
    00900                     $UpdateModTime = TRUE;
    00901                 }
    00902                 break;
    00903
    00904             case MetadataSchema::MDFTYPE_USER:
    00905                 # if value passed in was object
    00906                 if (is_object($NewValue))
    00907                 {
    00908                     # retrieve user ID from object
    00909                     $UserId = $NewValue->Get("UserId");
    00910                 }
    00911                 # else if value passed in was user name
    00912                 elseif (is_string($NewValue))
    00913                 {
    00914                     # create user object and retrieve user ID from there
    00915                     $User = new User($this->DB, $NewValue);
    00916                     $UserId = $User->Get("UserId");
    00917                 }
    00918                 else
    00919                 {
    00920                     # assume value is user ID and use value directly
    00921                     $UserId = $NewValue;
    00922                 }
    00923
    00924                 if ($this->DBFields[$DBFieldName] != $UserId)
    00925                 {
    00926                     # save value directly to DB
    00927                     $DB->Query("UPDATE Resources SET `"
    00928                                .$DBFieldName."` = '".$UserId."' "
    00929                                ."WHERE ResourceId = ".$ResourceId);
    00930
    00931                     # save value locally
    00932                     $this->DBFields[$DBFieldName] = $UserId;
    00933                     $UpdateModTime = TRUE;
    00934                 }
    00935                 break;
    00936
    00937             case MetadataSchema::MDFTYPE_DATE:
    00938                 # if we were given a date object
    00939                 if (is_object($NewValue))
    00940                 {
    00941                     # use supplied date object
    00942                     $Date = $NewValue;
    00943                 }
    00944                 else
    00945                 {
    00946                     # create date object
    00947                     $Date = new Date($NewValue);
    00948                 }
    00949
    00950                 $OldDate = new Date(
    00951                     $this->DBFields[$DBFieldName."Begin"],
    00952                     $this->DBFields[$DBFieldName."End"]);
    00953
    00954                 if ($OldDate->BeginDate() != $Date->BeginDate() ||
    00955                     $OldDate->EndDate()   != $Date->EndDate()   ||
    00956                     $OldDate->Precision() != $Date->Precision() )
    00957                 {
    00958                     # extract values from date object and store in DB
    00959                     $BeginDate = "'".$Date->BeginDate()."'";
    00960                     if (strlen($BeginDate) < 3) {  $BeginDate = "NULL";  }
    00961                     $EndDate = "'".$Date->EndDate()."'";
    00962                     if (strlen($EndDate) < 3) {  $EndDate = "NULL";  }
    00963
    00964                     $DB->Query("UPDATE Resources SET "
    00965                                .$DBFieldName."Begin = ".$BeginDate.", "
    00966                                .$DBFieldName."End = ".$EndDate.", "
    00967                                .$DBFieldName."Precision = '".$Date->Precision()."' "
    00968                                ."WHERE ResourceId = ".$ResourceId);
    00969
    00970                     # save values locally
    00971                     $this->DBFields[$DBFieldName."Begin"] = $Date->BeginDate();
    00972                     $this->DBFields[$DBFieldName."End"] = $Date->EndDate();
    00973                     $this->DBFields[$DBFieldName."Precision"] = $Date->Precision();
    00974                     $UpdateModTime=TRUE;
    00975                 }
    00976                 break;
    00977
    00978             case MetadataSchema::MDFTYPE_TIMESTAMP:
    00979                 if (is_null($NewValue))
    00980                 {
    00981                     $DateValue = $NewValue;
    00982
    00983                     if (!is_null($this->DBFields[$DBFieldName]))
    00984                     {
    00985                         # save value directly to DB
    00986                         $DB->Query("UPDATE Resources SET "
    00987                                    ."`".$DBFieldName."` = NULL "
    00988                                    ."WHERE ResourceId = ".$ResourceId);
    00989                         $UpdateModTime = TRUE;
    00990                     }
    00991                 }
    00992                 else
    00993                 {
    00994                     # assume value is date and use directly
    00995                     $DateValue = date("Y-m-d H:i:s", strtotime($NewValue));
    00996
    00997                     if ($this->DBFields[$DBFieldName] != $DateValue)
    00998                     {
    00999                         # save value directly to DB
    01000                         $DB->Query("UPDATE Resources SET "
    01001                                    ."`".$DBFieldName."` = '".addslashes($DateValue)."' "
    01002                                    ."WHERE ResourceId = ".$ResourceId);
    01003                         $UpdateModTime=TRUE;
    01004                     }
    01005                 }
    01006
    01007                 # save value locally
    01008                 $this->DBFields[$DBFieldName] = $DateValue;
    01009                 break;
    01010
    01011             case MetadataSchema::MDFTYPE_TREE:
    01012                 $OldValue = $this->Get($Field);
    01013
    01014                 # if incoming value is array
    01015                 if (is_array($NewValue))
    01016                 {
    01017                     if ($OldValue != $NewValue)
    01018                     {
    01019                         # for each element of array
    01020                         foreach ($NewValue as
    01021                                  $ClassificationId => $ClassificationName)
    01022                         {
    01023                             $Class = new Classification($ClassificationId);
    01024                             if ($Class->Status() == Classification::CLASSSTAT_OK)
    01025                             {
    01026                                 # associate with resource if not already associated
    01027                                 $this->AddAssociation("ResourceClassInts",
    01028                                                       "ClassificationId",
    01029                                                       $ClassificationId);
    01030                                 $Class->RecalcResourceCount();
    01031                             }
    01032                         }
    01033                         $UpdateModTime=TRUE;
    01034                     }
    01035                 }
    01036                 else
    01037                 {
    01038                     # associate with resource if not already associated
    01039                     if (is_object($NewValue))
    01040                     {
    01041                         $Class = $NewValue;
    01042                         $NewValue = $Class->Id();
    01043                     }
    01044                     else
    01045                     {
    01046                         $Class = new Classification($NewValue);
    01047                     }
    01048
    01049                     if (!array_key_exists($Class->Id(), $OldValue))
    01050                     {
    01051
    01052                         $this->AddAssociation("ResourceClassInts",
    01053                                               "ClassificationId",
    01054                                               $NewValue);
    01055                         $Class->RecalcResourceCount();
    01056                         $UpdateModTime=TRUE;
    01057                     }
    01058                 }
    01059
    01060                 # clear our classification cache
    01061                 if ($UpdateModTime)
    01062                 {
    01063                     unset($this->ClassificationCache);
    01064                 }
    01065                 break;
    01066
    01067             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
    01068             case MetadataSchema::MDFTYPE_OPTION:
    01069                 $OldValue = $this->Get($Field);
    01070
    01071                 # Clear other values if this field expects unique options
    01072                 if ($Field->AllowMultiple() === FALSE)
    01073                 {
    01074                     # If we're fed an array for a unique option,
    01075                     # just use the last element of the array
    01076                     if (is_array($NewValue)){
    01077                         $NewValue = array_pop($NewValue);
    01078                     }
    01079
    01080                     if (!array_key_exists($NewValue, $OldValue))
    01081                     {
    01082
    01083                         $this->RemoveAllAssociations("ResourceNameInts",
    01084                                                      "ControlledNameId",
    01085                                                      $Field );
    01086                         $UpdateModTime=TRUE;
    01087                     }
    01088                 }
    01089
    01090                 # if incoming value is array
    01091                 if (is_array($NewValue) && ($Field->AllowMultiple() !== FALSE) )
    01092                 {
    01093                     if ($OldValue != $NewValue)
    01094                     {
    01095                         # for each element of array
    01096                         foreach ($NewValue as $ControlledNameId => $ControlledName)
    01097                         {
    01098                             # associate with resource if not already associated
    01099                             $this->AddAssociation("ResourceNameInts",
    01100                                                   "ControlledNameId",
    01101                                                   $ControlledNameId);
    01102                         }
    01103                         $UpdateModTime=TRUE;
    01104                     }
    01105                 }
    01106                 else
    01107                 {
    01108                     # associate with resource if not already associated
    01109                     if (is_object($NewValue)) {  $NewValue = $NewValue->Id();  }
    01110                     if (!array_key_exists($NewValue, $OldValue))
    01111                     {
    01112                         $this->AddAssociation("ResourceNameInts",
    01113                                               "ControlledNameId",
    01114                                               $NewValue);
    01115                         $UpdateModTime=TRUE;
    01116                     }
    01117                 }
    01118
    01119                 if ($UpdateModTime)
    01120                 {
    01121                     # clear our controlled name cache
    01122                     unset($this->ControlledNameCache);
    01123                     unset($this->ControlledNameVariantCache);
    01124                 }
    01125
    01126                 break;
    01127
    01128             case MetadataSchema::MDFTYPE_IMAGE:
    01129                 # if we were given an image object
    01130                 if (is_object($NewValue))
    01131                 {
    01132                     # grab ID from object
    01133                     $ImageId = $NewValue->Id();
    01134                 }
    01135                 else
    01136                 {
    01137                     # assume incoming value is ID
    01138                     $ImageId = $NewValue;
    01139                 }
    01140
    01141                 if ($this->DBFields[$DBFieldName] != $ImageId)
    01142                 {
    01143                     # store new image object ID in database
    01144                     $DB->Query("UPDATE Resources SET `"
    01145                                .$DBFieldName."` = '".$ImageId."'"
    01146                                ." WHERE ResourceId = ".$ResourceId);
    01147                     $UpdateModTime = TRUE;
    01148                     # save value locally
    01149                     $this->DBFields[$DBFieldName] = $ImageId;
    01150                 }
    01151                 break;
    01152
    01153             case MetadataSchema::MDFTYPE_FILE:
    01154                 # convert incoming value to array if necessary
    01155                 if (!is_array($NewValue)) {  $NewValue = array($NewValue);  }
    01156
    01157                 # for each incoming file
    01158                 $Factory = new FileFactory($Field->Id());
    01159                 foreach ($NewValue as $File)
    01160                 {
    01161                     # make copy of file
    01162                     $NewFile = $Factory->Copy($File);
    01163
    01164                     # associate copy with this resource and field
    01165                     $NewFile->ResourceId($this->Id);
    01166                     $NewFile->FieldId($Field->Id());
    01167                 }
    01168                 # Since we make a fresh copy of the File whenever Set is called,
    01169                 # we'll always update the modification time for this field.
    01170                 $UpdateModTime = TRUE;
    01171                 break;
    01172
    01173             default:
    01174                 # ERROR OUT
    01175                 exit("<br>SPT - ERROR: attempt to set unknown resource field type<br>\n");
    01176                 break;
    01177         }
    01178
    01179         if ($UpdateModTime && !$this->IsTempResource())
    01180         {
    01181             # update modification timestamps
    01182             global $G_User;
    01183             $UserId = $G_User->IsLoggedIn() ? $G_User->Get("UserId") : -1;
    01184             $DB->Query("DELETE FROM ResourceFieldTimestamps "
    01185                        ."WHERE ResourceId=".$this->Id." AND "
    01186                        ."FieldId=".$Field->Id() );
    01187             $DB->Query("INSERT INTO ResourceFieldTimestamps "
    01188                        ."(ResourceId,FieldId,ModifiedBy,Timestamp) VALUES ("
    01189                        .$this->Id.",".$Field->Id().","
    01190                        .$UserId.",NOW())");
    01191         }
    01192     }
    01193     # (for backward compatibility)
    01194     function SetByField($Field, $NewValue) {  return $this->Set($Field, $NewValue);  }
    01195
    01196     # set value by field ID
    01197     function SetByFieldId($FieldId, $NewValue)
    01198     {
    01199         $Field = $this->Schema->GetField($FieldId);
    01200         return $this->Set($Field, $NewValue);
    01201     }
    01202
    01203     # set qualifier by field name
    01204     function SetQualifier($FieldName, $NewValue)
    01205     {
    01206         $Field = $this->Schema->GetFieldByName($FieldName);
    01207         return $this->SetQualifierByField($Field, $NewValue);
    01208     }
    01209
    01210     # set qualifier by field ID
    01211     function SetQualifierByFieldId($FieldId, $NewValue)
    01212     {
    01213         $Field = $this->Schema->GetField($FieldId);
    01214         return $this->SetQualifierByField($Field, $NewValue);
    01215     }
    01216
    01217     # set qualifier using field object
    01218     function SetQualifierByField($Field, $NewValue)
    01219     {
    01220         # if field uses qualifiers and uses item-level qualifiers
    01221         if ($Field->UsesQualifiers() && $Field->HasItemLevelQualifiers())
    01222         {
    01223             # if qualifier object passed in
    01224             if (is_object($NewValue))
    01225             {
    01226                 # grab qualifier ID from object
    01227                 $QualifierId = $NewValue->Id();
    01228             }
    01229             else
    01230             {
    01231                 # assume value passed in is qualifier ID
    01232                 $QualifierId = $NewValue;
    01233             }
    01234
    01235             # update qualifier value in database
    01236             $DBFieldName = $Field->DBFieldName();
    01237             $this->DB->Query("UPDATE Resources SET "
    01238                      .$DBFieldName."Qualifier = '".$QualifierId."' "
    01239                      ."WHERE ResourceId = ".$this->Id);
    01240
    01241             # update local qualifier value
    01242             $this->DBFields[$DBFieldName."Qualifier"] = $QualifierId;
    01243         }
    01244     }
    01245
    01246     # clear value by field name
    01247     function Clear($FieldName, $ValueToClear = NULL)
    01248     {
    01249         $Field = $this->Schema->GetFieldByName($FieldName);
    01250         return $this->ClearByField($Field, $ValueToClear);
    01251     }
    01252
    01253     # clear value by field ID
    01254     function ClearByFieldId($FieldId, $ValueToClear = NULL)
    01255     {
    01256         $Field = $this->Schema->GetField($FieldId);
    01257         return $this->ClearByField($Field, $ValueToClear);
    01258     }
    01259
    01260     # clear value using field object
    01261     function ClearByField($Field, $ValueToClear = NULL)
    01262     {
    01263         # grab commonly-used values for local use
    01264         $DB = $this->DB;
    01265         $ResourceId = $this->Id;
    01266
    01267         # grab database field name
    01268         $DBFieldName = $Field->DBFieldName();
    01269
    01270         $UpdateModTime=FALSE;
    01271
    01272         # store value in DB based on field type
    01273         switch ($Field->Type())
    01274         {
    01275             case MetadataSchema::MDFTYPE_TEXT:
    01276             case MetadataSchema::MDFTYPE_PARAGRAPH:
    01277             case MetadataSchema::MDFTYPE_NUMBER:
    01278             case MetadataSchema::MDFTYPE_FLAG:
    01279             case MetadataSchema::MDFTYPE_USER:
    01280             case MetadataSchema::MDFTYPE_TIMESTAMP:
    01281             case MetadataSchema::MDFTYPE_URL:
    01282                 if (strlen($this->DBFields[$DBFieldName])>0)
    01283                 {
    01284                     # clear value in DB
    01285                     $DB->Query("UPDATE Resources SET `"
    01286                                .$DBFieldName."` = '' "
    01287                                ."WHERE ResourceId = ".$ResourceId);
    01288
    01289                     # clear value locally
    01290                     $this->DBFields[$DBFieldName] = NULL;
    01291                     $UpdateModTime=TRUE;
    01292                 }
    01293                 break;
    01294
    01295             case MetadataSchema::MDFTYPE_POINT:
    01296                 if (!is_null($this->DBFields[$DBFieldName."X"]) ||
    01297                     !is_null($this->DBFields[$DBFieldName."Y"]) )
    01298                 {
    01299                     # Clear DB Values
    01300                     $DB->Query("UPDATE Resources SET "
    01301                                ."`".$DBFieldName."X` = NULL ,"
    01302                                ."`".$DBFieldName."Y` = NULL "
    01303                                ."WHERE ResourceId = ".$ResourceId);
    01304
    01305                     # Clear local values
    01306                     $this->DBFields[$DBFieldName."X"] = NULL;
    01307                     $this->DBFields[$DBFieldName."Y"] = NULL;
    01308                     $UpdateModTime=TRUE;
    01309                 }
    01310                 break;
    01311
    01312             case MetadataSchema::MDFTYPE_DATE:
    01313                 if (!is_null($this->DBFields[$DBFieldName."Begin"]) ||
    01314                     !is_null($this->DBFields[$DBFieldName."End"])   ||
    01315                     !is_null($this->DBFields[$DBFieldName."Precision"]))
    01316                 {
    01317                     # clear date object values in DB
    01318                     $DB->Query("UPDATE Resources SET "
    01319                                .$DBFieldName."Begin = '', "
    01320                                .$DBFieldName."End = '', "
    01321                                .$DBFieldName."Precision = '' "
    01322                                ."WHERE ResourceId = ".$ResourceId);
    01323
    01324                     # clear value locally
    01325                     $this->DBFields[$DBFieldName."Begin"] = NULL;
    01326                     $this->DBFields[$DBFieldName."End"] = NULL;
    01327                     $this->DBFields[$DBFieldName."Precision"] = NULL;
    01328                     $UpdateModTime=TRUE;
    01329                 }
    01330                 break;
    01331
    01332             case MetadataSchema::MDFTYPE_TREE:
    01333                 $OldValue = $this->Get($Field);
    01334
    01335                 # if value to clear supplied
    01336                 if ($ValueToClear !== NULL)
    01337                 {
    01338                     # if supplied value is array
    01339                     if (is_array($ValueToClear))
    01340                     {
    01341                         # for each element of array
    01342                         foreach ($ValueToClear as $ClassificationId => $Dummy)
    01343                         {
    01344                             if (array_key_exists($ClassificationId, $OldValue))
    01345                             {
    01346                                 # remove association with resource (if any)
    01347                                 $this->RemoveAssociation("ResourceClassInts",
    01348                                                          "ClassificationId",
    01349                                                          $ClassificationId);
    01350                                 $Class = new Classification($ClassificationId);
    01351                                 $Class->RecalcResourceCount();
    01352                                 $UpdateModTime=TRUE;
    01353                             }
    01354                         }
    01355                     }
    01356                     else
    01357                     {
    01358                         if (array_key_exists($ValueToClear, $OldValue))
    01359                         {
    01360                             # remove association with resource (if any)
    01361                             $this->RemoveAssociation("ResourceClassInts",
    01362                                                      "ClassificationId",
    01363                                                      $ValueToClear);
    01364                             $Class = new Classification($ValueToClear);
    01365                             $Class->RecalcResourceCount();
    01366                             $UpdateModTime=TRUE;
    01367                         }
    01368                     }
    01369                 }
    01370                 else
    01371                 {
    01372                     if (count($OldValue)>0)
    01373                     {
    01374                         # remove all associations for resource and field
    01375                         $this->RemoveAllAssociations("ResourceClassInts", "ClassificationId", $Field);
    01376
    01377                         # recompute resource count
    01378                         $Values = $this->Get($Field);
    01379                         foreach ($Values as $ClassificationId => $Dummy)
    01380                         {
    01381                             $Class = new Classification($ClassificationId);
    01382                             $Class->RecalcResourceCount();
    01383                         }
    01384                         $UpdateModTime=TRUE;
    01385                     }
    01386                 }
    01387
    01388                 # clear our classification cache
    01389                 if ($UpdateModTime)
    01390                 {
    01391                     unset($this->ClassificationCache);
    01392                 }
    01393                 break;
    01394
    01395             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
    01396             case MetadataSchema::MDFTYPE_OPTION:
    01397                 $OldValue = $this->Get($Field);
    01398                 # if value to clear supplied
    01399                 if ($ValueToClear !== NULL)
    01400                 {
    01401                     # if incoming value is array
    01402                     if (is_array($ValueToClear))
    01403                     {
    01404                         # for each element of array
    01405                         foreach ($ValueToClear as $ControlledNameId =>
    01406                             $ControlledName)
    01407                         {
    01408                             if (array_key_exists($ControlledNameId, $OldValue))
    01409                             {
    01410                                 # remove association with resource (if any)
    01411                                 $this->RemoveAssociation("ResourceNameInts",
    01412                                                          "ControlledNameId",
    01413                                                          $ControlledNameId);
    01414                                 $UpdateModTime=TRUE;
    01415                             }
    01416                         }
    01417                     }
    01418                     else
    01419                     {
    01420                         if (array_key_exists($ValueToClear, $OldValue))
    01421                         {
    01422                             # remove association with resource (if any)
    01423                             $this->RemoveAssociation("ResourceNameInts",
    01424                                                      "ControlledNameId",
    01425                                                      $ValueToClear);
    01426                             $UpdateModTime=TRUE;
    01427                         }
    01428                     }
    01429                 }
    01430                 else
    01431                 {
    01432                     if (count($OldValue)>0)
    01433                     {
    01434                         # remove all associations for resource and field
    01435                         $this->RemoveAllAssociations("ResourceNameInts", "ControlledNameId", $Field);
    01436                         $UpdateModTime=TRUE;
    01437                     }
    01438                 }
    01439
    01440                 if ($UpdateModTime)
    01441                 {
    01442                     # clear our controlled name cache
    01443                     unset($this->ControlledNameCache);
    01444                     unset($this->ControlledNameVariantCache);
    01445                 }
    01446                 break;
    01447
    01448             case MetadataSchema::MDFTYPE_IMAGE:
    01449                 # delete image if no other resources are using it
    01450                 $ImageId = $DB->Query("SELECT `".$DBFieldName
    01451                                       ."` FROM Resources WHERE ResourceId = ".$ResourceId,
    01452                                       $DBFieldName);
    01453                 if ($ImageId > 0)
    01454                 {
    01455                     $ImageCount = $DB->Query("SELECT COUNT(*) AS ImageCount FROM Resources"
    01456                                              ." WHERE `".$DBFieldName."` = ".$ImageId,
    01457                                              "ImageCount");
    01458                     if ($ImageCount < 2)
    01459                     {
    01460                         $Image = new SPTImage($ImageId);
    01461                         $Image->Delete();
    01462                     }
    01463                     $UpdateModTime=TRUE;
    01464                 }
    01465
    01466                 # clear stored ID
    01467                 $DB->Query("UPDATE Resources SET `"
    01468                            .$DBFieldName."` = '' "
    01469                            ."WHERE ResourceId = ".$ResourceId);
    01470
    01471                 # clear value locally
    01472                 $this->DBFields[$DBFieldName] = NULL;
    01473                 break;
    01474
    01475             case MetadataSchema::MDFTYPE_FILE:
    01476                 # get array of Files associated with this resource
    01477                 $Files = $this->Get($Field, TRUE);
    01478
    01479                 if (count($Files)>0){
    01480                     # for each File
    01481                     foreach ($Files as $File)
    01482                     {
    01483                         # delete file
    01484                         $File->Delete();
    01485                     }
    01486                     $UpdateModTime=TRUE;
    01487                 }
    01488                 break;
    01489
    01490             default:
    01491                 # ERROR OUT
    01492                 exit("<br>SPT - ERROR: attempt to clear unknown resource field type<br>\n");
    01493                 break;
    01494         }
    01495
    01496         if ($UpdateModTime && !$this->IsTempResource())
    01497         {
    01498             # update modification timestamps
    01499             global $G_User;
    01500             $UserId = $G_User->IsLoggedIn() ? $G_User->Get("UserId") : -1;
    01501             $DB->Query("DELETE FROM ResourceFieldTimestamps "
    01502                        ."WHERE ResourceId=".$this->Id." AND "
    01503                        ."FieldId=".$Field->Id() );
    01504             $DB->Query("INSERT INTO ResourceFieldTimestamps "
    01505                        ."(ResourceId,FieldId,ModifiedBy,Timestamp) VALUES ("
    01506                        .$this->Id.",".$Field->Id().","
    01507                        .$UserId.",NOW())");
    01508         }
    01509     }
    01510
    01511
    01512     # --- Field-Specific or Type-Specific Attribute Retrieval Methods -------
    01513
    01514     # return 2D array of classifications associated with resource
    01515     # (first index is classification (field) name, second index is classification ID)
    01516     function Classifications()
    01517     {
    01518         $DB = $this->DB;
    01519
    01520         # start with empty array
    01521         $Names = array();
    01522
    01523         # for each controlled name
    01524         $DB->Query("SELECT ClassificationName, MetadataFields.FieldName, "
    01525                 ."ResourceClassInts.ClassificationId FROM ResourceClassInts, "
    01526                 ."Classifications, MetadataFields "
    01527                 ."WHERE ResourceClassInts.ResourceId = ".$this->Id." "
    01528                 ."AND ResourceClassInts.ClassificationId = Classifications.ClassificationId "
    01529                 ."AND Classifications.FieldId = MetadataFields.FieldId ");
    01530         while ($Record = $DB->FetchRow())
    01531         {
    01532             # add name to array
    01533             $Names[$Record["FieldName"]][$Record["ClassificationId"]] =
    01534                     $Record["ClassificationName"];
    01535         }
    01536
    01537         # return array to caller
    01538         return $Names;
    01539     }
    01540
    01541
    01542     # --- Ratings Methods ---------------------------------------------------
    01543
    01544     # return cumulative rating  (range is usually 0-100)
    01545     function CumulativeRating() {  return $this->CumulativeRating;  }
    01546
    01547     # return cumulative rating scaled to 1/10th  (range is usually 0-10)
    01548     function ScaledCumulativeRating()
    01549     {
    01550         if ($this->CumulativeRating == NULL)
    01551         {
    01552             return NULL;
    01553         }
    01554         else
    01555         {
    01556             return intval(($this->CumulativeRating + 5) / 10);
    01557         }
    01558     }
    01559
    01560     # return current number of ratings for resource
    01561     function NumberOfRatings()
    01562     {
    01563         # if number of ratings not already set
    01564         if (!isset($this->NumberOfRatings))
    01565         {
    01566             # obtain number of ratings
    01567             $this->NumberOfRatings =
    01568                     $this->DB->Query("SELECT Count(*) AS NumberOfRatings "
    01569                             ."FROM ResourceRatings "
    01570                             ."WHERE ResourceId = ".$this->Id,
    01571                     "NumberOfRatings"
    01572                     );
    01573
    01574             # recalculate cumulative rating if it looks erroneous
    01575             if (($this->NumberOfRatings > 0) && !$this->CumulativeRating())
    01576             {
    01577                 $this->UpdateCumulativeRating();
    01578             }
    01579         }
    01580
    01581         # return number of ratings to caller
    01582         return $this->NumberOfRatings;
    01583     }
    01584
    01585     # update individual rating for resource
    01586     function Rating($NewRating = NULL, $UserId = NULL)
    01587     {
    01588         $DB = $this->DB;
    01589
    01590         # if user ID not supplied
    01591         if ($UserId == NULL)
    01592         {
    01593             # if user is logged in
    01594             global $User;
    01595             if ($User->IsLoggedIn())
    01596             {
    01597                 # use ID of current user
    01598                 $UserId = $User->Get("UserId");
    01599             }
    01600             else
    01601             {
    01602                 # return NULL to caller
    01603                 return NULL;
    01604             }
    01605         }
    01606
    01607         # sanitize $NewRating
    01608         if (!is_null($NewRating))
    01609         {
    01610             $NewRating = intval($NewRating);
    01611         }
    01612
    01613         # if there is a rating for resource and user
    01614         $DB->Query("SELECT Rating FROM ResourceRatings "
    01615                 ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
    01616         if ($Record = $DB->FetchRow())
    01617         {
    01618             # if new rating was supplied
    01619             if ($NewRating != NULL)
    01620             {
    01621                 # update existing rating
    01622                 $DB->Query("UPDATE ResourceRatings "
    01623                         ."SET Rating = ${NewRating}, DateRated = NOW() "
    01624                         ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
    01625
    01626                 # update cumulative rating value
    01627                 $this->UpdateCumulativeRating();
    01628
    01629                 # return value is new rating
    01630                 $Rating = $NewRating;
    01631             }
    01632             else
    01633             {
    01634                 # get rating value to return to caller
    01635                 $Rating = $Record["Rating"];
    01636             }
    01637         }
    01638         else
    01639         {
    01640             # if new rating was supplied
    01641             if ($NewRating != NULL)
    01642             {
    01643                 # add new rating
    01644                 $DB->Query("INSERT INTO ResourceRatings "
    01645                         ."(ResourceId, UserId, DateRated, Rating) "
    01646                         ."VALUES ("
    01647                                 .$this->Id.", "
    01648                                 ."${UserId}, "
    01649                                 ."NOW(), "
    01650                                 ."${NewRating})");
    01651
    01652                 # update cumulative rating value
    01653                 $this->UpdateCumulativeRating();
    01654
    01655                 # return value is new rating
    01656                 $Rating = $NewRating;
    01657             }
    01658             else
    01659             {
    01660                 # return value is NULL
    01661                 $Rating = NULL;
    01662             }
    01663         }
    01664
    01665         # return rating value to caller
    01666         return $Rating;
    01667     }
    01668
    01669
    01670     # --- Resource Comment Methods ------------------------------------------
    01671
    01672     # return comments as array of Message objects
    01673     function Comments()
    01674     {
    01675         # read in comments if not already loaded
    01676         if (!isset($this->Comments))
    01677         {
    01678             $this->DB->Query("SELECT MessageId FROM Messages "
    01679                     ."WHERE ParentId = ".$this->Id
    01680                     ." AND ParentType = 2 "
    01681                     ."ORDER BY DatePosted DESC");
    01682             while ($MessageId = $this->DB->FetchField("MessageId"))
    01683             {
    01684                 $this->Comments[] = new Message($MessageId);
    01685             }
    01686         }
    01687
    01688         # return array of comments to caller
    01689         return $this->Comments;
    01690     }
    01691
    01692     # return current number of comments
    01693     function NumberOfComments()
    01694     {
    01695         # obtain number of comments if not already set
    01696         if (!isset($this->NumberOfComments))
    01697         {
    01698             $this->NumberOfComments =
    01699                     $this->DB->Query("SELECT Count(*) AS NumberOfComments "
    01700                             ."FROM Messages "
    01701                             ."WHERE ParentId = ".$this->Id
    01702                             ." AND ParentType = 2",
    01703                     "NumberOfComments"
    01704                     );
    01705         }
    01706
    01707         # return number of comments to caller
    01708         return $this->NumberOfComments;
    01709     }
    01710
    01711
    01712     # --- Permission Methods -------------------------------------------------
    01713
    01714     # return whether user can edit this resource
    01715     function UserCanEdit($User)
    01716     {
    01717         return ($User->HasPriv(PRIV_RESOURCEADMIN)
    01718             || $User->HasPriv(PRIV_RELEASEADMIN)
    01719             || ($User->HasPriv(PRIV_MYRESOURCEADMIN)
    01720                     && ($User->Id() == $this->DBFields["AddedById"]))
    01721         );
    01722     }
    01723
    01724     # report whether user can view or edit the specified field
    01725     function UserCanViewField($User, $FieldOrFieldName)
    01726     {
    01727         $Schema = new MetadataSchema();
    01728
    01729         # get field (if not supplied)
    01730         if (is_object($FieldOrFieldName)
    01731                 && ($FieldOrFieldName instanceof MetadataField))
    01732         {
    01733             $Field = $FieldOrFieldName;
    01734         }
    01735         elseif (strlen(trim($FieldOrFieldName)))
    01736         {
    01737             if ($Schema->FieldExists($FieldOrFieldName))
    01738             {
    01739                 $Field = $Schema->GetFieldByName($FieldOrFieldName);
    01740             }
    01741         }
    01742
    01743         # the field must be valid and enabled to be viewable
    01744         if (!isset($Field) || !$Field->Enabled())
    01745         {
    01746             return FALSE;
    01747         }
    01748
    01749         # if the user can edit the field, they can also view it implicitly
    01750         if ($this->UserCanEditField($User, $Field))
    01751         {
    01752             return TRUE;
    01753         }
    01754
    01755         # an "user is value of field" constraint isn't set, so only worry about
    01756         # the viewing privilege
    01757         if ($Field->ViewingUserIsValue() == MetadataField::USERISVALUE_UNSET)
    01758         {
    01759             # no viewing privilege is set, so anyone can view the field
    01760             if ($Field->ViewingPrivilege() == 0)
    01761             {
    01762                 return TRUE;
    01763             }
    01764
    01765             # a viewing privilege is set, so check if the user has it
    01766             else
    01767             {
    01768                 return $User->HasPriv($Field->ViewingPrivilege());
    01769             }
    01770         }
    01771
    01772         # an "user is value of field" constraint is set
    01773         else
    01774         {
    01775             $ViewingUserIsValue = $Field->ViewingUserIsValue();
    01776             $ViewingUserValue = $Field->ViewingUserValue();
    01777             $ViewingUserField = $Schema->GetField($ViewingUserValue);
    01778             $ViewingUserFieldValue = $this->Get($ViewingUserField);
    01779
    01780             # no viewing privilege is set, so only check the constraint
    01781             if ($Field->ViewingPrivilege() == 0)
    01782             {
    01783                 # just check if the user is the value of the field
    01784                 return $ViewingUserFieldValue == $User->Name();
    01785             }
    01786
    01787             # a viewing privilege is set, so check the privilege and constraint
    01788             else
    01789             {
    01790                 # OR user is value of field
    01791                 if ($ViewingUserIsValue == MetadataField::USERISVALUE_OR)
    01792                 {
    01793                     # user is value of the field, so short circuit
    01794                     if ($ViewingUserFieldValue == $User->Name())
    01795                     {
    01796                         return TRUE;
    01797                     }
    01798                 }
    01799
    01800                 # AND user is value of field constraint, but user isn't the
    01801                 # value, so short circuit
    01802                 else if ($ViewingUserFieldValue != $User->Name())
    01803                 {
    01804                     return FALSE;
    01805                 }
    01806
    01807                 # finally, if the logic hasn't been short circuited, check if
    01808                 # the user has the viewing privilege
    01809                 return $User->HasPriv($Field->ViewingPrivilege());
    01810             }
    01811         }
    01812     }
    01813
    01814     # report whether user can author the specified field
    01815     function UserCanAuthorField($User, $FieldOrFieldName)
    01816     {
    01817         $Schema = new MetadataSchema();
    01818
    01819         # get field (if not supplied)
    01820         if (is_object($FieldOrFieldName)
    01821                 && ($FieldOrFieldName instanceof MetadataField))
    01822         {
    01823             $Field = $FieldOrFieldName;
    01824         }
    01825         elseif (strlen(trim($FieldOrFieldName)))
    01826         {
    01827             if ($Schema->FieldExists($FieldOrFieldName))
    01828             {
    01829                 $Field = $Schema->GetFieldByName($FieldOrFieldName);
    01830             }
    01831         }
    01832
    01833         # the field must be valid and enabled to be viewable
    01834         if (!isset($Field) || !$Field->Enabled())
    01835         {
    01836             return FALSE;
    01837         }
    01838
    01839         # the user would have had to add the resource to be its author
    01840         if ($User->Name() != $this->Get("Added By Id"))
    01841         {
    01842             return FALSE;
    01843         }
    01844
    01845         # an "user is value of field" constraint isn't set, so only worry about
    01846         # the authoring privilege
    01847         if ($Field->AuthoringUserIsValue() == MetadataField::USERISVALUE_UNSET)
    01848         {
    01849             # no authoring privilege is set, so anyone can author the field
    01850             if ($Field->AuthoringPrivilege() == 0)
    01851             {
    01852                 return TRUE;
    01853             }
    01854
    01855             # an authoring privilege is set, so check if the user has it
    01856             else
    01857             {
    01858                 return $User->HasPriv($Field->AuthoringPrivilege());
    01859             }
    01860         }
    01861
    01862         # an "user is value of field" constraint is set
    01863         else
    01864         {
    01865             $AuthoringUserIsValue = $Field->AuthoringUserIsValue();
    01866             $AuthoringUserValue = $Field->AuthoringUserValue();
    01867             $AuthoringUserField = $Schema->GetField($AuthoringUserValue);
    01868             $AuthoringUserFieldValue = $this->Get($AuthoringUserField);
    01869
    01870             # no authoring privilege is set, so only check the constraint
    01871             if ($Field->AuthoringPrivilege() == 0)
    01872             {
    01873                 # just check if the user is the value of the field
    01874                 return $AuthoringUserFieldValue == $User->Name();
    01875             }
    01876
    01877             # an authoring privilege is set, so check the privilege and
    01878             # constraint
    01879             else
    01880             {
    01881                 # OR user is value of field
    01882                 if ($AuthoringUserIsValue == MetadataField::USERISVALUE_OR)
    01883                 {
    01884                     # user is value of the field, so short circuit
    01885                     if ($AuthoringUserFieldValue == $User->Name())
    01886                     {
    01887                         return TRUE;
    01888                     }
    01889                 }
    01890
    01891                 # AND user is value of field constraint, but user isn't the
    01892                 # value, so short circuit
    01893                 else if ($AuthoringUserFieldValue != $User->Name())
    01894                 {
    01895                     return FALSE;
    01896                 }
    01897
    01898                 # finally, if the logic hasn't been short circuited, check if
    01899                 # the user has the authoring privilege
    01900                 return $User->HasPriv($Field->AuthoringPrivilege());
    01901             }
    01902         }
    01903     }
    01904
    01905     # report whether user can author or edit the specified field
    01906     function UserCanEditField($User, $FieldOrFieldName)
    01907     {
    01908         $Schema = new MetadataSchema();
    01909
    01910         # fields hard-coded to be not allow edits
    01911         $UneditableFields = array(
    01912             "Cumulative Rating",
    01913             "Date Of Record Creation",
    01914             "Date Of Record Release",
    01915             "Date Last Modified",
    01916             "Last Modified By Id");
    01917
    01918         # get field (if not supplied)
    01919         if (is_object($FieldOrFieldName)
    01920                 && ($FieldOrFieldName instanceof MetadataField))
    01921         {
    01922             $Field = $FieldOrFieldName;
    01923         }
    01924         elseif (strlen(trim($FieldOrFieldName)))
    01925         {
    01926             if ($Schema->FieldExists($FieldOrFieldName))
    01927             {
    01928                 $Field = $Schema->GetFieldByName($FieldOrFieldName);
    01929             }
    01930         }
    01931
    01932         # the field must be valid and enabled to be editable
    01933         if (!isset($Field) || !$Field->Enabled())
    01934         {
    01935             return FALSE;
    01936         }
    01937
    01938         # if field name does not appear on "no edit" list
    01939         if (in_array($Field->Name(), $UneditableFields))
    01940         {
    01941             return FALSE;
    01942         }
    01943
    01944         # if the user can author the field, they can also edit it implicitly
    01945         if ($this->UserCanAuthorField($User, $Field))
    01946         {
    01947             return TRUE;
    01948         }
    01949
    01950         # an "user is value of field" constraint isn't set, so only worry about
    01951         # the editing privilege
    01952         if ($Field->EditingUserIsValue() == MetadataField::USERISVALUE_UNSET)
    01953         {
    01954             # no editing privilege is set, so anyone can author the field
    01955             if ($Field->EditingPrivilege() == 0)
    01956             {
    01957                 return TRUE;
    01958             }
    01959
    01960             # an editing privilege is set, so check if the user has it
    01961             else
    01962             {
    01963                 return $User->HasPriv($Field->EditingPrivilege());
    01964             }
    01965         }
    01966
    01967         # an "user is value of field" constraint is set
    01968         else
    01969         {
    01970             $EditingUserIsValue = $Field->EditingUserIsValue();
    01971             $EditingUserValue = $Field->EditingUserValue();
    01972             $EditingUserField = $Schema->GetField($EditingUserValue);
    01973             $EditingUserFieldValue = $this->Get($EditingUserField);
    01974
    01975             # no editing privilege is set, so only check the constraint
    01976             if ($Field->EditingPrivilege() == 0)
    01977             {
    01978                 # just check if the user is the value of the field
    01979                 return $EditingUserFieldValue == $User->Name();
    01980             }
    01981
    01982             # an editing privilege is set, so check the privilege and
    01983             # constraint
    01984             else
    01985             {
    01986                 # OR user is value of field
    01987                 if ($EditingUserIsValue == MetadataField::USERISVALUE_OR)
    01988                 {
    01989                     # user is value of the field, so short circuit
    01990                     if ($EditingUserFieldValue == $User->Name())
    01991                     {
    01992                         return TRUE;
    01993                     }
    01994                 }
    01995
    01996                 # AND user is value of field constraint, but user isn't the
    01997                 # value, so short circuit
    01998                 else if ($EditingUserFieldValue != $User->Name())
    01999                 {
    02000                     return FALSE;
    02001                 }
    02002
    02003                 # finally, if the logic hasn't been short circuited, check if
    02004                 # the user has the editing privilege
    02005                 return $User->HasPriv($Field->EditingPrivilege());
    02006             }
    02007         }
    02008     }
    02009
    02010     # ---- PRIVATE INTERFACE -------------------------------------------------
    02011
    02012     private $DB;
    02013     private $Schema;
    02014     private $DBFields;
    02015     private $Id;
    02016     private $NumberOfRatings;
    02017     private $CumulativeRating;
    02018     private $NumberOfComments;
    02019     private $Comments;
    02020     private $LastStatus;
    02021     private $ControlledNameCache;
    02022     private $ControlledNameVariantCache;
    02023     private $ClassificationCache;
    02024
    02025     # recalculate and save cumulative rating value for resource
    02026     private function UpdateCumulativeRating()
    02027     {
    02028         # grab totals from DB
    02029         $this->DB->Query("SELECT COUNT(Rating) AS Count, "
    02030                 ."SUM(Rating) AS Total FROM ResourceRatings "
    02031                 ."WHERE ResourceId = ".$this->Id);
    02032         $Record = $this->DB->FetchRow();
    02033
    02034         # calculate new cumulative rating
    02035         $this->CumulativeRating = round($Record["Total"] / $Record["Count"]);
    02036
    02037         # save new cumulative rating in DB
    02038         $this->DB->Query("UPDATE Resources "
    02039                 ."SET CumulativeRating = ".$this->CumulativeRating." "
    02040                 ."WHERE ResourceId = ".$this->Id);
    02041     }
    02042
    02043     # add intersection if not already present
    02044     private function AddAssociation($TableName, $TargetFieldName, $TargetValue)
    02045     {
    02046         # if target not already associated with resource
    02047         if ($this->DB->Query("SELECT COUNT(*) AS RecordCount FROM ".$TableName
    02048                    ." WHERE ResourceId = ".$this->Id
    02049                    ." AND ".$TargetFieldName." = '".$TargetValue."'",
    02050                    "RecordCount") == 0)
    02051         {
    02052             # associate target with resource
    02053             $this->DB->Query("INSERT INTO ".$TableName." SET"
    02054                        ." ResourceId = ".$this->Id
    02055                        .", ".$TargetFieldName." = '".$TargetValue."'");
    02056         }
    02057     }
    02058
    02059     # remove intersections (if any)
    02060     private function RemoveAssociation($TableName, $TargetFieldName, $TargetValue)
    02061     {
    02062         # remove any intersections with target ID from DB
    02063         $this->DB->Query("DELETE FROM ".$TableName
    02064                          ." WHERE ResourceId = ".$this->Id
    02065                          ." AND ".$TargetFieldName." = '".$TargetValue."'");
    02066     }
    02067
    02068     # remove all intersections for resource and field (if any)
    02069     private function RemoveAllAssociations($TableName, $TargetFieldName, $Field)
    02070     {
    02071         # retrieve list of entries for this field and resource
    02072         $Entries = $this->Get($Field);
    02073
    02074         # for each entry
    02075         foreach ($Entries as $EntryId => $EntryName)
    02076         {
    02077             # remove intersection
    02078             $this->RemoveAssociation($TableName, $TargetFieldName, $EntryId);
    02079         }
    02080     }
    02081 }