Resource.php

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