Resource.php

Go to the documentation of this file.
00001 <?PHP
00002 
00003 #
00004 #   FILE:  SPT--Resource.php
00005 #
00006 #   AUTHOR:  Edward Almasy
00007 #
00008 #   Part of the Collection Workflow Integration System (CWIS)
00009 #   Copyright 2002-2009 Internet Scout
00010 #   http://scout.wisc.edu
00011 #
00012 
00016 class Resource {
00017 
00018     # ---- PUBLIC INTERFACE --------------------------------------------------
00019 
00020     # object constructor (creates temp resource if no resource ID supplied)
00021 
00025     function Resource($ResourceId = NULL)
00026     {
00027         $this->DB = new SPTDatabase();
00028         $DB = $this->DB;
00029         $this->Schema = new MetadataSchema();
00030 
00031         # if resource ID supplied
00032         if ($ResourceId !== NULL)
00033         {
00034             # save resource ID
00035             $this->Id = intval($ResourceId);
00036 
00037             # locate resource in database
00038             $DB->Query("SELECT * FROM Resources WHERE ResourceId = ".$this->Id);
00039 
00040             # if unable to locate resource
00041             $Record = $DB->FetchRow();
00042             if ($Record == FALSE)
00043             {
00044                 # set status to -1 to indicate that creation failed
00045                 $this->LastStatus = -1;
00046             }
00047             else
00048             {
00049                 # load in attributes from database
00050                 $this->DBFields = $Record;
00051                 $this->CumulativeRating = $Record["CumulativeRating"];
00052 
00053                 # set status to 1 to indicate that creation succeeded
00054                 $this->LastStatus = 1;
00055             }
00056         }
00057         else
00058         {
00059             # lock DB tables to prevent next ID from being grabbed
00060             $DB->Query(
00061                 "LOCK TABLES Resources write, APUsers read, ".
00062                 "APSessions write, APSessionData write");
00063 
00064             # find next temp resource ID
00065             $Factory = new ResourceFactory();
00066             $this->Id = $Factory->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_FLAG
00089                     |MetadataSchema::MDFTYPE_NUMBER
00090                     |MetadataSchema::MDFTYPE_POINT);
00091             foreach ($Fields as $Field)
00092             {
00093                 $this->SetByField($Field, $Field->DefaultValue());
00094             }
00095 
00096             # Update timestamps as required:
00097             $TimestampFields = $Schema->GetFields(
00098                 MetadataSchema::MDFTYPE_TIMESTAMP);
00099             foreach ($TimestampFields as $Field)
00100             {
00101                 if ($Field->UpdateMethod() ==
00102                     MetadataField::UPDATEMETHOD_ONRECORDCREATE)
00103                 {
00104                     $this->SetByField($Field, "now");
00105                 }
00106             }
00107 
00108             # set status to 1 to indicate that creation succeeded
00109             $this->LastStatus = 1;
00110         }
00111     }
00112 
00116     function Delete()
00117     {
00118         global $SysConfig;
00119 
00120         # signal that resource deletion is about to occur
00121         global $AF;
00122         $AF->SignalEvent("EVENT_RESOURCE_DELETE", array(
00123                 "Resource" => $this,
00124                 ));
00125 
00126         # grab list of classifications
00127         $Classifications = $this->Classifications();
00128 
00129         # delete resource/classification intersections
00130         $DB = $this->DB;
00131         $DB->Query("DELETE FROM ResourceClassInts WHERE ResourceId = ".$this->Id());
00132 
00133         # for each classification type
00134         foreach ($Classifications as $ClassType => $ClassesOfType)
00135         {
00136             # for each classification of that type
00137             foreach ($ClassesOfType as $ClassId => $ClassName)
00138             {
00139                 # recalculate resource count for classification
00140                 $Class = new Classification($ClassId);
00141                 $Class->RecalcResourceCount();
00142             }
00143         }
00144 
00145         # delete resource/name intersections
00146         $DB->Query("DELETE FROM ResourceNameInts WHERE ResourceId = ".$this->Id());
00147 
00148         # delete any associated images not in use by other resources
00149         $Fields = $this->Schema->GetFields(MetadataSchema::MDFTYPE_IMAGE);
00150         foreach ($Fields as $Field)
00151         {
00152             $ImageId = $DB->Query("SELECT `".$Field->DBFieldName()
00153                                   ."` FROM Resources WHERE ResourceId = ".$this->Id(),
00154                                   $Field->DBFieldName());
00155             if ($ImageId > 0)
00156             {
00157                 $ImageCount = $DB->Query("SELECT COUNT(*) AS ImageCount FROM Resources"
00158                                          ." WHERE ".$Field->DBFieldName()." = ".$ImageId,
00159                                          "ImageCount");
00160                 if ($ImageCount < 2)
00161                 {
00162                     $Image = new SPTImage($ImageId);
00163                     $Image->Delete();
00164                 }
00165             }
00166         }
00167 
00168         # delete any associated files
00169         $Factory = new FileFactory(NULL);
00170         $Files = $Factory->GetFilesForResource($this->Id());
00171         foreach ($Files as $File)
00172         {
00173             $File->Delete();
00174         }
00175 
00176         # delete resource record from database
00177         $DB->Query("DELETE FROM Resources WHERE ResourceId = ".$this->Id());
00178 
00179         # drop item from search engine and recommender system
00180         if ($SysConfig->SearchDBEnabled())
00181         {
00182             $SearchEngine = new SPTSearchEngine();
00183             $SearchEngine->DropItem($this->Id());
00184         }
00185         if ($SysConfig->RecommenderDBEnabled())
00186         {
00187             $Recommender = new SPTRecommender();
00188             $Recommender->DropItem($this->Id());
00189         }
00190 
00191         # delete any resource comments
00192         $DB->Query("DELETE FROM Messages WHERE ParentId = ".$this->Id);
00193     }
00194 
00199     function Status() {  return $this->LastStatus;  }
00200 
00205     function Id() {  return $this->Id;  }
00206 
00212     function IsTempResource($NewSetting = NULL)
00213     {
00214         # if new temp resource setting supplied
00215         if (!is_null($NewSetting))
00216         {
00217             # if caller requested to switch
00218             $DB = $this->DB;
00219             if ((($this->Id() < 0) && ($NewSetting == FALSE))
00220                     || (($this->Id() >= 0) && ($NewSetting == TRUE)))
00221             {
00222                 # lock DB tables to prevent next ID from being grabbed
00223                 $DB->Query("LOCK TABLES Resources write");
00224 
00225                 # get next resource ID as appropriate
00226                 $OldResourceId = $this->Id;
00227                 $Factory = new ResourceFactory();
00228                 if ($NewSetting == TRUE)
00229                 {
00230                     $this->Id = $Factory->GetNextTempItemId();
00231                 }
00232                 else
00233                 {
00234                     $this->Id = $Factory->GetNextItemId();
00235                 }
00236 
00237                 # change resource ID
00238                 $DB->Query("UPDATE Resources SET ResourceId = ".
00239                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
00240 
00241                 # release DB tables
00242                 $DB->Query("UNLOCK TABLES");
00243 
00244                 # change associations
00245                 unset($this->ClassificationCache);
00246                 $DB->Query("UPDATE ResourceClassInts SET ResourceId = ".
00247                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
00248                 unset($this->ControlledNameCache);
00249                 unset($this->ControlledNameVariantCache);
00250                 $DB->Query("UPDATE ResourceNameInts SET ResourceId = ".
00251                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
00252                 $DB->Query("UPDATE Files SET ResourceId = ".
00253                     $this->Id.  " WHERE ResourceId = ".$OldResourceId);
00254 
00255                 # signal event as appropriate
00256                 if ($NewSetting === FALSE)
00257                 {
00258                     global $AF;
00259                     $AF->SignalEvent("EVENT_RESOURCE_ADD", array(
00260                             "Resource" => $this,
00261                             ));
00262                 }
00263             }
00264         }
00265 
00266         # report to caller whether we are a temp resource
00267         return ($this->Id() < 0) ? TRUE : FALSE;
00268     }
00269 
00270 
00271     # --- Generic Attribute Retrieval Methods -------------------------------
00272 
00287     function Get($FieldNameOrObject, $ReturnObject = FALSE, $IncludeVariants = FALSE)
00288     {
00289         # load field object if needed
00290         $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
00291                 : $this->Schema->GetFieldByName($FieldNameOrObject);
00292 
00293         # return no value found if we don't have a valid field
00294         if ((get_class($Field) != "MetadataField")
00295                 || ($Field->Status() != MetadataSchema::MDFSTAT_OK))
00296                 {  return NULL;  }
00297 
00298         # grab database field name
00299         $DBFieldName = $Field->DBFieldName();
00300 
00301         # format return value based on field type
00302         switch ($Field->Type())
00303         {
00304             case MetadataSchema::MDFTYPE_TEXT:
00305             case MetadataSchema::MDFTYPE_PARAGRAPH:
00306             case MetadataSchema::MDFTYPE_NUMBER:
00307             case MetadataSchema::MDFTYPE_FLAG:
00308             case MetadataSchema::MDFTYPE_URL:
00309                 if (isset($this->DBFields[$DBFieldName]))
00310                 {
00311                     $ReturnValue = $this->DBFields[$DBFieldName];
00312                 }
00313                 else
00314                 {
00315                     $ReturnValue = NULL;
00316                 }
00317                 break;
00318 
00319             case MetadataSchema::MDFTYPE_POINT:
00320                 $ReturnValue = array("X" => $this->DBFields[$DBFieldName."X"],
00321                                      "Y" => $this->DBFields[$DBFieldName."Y"]);
00322                 break;
00323 
00324             case MetadataSchema::MDFTYPE_DATE:
00325                 $Date = new Date($this->DBFields[$DBFieldName."Begin"],
00326                                     $this->DBFields[$DBFieldName."End"],
00327                                     $this->DBFields[$DBFieldName."Precision"]);
00328                 if ($ReturnObject)
00329                 {
00330                     $ReturnValue = $Date;
00331                 }
00332                 else
00333                 {
00334                     $ReturnValue = $Date->Formatted();
00335                 }
00336                 break;
00337 
00338             case MetadataSchema::MDFTYPE_TIMESTAMP:
00339                 $ReturnValue = $this->DBFields[$DBFieldName];
00340                 break;
00341 
00342             case MetadataSchema::MDFTYPE_TREE:
00343                 # start with empty array
00344                 $ReturnValue = array();
00345 
00346                 # if classification cache has not been loaded
00347                 if (!isset($this->ClassificationCache))
00348                 {
00349                     # load all classifications associated with this resource into cache
00350                     $this->ClassificationCache = array();
00351                     $this->DB->Query("SELECT Classifications.ClassificationId,Classifications.FieldId,ClassificationName "
00352                             ."FROM ResourceClassInts, Classifications  "
00353                             ."WHERE ResourceClassInts.ResourceId = ".$this->Id." "
00354                             ."AND ResourceClassInts.ClassificationId = Classifications.ClassificationId ");
00355                     while ($Record = $this->DB->FetchRow())
00356                     {
00357                         $this->ClassificationCache[$Record["ClassificationId"]]["Name"] =
00358                                 $Record["ClassificationName"];
00359                         $this->ClassificationCache[$Record["ClassificationId"]]["FieldId"] =
00360                                 $Record["FieldId"];
00361                     }
00362                 }
00363 
00364                 # for each entry in classification cache
00365                 foreach ($this->ClassificationCache as $ClassificationId => $ClassificationInfo)
00366                 {
00367                     # if classification ID matches field we are looking for
00368                     if ($ClassificationInfo["FieldId"] == $Field->Id())
00369                     {
00370                         # add field to result
00371                         if ($ReturnObject)
00372                         {
00373                             $ReturnValue[$ClassificationId] = new Classification($ClassificationId);
00374                         }
00375                         else
00376                         {
00377                             $ReturnValue[$ClassificationId] = $ClassificationInfo["Name"];
00378                         }
00379                     }
00380                 }
00381                 break;
00382 
00383             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00384             case MetadataSchema::MDFTYPE_OPTION:
00385                 # start with empty array
00386                 $ReturnValue = array();
00387 
00388                 # if controlled name cache has not been loaded
00389                 if (!isset($this->ControlledNameCache))
00390                 {
00391                     # load all controlled names associated with this resource into cache
00392                     $this->ControlledNameCache = array();
00393                     $this->DB->Query("SELECT ControlledNames.ControlledNameId,ControlledNames.FieldId,ControlledName "
00394                             ."FROM ResourceNameInts, ControlledNames  "
00395                             ."WHERE ResourceNameInts.ResourceId = ".$this->Id." "
00396                             ."AND ResourceNameInts.ControlledNameId = ControlledNames.ControlledNameId ");
00397                     while ($Record = $this->DB->FetchRow())
00398                     {
00399                         $this->ControlledNameCache[$Record["ControlledNameId"]]["Name"] = $Record["ControlledName"];
00400                         $this->ControlledNameCache[$Record["ControlledNameId"]]["FieldId"] = $Record["FieldId"];
00401                     }
00402                 }
00403 
00404                 # if variant names requested and variant name cache has not been loaded
00405                 if ($IncludeVariants && !isset($this->ControlledNameVariantCache))
00406                 {
00407                     # load all controlled names associated with this resource into cache
00408                     $this->ControlledNameVariantCache = array();
00409                     $this->DB->Query("SELECT ControlledNames.ControlledNameId,ControlledNames.FieldId,ControlledName,VariantName "
00410                             ."FROM ResourceNameInts, ControlledNames, VariantNames  "
00411                             ."WHERE ResourceNameInts.ResourceId = ".$this->Id." "
00412                             ."AND ResourceNameInts.ControlledNameId = ControlledNames.ControlledNameId "
00413                             ."AND VariantNames.ControlledNameId = ControlledNames.ControlledNameId");
00414                     while ($Record = $this->DB->FetchRow())
00415                     {
00416                         $this->ControlledNameVariantCache[$Record["ControlledNameId"]][] = $Record["VariantName"];
00417                     }
00418                 }
00419 
00420                 # for each entry in controlled name cache
00421                 foreach ($this->ControlledNameCache as $ControlledNameId => $ControlledNameInfo)
00422                 {
00423                     # if controlled name type matches field we are looking for
00424                     if ($ControlledNameInfo["FieldId"] == $Field->Id())
00425                     {
00426                         # if objects requested
00427                         if ($ReturnObject)
00428                         {
00429                             $ReturnValue[$ControlledNameId] =
00430                                     new ControlledName($ControlledNameId);
00431                         }
00432                         else
00433                         {
00434                             # if variant names requested
00435                             if ($IncludeVariants)
00436                             {
00437                                 # add field to result
00438                                 $ReturnValue[] = $ControlledNameInfo["Name"];
00439 
00440                                 # add any variant names to result
00441                                 if (isset($this->ControlledNameVariantCache[$ControlledNameId]))
00442                                 {
00443                                     $ReturnValue = array_merge($ReturnValue, $this->ControlledNameVariantCache[$ControlledNameId]);
00444                                 }
00445                             }
00446                             else
00447                             {
00448                                 # add field with index to result
00449                                 $ReturnValue[$ControlledNameId] = $ControlledNameInfo["Name"];
00450                             }
00451                         }
00452                     }
00453                 }
00454                 break;
00455 
00456             case MetadataSchema::MDFTYPE_USER:
00457                 $User = new User($this->DB, (int)$this->DBFields[$DBFieldName]);
00458                 if ($ReturnObject)
00459                 {
00460                     $ReturnValue = $User;
00461                 }
00462                 else
00463                 {
00464                     $ReturnValue = $User->Get("UserName");
00465                 }
00466                 break;
00467 
00468             case MetadataSchema::MDFTYPE_IMAGE:
00469                 if ($this->DBFields[$DBFieldName] > 0)
00470                 {
00471                     $ImageObject = new SPTImage($this->DBFields[$DBFieldName]);
00472                     if ($ReturnObject)
00473                     {
00474                         $ReturnValue = $ImageObject;
00475                     }
00476                     else
00477                     {
00478                         $ReturnValue = $ImageObject->AltText();
00479                     }
00480                 }
00481                 else
00482                 {
00483                     $ReturnValue = NULL;
00484                 }
00485                 break;
00486 
00487             case MetadataSchema::MDFTYPE_FILE:
00488                 # retrieve files using factory
00489                 $Factory = new FileFactory($Field->Id());
00490                 $ReturnValue = $Factory->GetFilesForResource(
00491                         $this->Id, $ReturnObject);
00492                 break;
00493 
00494             default:
00495                 # ERROR OUT
00496                 exit("<br>SPT - ERROR: attempt to retrieve unknown resource field type (".$Field->Type().")<br>\n");
00497                 break;
00498         }
00499 
00500         # return formatted value to caller
00501         return $ReturnValue;
00502     }
00507     function GetByField($FieldNameOrObject,
00508             $ReturnObject = FALSE, $IncludeVariants = FALSE)
00509     {  return $this->Get($FieldNameOrObject, $ReturnObject, $IncludeVariants);  }
00510 
00524     function GetByFieldId($FieldId, $ReturnObject = FALSE, $IncludeVariants = FALSE)
00525     {
00526         $Field = $this->Schema->GetField($FieldId);
00527         return ($Field) ? $this->Get($Field, $ReturnObject, $IncludeVariants) : NULL;
00528     }
00529 
00530     # return all resource attributes as an array
00531     function GetAsArray($IncludeDisabledFields = FALSE, $ReturnObjects = TRUE)
00532     {
00533         # retrieve field info
00534         $Fields = $this->Schema->GetFields();
00535 
00536         # for each field
00537         foreach ($Fields as $Field)
00538         {
00539             # if field is enabled or caller requested disabled fields
00540             if ($Field->Enabled() || $IncludeDisabledFields)
00541             {
00542                 # retrieve info and add it to the array
00543                 $FieldStrings[$Field->Name()] = $this->Get($Field, $ReturnObjects);
00544 
00545                 # if field uses qualifiers
00546                 if ($Field->UsesQualifiers())
00547                 {
00548                     # get qualifier attributes and add to the array
00549                     $FieldStrings[$Field->Name()." Qualifier"] =
00550                             $this->GetQualifierByField($Field, $ReturnObjects);
00551                 }
00552             }
00553         }
00554 
00555         # add in internal values
00556         $FieldStrings["ResourceId"] = $this->Id();
00557         $FieldStrings["CumulativeRating"] = $this->CumulativeRating();
00558 
00559         # return array to caller
00560         return $FieldStrings;
00561     }
00562 
00577     function GetMapped($MappedName, $ReturnObject = FALSE, $IncludeVariants = FALSE)
00578     {
00579         return $this->Schema->StdNameToFieldMapping($MappedName)
00580                 ? $this->GetByFieldId($this->Schema->StdNameToFieldMapping($MappedName),
00581                         $ReturnObject, $IncludeVariants)
00582                 : NULL;
00583     }
00584 
00591     function GetQualifier($FieldName, $ReturnObject = TRUE)
00592     {
00593         $Field = $this->Schema->GetFieldByName($FieldName);
00594         return $this->GetQualifierByField($Field, $ReturnObject);
00595     }
00596 
00603     function GetQualifierByFieldId($FieldId, $ReturnObject = TRUE)
00604     {
00605         $Field = $this->Schema->GetField($FieldId);
00606         return $this->GetQualifierByField($Field, $ReturnObject);
00607     }
00608 
00617     function GetQualifierByField($Field, $ReturnObject = TRUE)
00618     {
00619         # return NULL if field is invalid
00620         if ((get_class($Field) != "MetadataField")
00621                 || ($Field->Status() != MetadataSchema::MDFSTAT_OK))
00622                 {  return NULL;  }
00623 
00624         # assume no qualifiers if not otherwise determined
00625         $ReturnValue = NULL;
00626 
00627         # if field uses qualifiers
00628         if ($Field->UsesQualifiers())
00629         {
00630             # retrieve qualifiers based on field type
00631             switch ($Field->Type())
00632             {
00633                 case MetadataSchema::MDFTYPE_TREE:
00634                 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00635                 case MetadataSchema::MDFTYPE_OPTION:
00636                     # retrieve list of items
00637                     $Items = $this->Get($Field);
00638 
00639                     # if field uses item-level qualifiers
00640                     if ($Field->HasItemLevelQualifiers())
00641                     {
00642                         # determine general item name in DB
00643                         $TableName = ($Field->Type() == MetadataSchema::MDFTYPE_TREE)
00644                                 ? "Classification" : "ControlledName";
00645 
00646                         # for each item
00647                         foreach ($Items as $ItemId => $ItemName)
00648                         {
00649                             # look up qualifier for item
00650                             $QualId = $this->DB->Query(
00651                                     "SELECT * FROM ".$TableName."s"
00652                                     ." WHERE ".$TableName."Id = ".$ItemId
00653                                     , "QualifierId");
00654 
00655 
00656                             if ($QualId > 0)
00657                             {
00658                                 # if object was requested by caller
00659                                 if ($ReturnObject)
00660                                 {
00661                                     # load qualifier and add to return value array
00662                                     $ReturnValue[$ItemId] = new Qualifier($QualId);
00663                                 }
00664                                 else
00665                                 {
00666                                     # add qualifier ID to return value array
00667                                     $ReturnValue[$ItemId] = $QualId;
00668                                 }
00669                             }
00670                             else
00671                             {
00672                                 # add NULL to return value array for this item
00673                                 $ReturnValue[$ItemId] = NULL;
00674                             }
00675                         }
00676                     }
00677                     else
00678                     {
00679                         # for each item
00680                         foreach ($Items as $ItemId => $ItemName)
00681                         {
00682                             # if object was requested by caller
00683                             if ($ReturnObject)
00684                             {
00685                                 # load default qualifier and add to return value array
00686                                 $ReturnValue[$ItemId] = new Qualifier($Field->DefaultQualifier());
00687                             }
00688                             else
00689                             {
00690                                 # add default qualifier ID to return value array
00691                                 $ReturnValue[$ItemId] = $Field->DefaultQualifier();
00692                             }
00693                         }
00694                     }
00695                     break;
00696 
00697                 default:
00698                     # if field uses item-level qualifiers
00699                     if ($Field->HasItemLevelQualifiers())
00700                     {
00701                         # if qualifier available
00702                         if ($this->DBFields[$Field->DBFieldName()."Qualifier"] > 0)
00703                         {
00704                             # if object was requested by caller
00705                             if ($ReturnObject)
00706                             {
00707                                 # return qualifier for field
00708                                 $ReturnValue = new Qualifier($this->DBFields[$Field->DBFieldName()."Qualifier"]);
00709                             }
00710                             else
00711                             {
00712                                 # return qualifier ID for field
00713                                 $ReturnValue = $this->DBFields[$Field->DBFieldName()."Qualifier"];
00714                             }
00715                         }
00716                     }
00717                     else
00718                     {
00719                         # if default qualifier available
00720                         if ($Field->DefaultQualifier() > 0)
00721                         {
00722                             # if object was requested by caller
00723                             if ($ReturnObject)
00724                             {
00725                                 # return default qualifier
00726                                 $ReturnValue = new Qualifier($Field->DefaultQualifier());
00727                             }
00728                             else
00729                             {
00730                                 # return default qualifier ID
00731                                 $ReturnValue = $Field->DefaultQualifier();
00732                             }
00733                         }
00734                     }
00735                     break;
00736             }
00737         }
00738 
00739         # return qualifier object or ID (or array of same) to caller
00740         return $ReturnValue;
00741     }
00742 
00743 
00744     # --- Generic Attribute Setting Methods ---------------------------------
00745 
00746     # set value using field name or field object
00747     function Set($FieldNameOrObject, $NewValue)
00748     {
00749         # load field object if needed
00750         $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
00751                 : $this->Schema->GetFieldByName($FieldNameOrObject);
00752 
00753         # grab commonly-used values for local use
00754         $DB = $this->DB;
00755         $ResourceId = $this->Id;
00756 
00757         # grab database field name
00758         $DBFieldName = $Field->DBFieldName();
00759 
00760         # store value in DB based on field type
00761         switch ($Field->Type())
00762         {
00763             case MetadataSchema::MDFTYPE_TEXT:
00764             case MetadataSchema::MDFTYPE_PARAGRAPH:
00765             case MetadataSchema::MDFTYPE_URL:
00766                 # save value directly to DB
00767                 $DB->Query("UPDATE Resources SET `"
00768                            .$DBFieldName."` = '".addslashes($NewValue)."' "
00769                            ."WHERE ResourceId = ".$ResourceId);
00770 
00771                 # save value locally
00772                 $this->DBFields[$DBFieldName] = $NewValue;
00773                 break;
00774 
00775             case MetadataSchema::MDFTYPE_NUMBER:
00776                 # save value directly to DB
00777                 if (is_null($NewValue))
00778                 {
00779                     $DB->Query("UPDATE Resources SET `"
00780                            .$DBFieldName."` = NULL"
00781                            ." WHERE ResourceId = ".$ResourceId);
00782                 }
00783                 else
00784                 {
00785                     $DB->Query("UPDATE Resources SET `"
00786                            .$DBFieldName."` = ".intval($NewValue)
00787                            ." WHERE ResourceId = ".$ResourceId);
00788                 }
00789 
00790                 # save value locally
00791                 $this->DBFields[$DBFieldName] = $NewValue;
00792                 break;
00793 
00794 
00795             case MetadataSchema::MDFTYPE_POINT:
00796                 if (is_null($NewValue))
00797                 {
00798                     $DB->Query("UPDATE Resources SET "
00799                                ."`".$DBFieldName."X` = NULL, "
00800                                ."`".$DBFieldName."Y` = NULL "
00801                                ."WHERE ResourceId = ".$ResourceId);
00802                     $this->DBFields[$DBFieldName."X"] = NULL;
00803                     $this->DBFields[$DBFieldName."Y"] = NULL;
00804                 }
00805                 else
00806                 {
00807                     $DB->Query("UPDATE Resources SET "
00808                                ."`".$DBFieldName."X` = ".(strlen($NewValue["X"])
00809                                             ? "'".$NewValue["X"]."'" : "NULL").", "
00810                                ."`".$DBFieldName."Y` = ".(strlen($NewValue["Y"])
00811                                             ? "'".$NewValue["Y"]."'" : "NULL")
00812                                ." WHERE ResourceId = ".$ResourceId);
00813 
00814                     $Digits = $Field->PointDecimalDigits();
00815 
00816                     $this->DBFields[$DBFieldName."X"] =
00817                         strlen($NewValue["X"]) ? round($NewValue["X"], $Digits) : NULL;
00818                     $this->DBFields[$DBFieldName."Y"] =
00819                         strlen($NewValue["Y"]) ? round($NewValue["Y"], $Digits) : NULL;
00820                 }
00821                 break;
00822 
00823             case MetadataSchema::MDFTYPE_FLAG:
00824                 # save value directly to DB
00825                 if (is_null($NewValue))
00826                 {
00827                     $DB->Query("UPDATE Resources SET `"
00828                            .$DBFieldName."` = NULL"
00829                            ." WHERE ResourceId = ".$ResourceId);
00830                 }
00831                 else
00832                 {
00833                     $DB->Query("UPDATE Resources SET `"
00834                            .$DBFieldName."` = ".$NewValue
00835                            ." WHERE ResourceId = ".$ResourceId);
00836                 }
00837 
00838                 # save value locally
00839                 $OldValue = $this->DBFields[$DBFieldName];
00840                 $this->DBFields[$DBFieldName] = $NewValue;
00841 
00842                 # recalculate counts for any associated classifications if necessary
00843                 if (($DBFieldName == "ReleaseFlag") && ($NewValue != $OldValue))
00844                 {
00845                     $DB->Query("SELECT ClassificationId FROM ResourceClassInts WHERE ResourceId = ".$ResourceId);
00846                     while ($ClassId = $DB->FetchField("ClassificationId"))
00847                     {
00848                         $Class = new Classification($ClassId);
00849                         $Class->RecalcResourceCount();
00850                     }
00851                 }
00852                 break;
00853 
00854             case MetadataSchema::MDFTYPE_USER:
00855                 # if value passed in was object
00856                 if (is_object($NewValue))
00857                 {
00858                     # retrieve user ID from object
00859                     $UserId = $NewValue->Get("UserId");
00860                 }
00861                 # else if value passed in was user name
00862                 elseif (is_string($NewValue))
00863                 {
00864                     # create user object and retrieve user ID from there
00865                     $User = new User($this->DB, $NewValue);
00866                     $UserId = $User->Get("UserId");
00867                 }
00868                 else
00869                 {
00870                     # assume value is user ID and use value directly
00871                     $UserId = $NewValue;
00872                 }
00873 
00874                 # save value directly to DB
00875                 $DB->Query("UPDATE Resources SET `"
00876                            .$DBFieldName."` = '".$UserId."' "
00877                            ."WHERE ResourceId = ".$ResourceId);
00878 
00879                 # save value locally
00880                 $this->DBFields[$DBFieldName] = $UserId;
00881                 break;
00882 
00883             case MetadataSchema::MDFTYPE_DATE:
00884                 # if we were given a date object
00885                 if (is_object($NewValue))
00886                 {
00887                     # use supplied date object
00888                     $Date = $NewValue;
00889                 }
00890                 else
00891                 {
00892                     # create date object
00893                     $Date = new Date($NewValue);
00894                 }
00895 
00896                 # extract values from date object and store in DB
00897                 $BeginDate = "'".$Date->BeginDate()."'";
00898                 if (strlen($BeginDate) < 3) {  $BeginDate = "NULL";  }
00899                 $EndDate = "'".$Date->EndDate()."'";
00900                 if (strlen($EndDate) < 3) {  $EndDate = "NULL";  }
00901                 $DB->Query("UPDATE Resources SET "
00902                            .$DBFieldName."Begin = ".$BeginDate.", "
00903                            .$DBFieldName."End = ".$EndDate.", "
00904                            .$DBFieldName."Precision = '".$Date->Precision()."' "
00905                            ."WHERE ResourceId = ".$ResourceId);
00906 
00907                 # save values locally
00908                 $this->DBFields[$DBFieldName."Begin"] = $Date->BeginDate();
00909                 $this->DBFields[$DBFieldName."End"] = $Date->EndDate();
00910                 $this->DBFields[$DBFieldName."Precision"] = $Date->Precision();
00911                 break;
00912 
00913             case MetadataSchema::MDFTYPE_TIMESTAMP:
00914                 # assume value is date and use directly
00915                 $DateValue = date("Y-m-d H:i:s", strtotime($NewValue));
00916 
00917                 # save value directly to DB
00918                 $DB->Query("UPDATE Resources SET `"
00919                            .$DBFieldName."` = '".addslashes($DateValue)."' "
00920                            ."WHERE ResourceId = ".$ResourceId);
00921 
00922                 # save value locally
00923                 $this->DBFields[$DBFieldName] = $DateValue;
00924                 break;
00925 
00926             case MetadataSchema::MDFTYPE_TREE:
00927                 # if incoming value is array
00928                 if (is_array($NewValue))
00929                 {
00930                     # for each element of array
00931                     foreach ($NewValue as
00932                         $ClassificationId => $ClassificationName)
00933                     {
00934                         $Class = new Classification($ClassificationId);
00935                         if ($Class->Status() == Classification::CLASSSTAT_OK)
00936                         {
00937                             # associate with resource if not already associated
00938                             $this->AddAssociation("ResourceClassInts",
00939                                                   "ClassificationId",
00940                                                   $ClassificationId);
00941                             $Class->RecalcResourceCount();
00942                         }
00943                     }
00944                 }
00945                 else
00946                 {
00947                     # associate with resource if not already associated
00948                     if (is_object($NewValue))
00949                     {
00950                         $Class = $NewValue;
00951                         $NewValue = $Class->Id();
00952                     }
00953                     else
00954                     {
00955                         $Class = new Classification($NewValue);
00956                     }
00957                     $this->AddAssociation("ResourceClassInts",
00958                                           "ClassificationId",
00959                                           $NewValue);
00960                     $Class->RecalcResourceCount();
00961                 }
00962 
00963                 # clear our classification cache
00964                 unset($this->ClassificationCache);
00965                 break;
00966 
00967             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
00968             case MetadataSchema::MDFTYPE_OPTION:
00969                 # Clear other values if this field expects unique options
00970                 if ($Field->AllowMultiple() === FALSE)
00971                 {
00972                     $this->RemoveAllAssociations("ResourceNameInts",
00973                                                  "ControlledNameId",
00974                                                  $Field );
00975                 }
00976 
00977                 # if incoming value is array
00978                 if (is_array($NewValue) && ($Field->AllowMultiple() !== FALSE) )
00979                 {
00980                     # for each element of array
00981                     foreach ($NewValue as $ControlledNameId => $ControlledName)
00982                     {
00983                         # associate with resource if not already associated
00984                         $this->AddAssociation("ResourceNameInts",
00985                                               "ControlledNameId",
00986                                               $ControlledNameId);
00987                     }
00988                 }
00989                 else
00990                 {
00991                     # If we're fed an array for a unique option,
00992                     # just use the last element of the array
00993                     if (is_array($NewValue))
00994                     {
00995                         $NewValue = array_pop($NewValue);
00996                     }
00997 
00998                     # associate with resource if not already associated
00999                     if (is_object($NewValue)) {  $NewValue = $NewValue->Id();  }
01000                     $this->AddAssociation("ResourceNameInts",
01001                                           "ControlledNameId",
01002                                           $NewValue);
01003                 }
01004 
01005                 # clear our controlled name cache
01006                 unset($this->ControlledNameCache);
01007                 unset($this->ControlledNameVariantCache);
01008                 break;
01009 
01010             case MetadataSchema::MDFTYPE_IMAGE:
01011                 # if we were given an image object
01012                 if (is_object($NewValue))
01013                 {
01014                     # grab ID from object
01015                     $ImageId = $NewValue->Id();
01016                 }
01017                 else
01018                 {
01019                     # assume incoming value is ID
01020                     $ImageId = $NewValue;
01021                 }
01022 
01023                 # store new image object ID in database
01024                 $DB->Query("UPDATE Resources SET `"
01025                            .$DBFieldName."` = '".$ImageId."'"
01026                            ." WHERE ResourceId = ".$ResourceId);
01027 
01028                 # save value locally
01029                 $this->DBFields[$DBFieldName] = $ImageId;
01030                 break;
01031 
01032             case MetadataSchema::MDFTYPE_FILE:
01033                 # convert incoming value to array if necessary
01034                 if (!is_array($NewValue)) {  $NewValue = array($NewValue);  }
01035 
01036                 # for each incoming file
01037                 $Factory = new FileFactory($Field->Id());
01038                 foreach ($NewValue as $File)
01039                 {
01040                     # make copy of file
01041                     $NewFile = $Factory->Copy($File);
01042 
01043                     # associate copy with this resource and field
01044                     $NewFile->ResourceId($this->Id);
01045                     $NewFile->FieldId($Field->Id());
01046                 }
01047                 break;
01048 
01049             default:
01050                 # ERROR OUT
01051                 exit("<br>SPT - ERROR: attempt to set unknown resource field type<br>\n");
01052                 break;
01053         }
01054     }
01055     # (for backward compatibility)
01056     function SetByField($Field, $NewValue) {  return $this->Set($Field, $NewValue);  }
01057 
01058     # set value by field ID
01059     function SetByFieldId($FieldId, $NewValue)
01060     {
01061         $Field = $this->Schema->GetField($FieldId);
01062         return $this->Set($Field, $NewValue);
01063     }
01064 
01065     # set qualifier by field name
01066     function SetQualifier($FieldName, $NewValue)
01067     {
01068         $Field = $this->Schema->GetFieldByName($FieldName);
01069         return $this->SetQualifierByField($Field, $NewValue);
01070     }
01071 
01072     # set qualifier by field ID
01073     function SetQualifierByFieldId($FieldId, $NewValue)
01074     {
01075         $Field = $this->Schema->GetField($FieldId);
01076         return $this->SetQualifierByField($Field, $NewValue);
01077     }
01078 
01079     # set qualifier using field object
01080     function SetQualifierByField($Field, $NewValue)
01081     {
01082         # if field uses qualifiers and uses item-level qualifiers
01083         if ($Field->UsesQualifiers() && $Field->HasItemLevelQualifiers())
01084         {
01085             # if qualifier object passed in
01086             if (is_object($NewValue))
01087             {
01088                 # grab qualifier ID from object
01089                 $QualifierId = $NewValue->Id();
01090             }
01091             else
01092             {
01093                 # assume value passed in is qualifier ID
01094                 $QualifierId = $NewValue;
01095             }
01096 
01097             # update qualifier value in database
01098             $DBFieldName = $Field->DBFieldName();
01099             $this->DB->Query("UPDATE Resources SET "
01100                      .$DBFieldName."Qualifier = '".$QualifierId."' "
01101                      ."WHERE ResourceId = ".$this->Id);
01102 
01103             # update local qualifier value
01104             $this->DBFields[$DBFieldName."Qualifier"] = $QualifierId;
01105         }
01106     }
01107 
01108     # clear value by field name
01109     function Clear($FieldName, $ValueToClear = NULL)
01110     {
01111         $Field = $this->Schema->GetFieldByName($FieldName);
01112         return $this->ClearByField($Field, $ValueToClear);
01113     }
01114 
01115     # clear value by field ID
01116     function ClearByFieldId($FieldId, $ValueToClear = NULL)
01117     {
01118         $Field = $this->Schema->GetField($FieldId);
01119         return $this->ClearByField($Field, $ValueToClear);
01120     }
01121 
01122     # clear value using field object
01123     function ClearByField($Field, $ValueToClear = NULL)
01124     {
01125         # grab commonly-used values for local use
01126         $DB = $this->DB;
01127         $ResourceId = $this->Id;
01128 
01129         # grab database field name
01130         $DBFieldName = $Field->DBFieldName();
01131 
01132         # store value in DB based on field type
01133         switch ($Field->Type())
01134         {
01135             case MetadataSchema::MDFTYPE_TEXT:
01136             case MetadataSchema::MDFTYPE_PARAGRAPH:
01137             case MetadataSchema::MDFTYPE_NUMBER:
01138             case MetadataSchema::MDFTYPE_FLAG:
01139             case MetadataSchema::MDFTYPE_USER:
01140             case MetadataSchema::MDFTYPE_TIMESTAMP:
01141             case MetadataSchema::MDFTYPE_URL:
01142                 # clear value in DB
01143                 $DB->Query("UPDATE Resources SET `"
01144                            .$DBFieldName."` = '' "
01145                            ."WHERE ResourceId = ".$ResourceId);
01146 
01147                 # clear value locally
01148                 $this->DBFields[$DBFieldName] = NULL;
01149                 break;
01150 
01151             case MetadataSchema::MDFTYPE_POINT:
01152                 # Clear DB Values
01153                 $DB->Query("UPDATE Resources SET "
01154                            ."`".$DBFieldName."X` = NULL ,"
01155                            ."`".$DBFieldName."Y` = NULL "
01156                            ."WHERE ResourceId = ".$ResourceId);
01157 
01158                 # Clear local values
01159                 $this->DBFields[$DBFieldName."X"] = NULL;
01160                 $this->DBFields[$DBFieldName."Y"] = NULL;
01161                 break;
01162 
01163             case MetadataSchema::MDFTYPE_DATE:
01164                 # clear date object values in DB
01165                 $DB->Query("UPDATE Resources SET "
01166                            .$DBFieldName."Begin = '', "
01167                            .$DBFieldName."End = '', "
01168                            .$DBFieldName."Precision = '' "
01169                            ."WHERE ResourceId = ".$ResourceId);
01170 
01171                 # clear value locally
01172                 $this->DBFields[$DBFieldName."Begin"] = NULL;
01173                 $this->DBFields[$DBFieldName."End"] = NULL;
01174                 $this->DBFields[$DBFieldName."Precision"] = NULL;
01175                 break;
01176 
01177             case MetadataSchema::MDFTYPE_TREE:
01178                 # if value to clear supplied
01179                 if ($ValueToClear !== NULL)
01180                 {
01181                     # if supplied value is array
01182                     if (is_array($ValueToClear))
01183                     {
01184                         # for each element of array
01185                         foreach ($ValueToClear as $ClassificationId => $Dummy)
01186                         {
01187                             # remove association with resource (if any)
01188                             $this->RemoveAssociation("ResourceClassInts",
01189                                                   "ClassificationId",
01190                                                   $ClassificationId);
01191                             $Class = new Classification($ClassificationId);
01192                             $Class->RecalcResourceCount();
01193                         }
01194                     }
01195                     else
01196                     {
01197                         # remove association with resource (if any)
01198                         $this->RemoveAssociation("ResourceClassInts",
01199                                               "ClassificationId",
01200                                               $ValueToClear);
01201                         $Class = new Classification($ValueToClear);
01202                         $Class->RecalcResourceCount();
01203                     }
01204                 }
01205                 else
01206                 {
01207                     # remove all associations for resource and field
01208                     $this->RemoveAllAssociations("ResourceClassInts", "ClassificationId", $Field);
01209 
01210                     # recompute resource count
01211                     $Values = $this->Get($Field);
01212                     foreach ($Values as $ClassificationId => $Dummy)
01213                     {
01214                         $Class = new Classification($ClassificationId);
01215                         $Class->RecalcResourceCount();
01216                     }
01217                 }
01218 
01219                 # clear our classification cache
01220                 unset($this->ClassificationCache);
01221                 break;
01222 
01223             case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
01224             case MetadataSchema::MDFTYPE_OPTION:
01225                 # if value to clear supplied
01226                 if ($ValueToClear !== NULL)
01227                 {
01228                     # if incoming value is array
01229                     if (is_array($ValueToClear))
01230                     {
01231                         # for each element of array
01232                         foreach ($ValueToClear as $ControlledNameId =>
01233                             $ControlledName)
01234                         {
01235                             # remove association with resource (if any)
01236                             $this->RemoveAssociation("ResourceNameInts",
01237                                                   "ControlledNameId",
01238                                                   $ControlledNameId);
01239                         }
01240                     }
01241                     else
01242                     {
01243                         # remove association with resource (if any)
01244                         $this->RemoveAssociation("ResourceNameInts",
01245                                               "ControlledNameId",
01246                                               $ValueToClear);
01247                     }
01248                 }
01249                 else
01250                 {
01251                     # remove all associations for resource and field
01252                     $this->RemoveAllAssociations("ResourceNameInts", "ControlledNameId", $Field);
01253                 }
01254 
01255                 # clear our controlled name cache
01256                 unset($this->ControlledNameCache);
01257                 unset($this->ControlledNameVariantCache);
01258                 break;
01259 
01260             case MetadataSchema::MDFTYPE_IMAGE:
01261                 # delete image if no other resources are using it
01262                 $ImageId = $DB->Query("SELECT `".$DBFieldName
01263                                       ."` FROM Resources WHERE ResourceId = ".$ResourceId,
01264                                       $DBFieldName);
01265                 if ($ImageId > 0)
01266                 {
01267                     $ImageCount = $DB->Query("SELECT COUNT(*) AS ImageCount FROM Resources"
01268                                              ." WHERE `".$DBFieldName."` = ".$ImageId,
01269                                              "ImageCount");
01270                     if ($ImageCount < 2)
01271                     {
01272                         $Image = new SPTImage($ImageId);
01273                         $Image->Delete();
01274                     }
01275                 }
01276 
01277                 # clear stored ID
01278                 $DB->Query("UPDATE Resources SET `"
01279                            .$DBFieldName."` = '' "
01280                            ."WHERE ResourceId = ".$ResourceId);
01281 
01282                 # clear value locally
01283                 $this->DBFields[$DBFieldName] = NULL;
01284                 break;
01285 
01286             case MetadataSchema::MDFTYPE_FILE:
01287                 # get array of Files associated with this resource
01288                 $Files->Get($Field);
01289 
01290                 # for each File
01291                 foreach ($Files as $File)
01292                 {
01293                     # delete file
01294                     $File->Delete();
01295                 }
01296                 break;
01297 
01298             default:
01299                 # ERROR OUT
01300                 exit("<br>SPT - ERROR: attempt to clear unknown resource field type<br>\n");
01301                 break;
01302         }
01303     }
01304 
01305 
01306     # --- Field-Specific or Type-Specific Attribute Retrieval Methods -------
01307 
01308     # return 2D array of classifications associated with resource
01309     # (first index is classification (field) name, second index is classification ID)
01310     function Classifications()
01311     {
01312         $DB = $this->DB;
01313 
01314         # start with empty array
01315         $Names = array();
01316 
01317         # for each controlled name
01318         $DB->Query("SELECT ClassificationName, MetadataFields.FieldName, "
01319                 ."ResourceClassInts.ClassificationId FROM ResourceClassInts, "
01320                 ."Classifications, MetadataFields "
01321                 ."WHERE ResourceClassInts.ResourceId = ".$this->Id." "
01322                 ."AND ResourceClassInts.ClassificationId = Classifications.ClassificationId "
01323                 ."AND Classifications.FieldId = MetadataFields.FieldId ");
01324         while ($Record = $DB->FetchRow())
01325         {
01326             # add name to array
01327             $Names[$Record["FieldName"]][$Record["ClassificationId"]] =
01328                     $Record["ClassificationName"];
01329         }
01330 
01331         # return array to caller
01332         return $Names;
01333     }
01334 
01335 
01336     # --- Ratings Methods ---------------------------------------------------
01337 
01338     # return cumulative rating  (range is usually 0-100)
01339     function CumulativeRating() {  return $this->CumulativeRating;  }
01340 
01341     # return cumulative rating scaled to 1/10th  (range is usually 0-10)
01342     function ScaledCumulativeRating()
01343     {
01344         if ($this->CumulativeRating == NULL)
01345         {
01346             return NULL;
01347         }
01348         else
01349         {
01350             return intval(($this->CumulativeRating + 5) / 10);
01351         }
01352     }
01353 
01354     # return current number of ratings for resource
01355     function NumberOfRatings()
01356     {
01357         # if number of ratings not already set
01358         if (!isset($this->NumberOfRatings))
01359         {
01360             # obtain number of ratings
01361             $this->NumberOfRatings =
01362                     $this->DB->Query("SELECT Count(*) AS NumberOfRatings "
01363                             ."FROM ResourceRatings "
01364                             ."WHERE ResourceId = ".$this->Id,
01365                     "NumberOfRatings"
01366                     );
01367 
01368             # recalculate cumulative rating if it looks erroneous
01369             if (($this->NumberOfRatings > 0) && !$this->CumulativeRating())
01370             {
01371                 $this->UpdateCumulativeRating();
01372             }
01373         }
01374 
01375         # return number of ratings to caller
01376         return $this->NumberOfRatings;
01377     }
01378 
01379     # update individual rating for resource
01380     function Rating($NewRating = NULL, $UserId = NULL)
01381     {
01382         $DB = $this->DB;
01383 
01384         # if user ID not supplied
01385         if ($UserId == NULL)
01386         {
01387             # if user is logged in
01388             global $User;
01389             if ($User->IsLoggedIn())
01390             {
01391                 # use ID of current user
01392                 $UserId = $User->Get("UserId");
01393             }
01394             else
01395             {
01396                 # return NULL to caller
01397                 return NULL;
01398             }
01399         }
01400 
01401         # if there is a rating for resource and user
01402         $DB->Query("SELECT Rating FROM ResourceRatings "
01403                 ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
01404         if ($Record = $DB->FetchRow())
01405         {
01406             # if new rating was supplied
01407             if ($NewRating != NULL)
01408             {
01409                 # update existing rating
01410                 $DB->Query("UPDATE ResourceRatings "
01411                         ."SET Rating = ${NewRating}, DateRated = NOW() "
01412                         ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
01413 
01414                 # update cumulative rating value
01415                 $this->UpdateCumulativeRating();
01416 
01417                 # return value is new rating
01418                 $Rating = $NewRating;
01419             }
01420             else
01421             {
01422                 # get rating value to return to caller
01423                 $Rating = $Record["Rating"];
01424             }
01425         }
01426         else
01427         {
01428             # if new rating was supplied
01429             if ($NewRating != NULL)
01430             {
01431                 # add new rating
01432                 $DB->Query("INSERT INTO ResourceRatings "
01433                         ."(ResourceId, UserId, DateRated, Rating) "
01434                         ."VALUES ("
01435                                 .$this->Id.", "
01436                                 ."${UserId}, "
01437                                 ."NOW(), "
01438                                 ."${NewRating})");
01439 
01440                 # update cumulative rating value
01441                 $this->UpdateCumulativeRating();
01442 
01443                 # return value is new rating
01444                 $Rating = $NewRating;
01445             }
01446             else
01447             {
01448                 # return value is NULL
01449                 $Rating = NULL;
01450             }
01451         }
01452 
01453         # return rating value to caller
01454         return $Rating;
01455     }
01456 
01457 
01458     # --- Resource Comment Methods ------------------------------------------
01459 
01460     # return comments as array of Message objects
01461     function Comments()
01462     {
01463         # read in comments if not already loaded
01464         if (!isset($this->Comments))
01465         {
01466             $this->DB->Query("SELECT MessageId FROM Messages "
01467                     ."WHERE ParentId = ".$this->Id
01468                     ." AND ParentType = 2 "
01469                     ."ORDER BY DatePosted DESC");
01470             while ($MessageId = $this->DB->FetchField("MessageId"))
01471             {
01472                 $this->Comments[] = new Message($MessageId);
01473             }
01474         }
01475 
01476         # return array of comments to caller
01477         return $this->Comments;
01478     }
01479 
01480     # return current number of comments
01481     function NumberOfComments()
01482     {
01483         # obtain number of comments if not already set
01484         if (!isset($this->NumberOfComments))
01485         {
01486             $this->NumberOfComments =
01487                     $this->DB->Query("SELECT Count(*) AS NumberOfComments "
01488                             ."FROM Messages "
01489                             ."WHERE ParentId = ".$this->Id
01490                             ." AND ParentType = 2",
01491                     "NumberOfComments"
01492                     );
01493         }
01494 
01495         # return number of comments to caller
01496         return $this->NumberOfComments;
01497     }
01498 
01499 
01500     # --- Permission Methods -------------------------------------------------
01501 
01502     # return whether user can edit this resource
01503     function UserCanEdit($User)
01504     {
01505         return ($User->HasPriv(PRIV_RESOURCEADMIN)
01506             || $User->HasPriv(PRIV_RELEASEADMIN)
01507             || ($User->HasPriv(PRIV_MYRESOURCEADMIN)
01508                     && ($User->Id() == $this->DBFields["AddedById"]))
01509         );
01510     }
01511 
01512     # report whether user can view or edit specified field
01513     function UserCanViewField($User, $FieldOrFieldName)
01514     {
01515         # get field (if not supplied)
01516         if (is_object($FieldOrFieldName))
01517         {
01518             $Field = $FieldOrFieldName;
01519         }
01520         else
01521         {
01522             $Schema = new MetadataSchema();
01523             $Field = $Schema->GetFieldByName($FieldOrFieldName);
01524         }
01525 
01526         if ($Field->Status() != MetadataSchema::MDFSTAT_OK)
01527         {
01528             return FALSE;
01529         }
01530 
01531         # return enabled and viewable state from field
01532         return $Field->Enabled()
01533                 && ($Field->ViewingPrivilege() == 0
01534                     || $User->HasPriv($Field->ViewingPrivilege())
01535                     || $this->UserCanEditField($User, $Field));
01536     }
01537 
01538     function UserCanEditField($User, $FieldOrFieldName)
01539     {
01540         # get field (if not supplied)
01541         if (is_object($FieldOrFieldName))
01542         {
01543             $Field = $FieldOrFieldName;
01544         }
01545         else
01546         {
01547             $Schema = new MetadataSchema();
01548             $Field = $Schema->GetFieldByName($FieldOrFieldName);
01549         }
01550 
01551         if ($Field->Status() != MetadataSchema::MDFSTAT_OK)
01552         {
01553             return FALSE;
01554         }
01555 
01556         # start out assuming field cannot be edited
01557         $IsEditable = FALSE;
01558 
01559         # if user has editing privileges for field
01560         #       or user added resource and has authoring privileges for field
01561         if ($User->HasPriv($Field->EditingPrivilege())
01562                 || (($User->Name() == $this->Get("Added By Id"))
01563                         && (($Field->AuthoringPrivilege() == 0)
01564                             || $User->HasPriv($Field->AuthoringPrivilege()))))
01565         {
01566             # if field name does not appear on "no edit" list
01567             $UneditableFields = array(
01568                     "Cumulative Rating",
01569                     "Date Of Record Creation",
01570                     "Date Of Record Release",
01571                     "Date Last Modified",
01572                     "Added By Id",
01573                     "Last Modified By Id",
01574                     );
01575             if (!in_array($Field->Name(), $UneditableFields))
01576             {
01577                 # user can edit field
01578                 $IsEditable = TRUE;
01579             }
01580         }
01581 
01582         # return result to caller
01583         return $IsEditable;
01584     }
01585 
01586     # ---- PRIVATE INTERFACE -------------------------------------------------
01587 
01588     private $DB;
01589     private $Schema;
01590     private $DBFields;
01591     private $Id;
01592     private $NumberOfRatings;
01593     private $CumulativeRating;
01594     private $NumberOfComments;
01595     private $Comments;
01596     private $LastStatus;
01597     private $ControlledNameCache;
01598     private $ControlledNameVariantCache;
01599     private $ClassificationCache;
01600 
01601     # recalculate and save cumulative rating value for resource
01602     private function UpdateCumulativeRating()
01603     {
01604         # grab totals from DB
01605         $this->DB->Query("SELECT COUNT(Rating) AS Count, "
01606                 ."SUM(Rating) AS Total FROM ResourceRatings "
01607                 ."WHERE ResourceId = ".$this->Id);
01608         $Record = $this->DB->FetchRow();
01609 
01610         # calculate new cumulative rating
01611         $this->CumulativeRating = round($Record["Total"] / $Record["Count"]);
01612 
01613         # save new cumulative rating in DB
01614         $this->DB->Query("UPDATE Resources "
01615                 ."SET CumulativeRating = ".$this->CumulativeRating." "
01616                 ."WHERE ResourceId = ".$this->Id);
01617     }
01618 
01619     # add intersection if not already present
01620     private function AddAssociation($TableName, $TargetFieldName, $TargetValue)
01621     {
01622         # if target not already associated with resource
01623         if ($this->DB->Query("SELECT COUNT(*) AS RecordCount FROM ".$TableName
01624                    ." WHERE ResourceId = ".$this->Id
01625                    ." AND ".$TargetFieldName." = '".$TargetValue."'",
01626                    "RecordCount") == 0)
01627         {
01628             # associate target with resource
01629             $this->DB->Query("INSERT INTO ".$TableName." SET"
01630                        ." ResourceId = ".$this->Id
01631                        .", ".$TargetFieldName." = '".$TargetValue."'");
01632         }
01633     }
01634 
01635     # remove intersections (if any)
01636     private function RemoveAssociation($TableName, $TargetFieldName, $TargetValue)
01637     {
01638         # remove any intersections with target ID from DB
01639         $this->DB->Query("DELETE FROM ".$TableName
01640                          ." WHERE ResourceId = ".$this->Id
01641                          ." AND ".$TargetFieldName." = '".$TargetValue."'");
01642     }
01643 
01644     # remove all intersections for resource and field (if any)
01645     private function RemoveAllAssociations($TableName, $TargetFieldName, $Field)
01646     {
01647         # retrieve list of entries for this field and resource
01648         $Entries = $this->Get($Field);
01649 
01650         # for each entry
01651         foreach ($Entries as $EntryId => $EntryName)
01652         {
01653             # remove intersection
01654             $this->RemoveAssociation($TableName, $TargetFieldName, $EntryId);
01655         }
01656     }
01657 }
01658 
01659 
01660 ?>