CWIS Developer Documentation
Resource.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: Resource.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2011-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
8 #
9 
13 class Resource {
14 
15  # ---- PUBLIC INTERFACE --------------------------------------------------
16 
23  function __construct($ResourceId)
24  {
25  $this->DB = new Database();
26 
27  # save resource ID
28  $this->Id = intval($ResourceId);
29 
30  # locate resource in database
31  $this->DB->Query("SELECT * FROM Resources WHERE ResourceId = ".$this->Id);
32 
33  # if unable to locate resource
34  $Record = $this->DB->FetchRow();
35  if ($Record == FALSE)
36  {
37  # set status to -1 to indicate that creation failed
38  $this->LastStatus = -1;
39  }
40  else
41  {
42  # load in attributes from database
43  $this->DBFields = $Record;
44  $this->CumulativeRating = $Record["CumulativeRating"];
45 
46  # load our local metadata schema
47  $this->Schema = new MetadataSchema($this->DBFields["SchemaId"]);
48 
49  # set status to 1 to indicate that creation succeeded
50  $this->LastStatus = 1;
51  }
52  }
53 
59  static function Create($SchemaId)
60  {
61  # clean out any temp resource records more than three days old
62  $RFactory = new ResourceFactory();
63  $RFactory->CleanOutStaleTempItems(60 * 24 * 3);
64 
65  # lock DB tables to prevent next ID from being grabbed
66  $DB = new Database;
67  $DB->Query("LOCK TABLES Resources WRITE");
68 
69  # find next temp resource ID
70  $Id = $RFactory->GetNextTempItemId();
71 
72  # write out new resource record with temp resource ID
73  # Set DateLastModified = NOW() to avoid being pruned as a
74  # stale temp resource.
75  $DB->Query(
76  "INSERT INTO Resources
77  SET `ResourceId` = '".intval($Id)."',
78  `SchemaId` = '".intval($SchemaId)."',
79  `DateLastModified` = NOW() " );
80 
81  # release DB tables
82  $DB->Query("UNLOCK TABLES");
83 
84  # create new Resource object
85  $Resource = new Resource($Id);
86 
87  # set some additional fields for default resources
88  if ($SchemaId == MetadataSchema::SCHEMAID_DEFAULT)
89  {
90  $Resource->Set("Added By Id", $GLOBALS["G_User"]->Id());
91  $Resource->Set("Last Modified By Id", $GLOBALS["G_User"]->Id());
92  $Resource->Set("Date Of Record Creation", date("Y-m-d H:i:s"));
93  $Resource->Set("Date Last Modified", date("Y-m-d H:i:s"));
94  }
95 
96  # set any default values
97  $Schema = new MetadataSchema($SchemaId);
98  $Fields = $Schema->GetFields(MetadataSchema::MDFTYPE_OPTION
103  foreach ($Fields as $Field)
104  {
105  $DefaultValue = $Field->DefaultValue();
106 
107  # flip option default values to get into the form that
108  # Resource::Set() expects
109  if ($Field->Type() == MetadataSchema::MDFTYPE_OPTION
110  && is_array($DefaultValue))
111  {
112  $DefaultValue = array_flip($DefaultValue);
113  }
114 
115  if (!empty($DefaultValue))
116  $Resource->SetByField($Field, $DefaultValue);
117  }
118 
119  # update timestamps as required
120  $TimestampFields = $Schema->GetFields(MetadataSchema::MDFTYPE_TIMESTAMP);
121  foreach ($TimestampFields as $Field)
122  {
123  if ($Field->UpdateMethod() ==
125  {
126  $Resource->SetByField($Field, "now");
127  }
128  }
129 
130  # signal resource creation
131  $GLOBALS["AF"]->SignalEvent("EVENT_RESOURCE_CREATE", array(
132  "Resource" => $Resource,
133  ));
134 
135  # return new Resource object to caller
136  return $Resource;
137  }
138 
143  function Delete()
144  {
145  global $SysConfig;
146 
147  # signal that resource deletion is about to occur
148  global $AF;
149  $AF->SignalEvent("EVENT_RESOURCE_DELETE", array(
150  "Resource" => $this,
151  ));
152 
153  # grab list of classifications
154  $Classifications = $this->Classifications();
155 
156  # delete resource/classification intersections
157  $DB = $this->DB;
158  $DB->Query("DELETE FROM ResourceClassInts WHERE ResourceId = ".$this->Id());
159 
160  # for each classification type
161  foreach ($Classifications as $ClassType => $ClassesOfType)
162  {
163  # for each classification of that type
164  foreach ($ClassesOfType as $ClassId => $ClassName)
165  {
166  # recalculate resource count for classification
167  $Class = new Classification($ClassId);
168  $Class->RecalcResourceCount();
169  }
170  }
171 
172  # delete resource references
173  $DB->Query("
174  DELETE FROM ReferenceInts
175  WHERE SrcResourceId = '".addslashes($this->Id())."'
176  OR DstResourceId = '".addslashes($this->Id())."'");
177 
178  # delete resource/name intersections
179  $DB->Query("DELETE FROM ResourceNameInts WHERE ResourceId = ".$this->Id());
180 
181  # delete any associated images not in use by other resources
182  $DB->Query("SELECT ImageId FROM ResourceImageInts"
183  ." WHERE ResourceId = ".intval($this->Id()));
184  $ImageIds = $DB->FetchColumn("ImageId");
185  foreach ($ImageIds as $ImageId)
186  {
187  $DB->Query("SELECT ResourceId FROM ResourceImageInts"
188  ." WHERE ImageId = ".intval($ImageId)
189  ." AND ResourceId != ".intval($this->Id()));
190  if ($DB->NumRowsSelected() == 0)
191  {
192  $Image = new SPTImage($ImageId);
193  $Image->Delete();
194  }
195  }
196 
197  # delete any associated files
198  $Factory = new FileFactory(NULL);
199  $Files = $Factory->GetFilesForResource($this->Id());
200  foreach ($Files as $File)
201  {
202  $File->Delete();
203  }
204 
205  # delete resource record from database
206  $DB->Query("DELETE FROM Resources WHERE ResourceId = ".$this->Id());
207 
208  # drop item from search engine and recommender system
209  if ($SysConfig->SearchDBEnabled())
210  {
211  $SearchEngine = new SPTSearchEngine();
212  $SearchEngine->DropItem($this->Id());
213  }
214  if ($SysConfig->RecommenderDBEnabled())
215  {
216  $Recommender = new SPTRecommender();
217  $Recommender->DropItem($this->Id());
218  }
219 
220  # get the folders containing the resource
221  $FolderFactory = new FolderFactory();
222  $Folders = $FolderFactory->GetFoldersContainingItem(
223  $this->Id,
224  "Resource");
225 
226  # drop the resource from each folder it belongs to
227  foreach ($Folders as $Folder)
228  {
229  # mixed item type folder
230  if ($Folder->ContainsItem($this->Id, "Resource"))
231  {
232  $Folder->RemoveItem($this->Id, "Resource");
233  }
234 
235  # single item type folder
236  else
237  {
238  $Folder->RemoveItem($this->Id);
239  }
240  }
241 
242  # delete any resource comments
243  $DB->Query("DELETE FROM Messages WHERE ParentId = ".$this->Id);
244  }
245 
250  function Status() { return $this->LastStatus; }
251 
256  function Id() { return $this->Id; }
257 
262  function SchemaId() { return $this->DBFields["SchemaId"]; }
263 
270  function IsTempResource($NewSetting = NULL)
271  {
272  # if new temp resource setting supplied
273  if (!is_null($NewSetting))
274  {
275  # if caller requested to switch
276  $DB = $this->DB;
277  if ((($this->Id() < 0) && ($NewSetting == FALSE))
278  || (($this->Id() >= 0) && ($NewSetting == TRUE)))
279  {
280  # lock DB tables to prevent next ID from being grabbed
281  $DB->Query("LOCK TABLES Resources write");
282 
283  # get next resource ID as appropriate
284  $OldResourceId = $this->Id;
285  $Factory = new ResourceFactory($this->SchemaId());
286  if ($NewSetting == TRUE)
287  {
288  $this->Id = $Factory->GetNextTempItemId();
289  }
290  else
291  {
292  $this->Id = $Factory->GetNextItemId();
293  }
294 
295  # change resource ID
296  $DB->Query("UPDATE Resources SET ResourceId = ".
297  $this->Id. " WHERE ResourceId = ".$OldResourceId);
298 
299  # release DB tables
300  $DB->Query("UNLOCK TABLES");
301 
302  # change associations
303  unset($this->ClassificationCache);
304  $DB->Query("UPDATE ResourceClassInts SET ResourceId = ".
305  $this->Id. " WHERE ResourceId = ".$OldResourceId);
306  unset($this->ControlledNameCache);
307  unset($this->ControlledNameVariantCache);
308  $DB->Query("UPDATE ResourceNameInts SET ResourceId = ".
309  $this->Id. " WHERE ResourceId = ".$OldResourceId);
310  $DB->Query("UPDATE Files SET ResourceId = ".
311  $this->Id. " WHERE ResourceId = ".$OldResourceId);
312  $DB->Query("UPDATE ReferenceInts SET SrcResourceId = ".
313  $this->Id. " WHERE SrcResourceId = ".$OldResourceId);
314  $DB->Query("UPDATE ResourceImageInts SET ResourceId = ".
315  $this->Id. " WHERE ResourceId = ".$OldResourceId);
316 
317  # signal event as appropriate
318  if ($NewSetting === FALSE)
319  {
320  $GLOBALS["AF"]->SignalEvent("EVENT_RESOURCE_ADD", array(
321  "Resource" => $this,
322  ));
323  }
324  }
325  }
326 
327  # report to caller whether we are a temp resource
328  return ($this->Id() < 0) ? TRUE : FALSE;
329  }
330 
331 
332  # --- Generic Attribute Retrieval Methods -------------------------------
333 
348  function Get($FieldNameOrObject, $ReturnObject = FALSE, $IncludeVariants = FALSE)
349  {
350  # load field object if needed
351  $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
352  : $this->Schema->GetFieldByName($FieldNameOrObject);
353 
354  # return no value found if we don't have a valid field
355  if (!($Field instanceof MetadataField)) { return NULL; }
356 
357  # grab database field name
358  $DBFieldName = $Field->DBFieldName();
359 
360  # format return value based on field type
361  switch ($Field->Type())
362  {
366  $ReturnValue = isset($this->DBFields[$DBFieldName])
367  ? (string)$this->DBFields[$DBFieldName] : NULL;
368  break;
369 
371  $ReturnValue = isset($this->DBFields[$DBFieldName])
372  ? (int)$this->DBFields[$DBFieldName] : NULL;
373  break;
374 
376  $ReturnValue = isset($this->DBFields[$DBFieldName])
377  ? (bool)$this->DBFields[$DBFieldName] : NULL;
378  break;
379 
381  $ReturnValue = array("X" => (float)$this->DBFields[$DBFieldName."X"],
382  "Y" => (float)$this->DBFields[$DBFieldName."Y"]);
383  break;
384 
386  $Date = new Date($this->DBFields[$DBFieldName."Begin"],
387  $this->DBFields[$DBFieldName."End"],
388  $this->DBFields[$DBFieldName."Precision"]);
389  if ($ReturnObject)
390  {
391  $ReturnValue = $Date;
392  }
393  else
394  {
395  $ReturnValue = $Date->Formatted();
396  }
397  break;
398 
400  $ReturnValue = $this->DBFields[$DBFieldName];
401  break;
402 
404  # start with empty array
405  $ReturnValue = array();
406 
407  # if classification cache has not been loaded
408  if (!isset($this->ClassificationCache))
409  {
410  # load all classifications associated with this resource into cache
411  $this->ClassificationCache = array();
412  $this->DB->Query(
413  "SELECT Classifications.ClassificationId,"
414  ." Classifications.FieldId,ClassificationName"
415  ." FROM ResourceClassInts, Classifications"
416  ." WHERE ResourceClassInts.ResourceId = ".$this->Id
417  ." AND ResourceClassInts.ClassificationId"
418  ." = Classifications.ClassificationId");
419  while ($Record = $this->DB->FetchRow())
420  {
421  $this->ClassificationCache[$Record["ClassificationId"]]["Name"] =
422  $Record["ClassificationName"];
423  $this->ClassificationCache[$Record["ClassificationId"]]["FieldId"] =
424  $Record["FieldId"];
425  }
426  }
427 
428  # for each entry in classification cache
429  foreach ($this->ClassificationCache as $ClassificationId => $ClassificationInfo)
430  {
431  # if classification ID matches field we are looking for
432  if ($ClassificationInfo["FieldId"] == $Field->Id())
433  {
434  # add field to result
435  if ($ReturnObject)
436  {
437  $ReturnValue[$ClassificationId] = new Classification($ClassificationId);
438  }
439  else
440  {
441  $ReturnValue[$ClassificationId] = $ClassificationInfo["Name"];
442  }
443  }
444  }
445  break;
446 
449  # start with empty array
450  $ReturnValue = array();
451 
452  # if controlled name cache has not been loaded
453  if (!isset($this->ControlledNameCache))
454  {
455  # load all controlled names associated with this resource into cache
456  $this->ControlledNameCache = array();
457  $this->DB->Query(
458  "SELECT ControlledNames.ControlledNameId,"
459  ." ControlledNames.FieldId,ControlledName"
460  ." FROM ResourceNameInts, ControlledNames"
461  ." WHERE ResourceNameInts.ResourceId = ".$this->Id
462  ." AND ResourceNameInts.ControlledNameId"
463  ." = ControlledNames.ControlledNameId"
464  ." ORDER BY ControlledNames.ControlledName ASC");
465  while ($Record = $this->DB->FetchRow())
466  {
467  $this->ControlledNameCache[$Record["ControlledNameId"]]["Name"] = $Record["ControlledName"];
468  $this->ControlledNameCache[$Record["ControlledNameId"]]["FieldId"] = $Record["FieldId"];
469  }
470  }
471 
472  # if variant names requested and variant name cache has not been loaded
473  if ($IncludeVariants && !isset($this->ControlledNameVariantCache))
474  {
475  # load all controlled names associated with this resource into cache
476  $this->ControlledNameVariantCache = array();
477  $this->DB->Query("SELECT ControlledNames.ControlledNameId,"
478  ." ControlledNames.FieldId,"
479  ." ControlledName, VariantName"
480  ." FROM ResourceNameInts, ControlledNames, VariantNames"
481  ." WHERE ResourceNameInts.ResourceId = ".$this->Id
482  ." AND ResourceNameInts.ControlledNameId"
483  ." = ControlledNames.ControlledNameId"
484  ." AND VariantNames.ControlledNameId"
485  ." = ControlledNames.ControlledNameId");
486  while ($Record = $this->DB->FetchRow())
487  {
488  $this->ControlledNameVariantCache[$Record["ControlledNameId"]][]
489  = $Record["VariantName"];
490  }
491  }
492 
493  # for each entry in controlled name cache
494  foreach ($this->ControlledNameCache as $ControlledNameId => $ControlledNameInfo)
495  {
496  # if controlled name type matches field we are looking for
497  if ($ControlledNameInfo["FieldId"] == $Field->Id())
498  {
499  # if objects requested
500  if ($ReturnObject)
501  {
502  $ReturnValue[$ControlledNameId] =
503  new ControlledName($ControlledNameId);
504  }
505  else
506  {
507  # if variant names requested
508  if ($IncludeVariants)
509  {
510  # add field to result
511  $ReturnValue[] = $ControlledNameInfo["Name"];
512 
513  # add any variant names to result
514  if (isset($this->ControlledNameVariantCache[$ControlledNameId]))
515  {
516  $ReturnValue = array_merge(
517  $ReturnValue,
518  $this->ControlledNameVariantCache[$ControlledNameId]);
519  }
520  }
521  else
522  {
523  # add field with index to result
524  $ReturnValue[$ControlledNameId] =
525  $ControlledNameInfo["Name"];
526  }
527  }
528  }
529  }
530  break;
531 
533  $User = new CWUser(intval($this->DBFields[$DBFieldName]));
534  if ($ReturnObject)
535  {
536  $ReturnValue = $User;
537  }
538  else
539  {
540  $ReturnValue = $User->Get("UserName");
541  }
542  break;
543 
545  # start out assuming no images will be found
546  $ReturnValue = array();
547 
548  # find all images associated with this resource
549  $this->DB->Query("SELECT ImageId FROM ResourceImageInts"
550  ." WHERE ResourceId = ".intval($this->Id())
551  ." AND FieldId = ".intval($Field->Id()));
552 
553  # if images were found
554  if ($this->DB->NumRowsSelected())
555  {
556  # if we are to return an object
557  $ImageIds = $this->DB->FetchColumn("ImageId");
558  if ($ReturnObject)
559  {
560  # load array of Image objects for return value
561  foreach ($ImageIds as $ImageId)
562  {
563  $ReturnValue[$ImageId] = new SPTImage($ImageId);
564  }
565  }
566  else
567  {
568  # load array of Image ids for return value
569  $ReturnValue = $ImageIds;
570  }
571  }
572  break;
573 
575  # retrieve files using factory
576  $Factory = new FileFactory($Field->Id());
577  $ReturnValue = $Factory->GetFilesForResource(
578  $this->Id, $ReturnObject);
579  break;
580 
582  # query for resource references
583  $this->DB->Query("
584  SELECT * FROM ReferenceInts
585  WHERE FieldId = '".addslashes($Field->Id())."'
586  AND SrcResourceId = '".addslashes($this->Id())."'");
587 
588  $ReturnValue = array();
589 
590  # return each reference as a Resource object
591  if ($ReturnObject)
592  {
593  $FoundErrors = FALSE;
594 
595  while (FALSE !== ($Record = $this->DB->FetchRow()))
596  {
597  $ReferenceId = $Record["DstResourceId"];
598  $Reference = new Resource($ReferenceId);
599 
600  # the reference is bad, so flag that there were errors
601  if ($Reference->Status() != 1)
602  {
603  $FoundErrors = TRUE;
604  }
605 
606  else
607  {
608  $ReturnValue[$ReferenceId] = $Reference;
609  }
610  }
611 
612  # try to fix the errors by removing any references to
613  # resources that were bad
614  if ($FoundErrors)
615  {
616  $this->Set($Field, $ReturnValue);
617  }
618  }
619 
620  # return each reference as a resource ID
621  else
622  {
623  while (FALSE !== ($Record = $this->DB->FetchRow()))
624  {
625  $ReferenceId = $Record["DstResourceId"];
626  $ReturnValue[$ReferenceId] = $ReferenceId;
627  }
628  }
629  break;
630 
631  default:
632  # ERROR OUT
633  exit("<br>SPT - ERROR: attempt to retrieve unknown resource field type (".$Field->Type().")<br>\n");
634  break;
635  }
636 
637  # return formatted value to caller
638  return $ReturnValue;
639  }
644  function GetByField($FieldNameOrObject,
645  $ReturnObject = FALSE, $IncludeVariants = FALSE)
646  { return $this->Get($FieldNameOrObject, $ReturnObject, $IncludeVariants); }
647 
661  function GetByFieldId($FieldId, $ReturnObject = FALSE, $IncludeVariants = FALSE)
662  {
663  $Field = $this->Schema->GetField($FieldId);
664  return ($Field) ? $this->Get($Field, $ReturnObject, $IncludeVariants) : NULL;
665  }
666 
679  function GetAsArray($IncludeDisabledFields = FALSE, $ReturnObjects = TRUE)
680  {
681  # retrieve field info
682  $Fields = $this->Schema->GetFields();
683 
684  # for each field
685  foreach ($Fields as $Field)
686  {
687  # if field is enabled or caller requested disabled fields
688  if ($Field->Enabled() || $IncludeDisabledFields)
689  {
690  # retrieve info and add it to the array
691  $FieldStrings[$Field->Name()] = $this->Get($Field, $ReturnObjects);
692 
693  # if field uses qualifiers
694  if ($Field->UsesQualifiers())
695  {
696  # get qualifier attributes and add to the array
697  $FieldStrings[$Field->Name()." Qualifier"] =
698  $this->GetQualifierByField($Field, $ReturnObjects);
699  }
700  }
701  }
702 
703  # add in internal values
704  $FieldStrings["ResourceId"] = $this->Id();
705  $FieldStrings["CumulativeRating"] = $this->CumulativeRating();
706 
707  # return array to caller
708  return $FieldStrings;
709  }
710 
725  function GetMapped($MappedName, $ReturnObject = FALSE, $IncludeVariants = FALSE)
726  {
727  return $this->Schema->StdNameToFieldMapping($MappedName)
728  ? $this->GetByFieldId($this->Schema->StdNameToFieldMapping($MappedName),
729  $ReturnObject, $IncludeVariants)
730  : NULL;
731  }
732 
741  function GetQualifier($FieldName, $ReturnObject = TRUE)
742  {
743  $Field = $this->Schema->GetFieldByName($FieldName);
744  return $this->GetQualifierByField($Field, $ReturnObject);
745  }
746 
755  function GetQualifierByFieldId($FieldId, $ReturnObject = TRUE)
756  {
757  $Field = $this->Schema->GetField($FieldId);
758  return ($Field) ? $this->GetQualifierByField($Field, $ReturnObject) : NULL;
759  }
760 
769  function GetQualifierByField($Field, $ReturnObject = TRUE)
770  {
771  # return NULL if field is invalid
772  if (!($Field instanceof MetadataField)) { return NULL; }
773 
774  # assume no qualifiers if not otherwise determined
775  $ReturnValue = NULL;
776 
777  # if field uses qualifiers
778  if ($Field->UsesQualifiers())
779  {
780  # retrieve qualifiers based on field type
781  switch ($Field->Type())
782  {
786  # retrieve list of items
787  $Items = $this->Get($Field);
788 
789  # if field uses item-level qualifiers
790  if ($Field->HasItemLevelQualifiers())
791  {
792  # determine general item name in DB
793  $TableName = ($Field->Type() == MetadataSchema::MDFTYPE_TREE)
794  ? "Classification" : "ControlledName";
795 
796  # for each item
797  foreach ($Items as $ItemId => $ItemName)
798  {
799  # look up qualifier for item
800  $QualId = $this->DB->Query(
801  "SELECT * FROM ".$TableName."s"
802  ." WHERE ".$TableName."Id = ".$ItemId,
803  "QualifierId");
804 
805 
806  if ($QualId > 0)
807  {
808  # if object was requested by caller
809  if ($ReturnObject)
810  {
811  # load qualifier and add to return value array
812  $ReturnValue[$ItemId] = new Qualifier($QualId);
813  }
814  else
815  {
816  # add qualifier ID to return value array
817  $ReturnValue[$ItemId] = $QualId;
818  }
819  }
820  else
821  {
822  # add NULL to return value array for this item
823  $ReturnValue[$ItemId] = NULL;
824  }
825  }
826  }
827  else
828  {
829  # for each item
830  foreach ($Items as $ItemId => $ItemName)
831  {
832  # if object was requested by caller
833  if ($ReturnObject)
834  {
835  # load default qualifier and add to return value array
836  $ReturnValue[$ItemId] = new Qualifier($Field->DefaultQualifier());
837  }
838  else
839  {
840  # add default qualifier ID to return value array
841  $ReturnValue[$ItemId] = $Field->DefaultQualifier();
842  }
843  }
844  }
845  break;
846 
847  default:
848  # if field uses item-level qualifiers
849  if ($Field->HasItemLevelQualifiers())
850  {
851  # if qualifier available
852  if ($this->DBFields[$Field->DBFieldName()."Qualifier"] > 0)
853  {
854  # if object was requested by caller
855  if ($ReturnObject)
856  {
857  # return qualifier for field
858  $ReturnValue = new Qualifier($this->DBFields[$Field->DBFieldName()."Qualifier"]);
859  }
860  else
861  {
862  # return qualifier ID for field
863  $ReturnValue = $this->DBFields[$Field->DBFieldName()."Qualifier"];
864  }
865  }
866  }
867  else
868  {
869  # if default qualifier available
870  if ($Field->DefaultQualifier() > 0)
871  {
872  # if object was requested by caller
873  if ($ReturnObject)
874  {
875  # return default qualifier
876  $ReturnValue = new Qualifier($Field->DefaultQualifier());
877  }
878  else
879  {
880  # return default qualifier ID
881  $ReturnValue = $Field->DefaultQualifier();
882  }
883  }
884  }
885  break;
886  }
887  }
888 
889  # return qualifier object or ID (or array of same) to caller
890  return $ReturnValue;
891  }
892 
900  function FieldIsSet($FieldNameOrObject, $IgnorePadding=FALSE)
901  {
902  # load field object if needed
903  $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
904  : $this->Schema->GetFieldByName($FieldNameOrObject);
905 
906  # return no value found if we don't have a valid field
907  if (!($Field instanceof MetadataField)) { return FALSE; }
908 
909  # get the value
910  $Value = $this->Get($Field);
911 
912  # checks depend on the field type
913  switch ($Field->Type())
914  {
919  return isset($Value)
920  && strlen($Value)
921  && (!$IgnorePadding || ($IgnorePadding && strlen(trim($Value))));
922 
924  return isset($Value)
925  && strlen($Value);
926 
928  return isset($Value["X"])
929  && isset($Value["Y"])
930  && strlen(trim($Value["X"]))
931  && strlen(trim($Value["Y"]));
932 
934  return isset($Value)
935  && strlen(trim($Value))
936  && $Value != "0000-00-00";
937 
939  return isset($Value)
940  && strlen(trim($Value))
941  && $Value != "0000-00-00 00:00:00";
942 
949  return count($Value) > 0;
950 
952  $Factory = new CWUserFactory();
953  return isset($Value)
954  && strlen($Value)
955  && $Factory->UserNameExists($Value);
956 
957  default:
958  return FALSE;
959  }
960  }
961 
962  # --- Generic Attribute Setting Methods ---------------------------------
963 
972  function Set($FieldNameOrObject, $NewValue, $Reset=FALSE)
973  {
974  # load field object if needed
975  $Field = is_object($FieldNameOrObject) ? $FieldNameOrObject
976  : $this->Schema->GetFieldByName($FieldNameOrObject);
977 
978  # return if we don't have a valid field
979  if (!($Field instanceof MetadataField)) { return; }
980 
981  # grab commonly-used values for local use
982  $DB = $this->DB;
983  $ResourceId = $this->Id;
984 
985  # grab database field name
986  $DBFieldName = $Field->DBFieldName();
987 
988  # Flag to deterimine if we've actually changed anything.
989  $UpdateModTime = FALSE;
990 
991  # store value in DB based on field type
992  switch ($Field->Type())
993  {
997  if ($this->DBFields[$DBFieldName] != $NewValue)
998  {
999  # save value directly to DB
1000  $DB->Query("UPDATE Resources SET `"
1001  .$DBFieldName."` = '".addslashes($NewValue)."' "
1002  ."WHERE ResourceId = ".$ResourceId);
1003 
1004  # save value locally
1005  $this->DBFields[$DBFieldName] = $NewValue;
1006  $UpdateModTime=TRUE;
1007  }
1008  break;
1009 
1011  if ( $this->DBFields[$DBFieldName] != $NewValue )
1012  {
1013  # save value directly to DB
1014  if (is_null($NewValue))
1015  {
1016  $DB->Query("UPDATE Resources SET `"
1017  .$DBFieldName."` = NULL"
1018  ." WHERE ResourceId = ".$ResourceId);
1019  }
1020  else
1021  {
1022  $DB->Query("UPDATE Resources SET `"
1023  .$DBFieldName."` = ".intval($NewValue)
1024  ." WHERE ResourceId = ".$ResourceId);
1025  }
1026 
1027  # save value locally
1028  $this->DBFields[$DBFieldName] = $NewValue;
1029  $UpdateModTime = TRUE;
1030  }
1031  break;
1032 
1033 
1035  if ($this->DBFields[$DBFieldName."X"] != $NewValue["X"] ||
1036  $this->DBFields[$DBFieldName."Y"] != $NewValue["Y"] )
1037  {
1038  if (is_null($NewValue))
1039  {
1040  $DB->Query("UPDATE Resources SET "
1041  ."`".$DBFieldName."X` = NULL, "
1042  ."`".$DBFieldName."Y` = NULL "
1043  ."WHERE ResourceId = ".$ResourceId);
1044  $this->DBFields[$DBFieldName."X"] = NULL;
1045  $this->DBFields[$DBFieldName."Y"] = NULL;
1046  }
1047  else
1048  {
1049  $DB->Query("UPDATE Resources SET "
1050  ."`".$DBFieldName."X` = ".(strlen($NewValue["X"])
1051  ? "'".$NewValue["X"]."'" : "NULL").", "
1052  ."`".$DBFieldName."Y` = ".(strlen($NewValue["Y"])
1053  ? "'".$NewValue["Y"]."'" : "NULL")
1054  ." WHERE ResourceId = ".$ResourceId);
1055 
1056  $Digits = $Field->PointDecimalDigits();
1057 
1058  $this->DBFields[$DBFieldName."X"] =
1059  strlen($NewValue["X"]) ? round($NewValue["X"], $Digits) : NULL;
1060  $this->DBFields[$DBFieldName."Y"] =
1061  strlen($NewValue["Y"]) ? round($NewValue["Y"], $Digits) : NULL;
1062  }
1063  $UpdateModTime = TRUE;
1064  }
1065  break;
1066 
1068  if ($this->DBFields[$DBFieldName] != $NewValue)
1069  {
1070  # save value directly to DB
1071  if (is_null($NewValue))
1072  {
1073  $DB->Query("UPDATE Resources SET `"
1074  .$DBFieldName."` = NULL"
1075  ." WHERE ResourceId = ".$ResourceId);
1076  }
1077  else
1078  {
1079  $NewValue = $NewValue ? "1" : "0";
1080  $DB->Query("UPDATE Resources SET `"
1081  .$DBFieldName."` = ".$NewValue
1082  ." WHERE ResourceId = ".$ResourceId);
1083  }
1084 
1085  $this->DBFields[$DBFieldName] = $NewValue;
1086 
1087  # recalculate counts for any associated classifications if necessary
1088  if ($DBFieldName == "ReleaseFlag")
1089  {
1090  $DB->Query("SELECT ClassificationId FROM ResourceClassInts"
1091  ." WHERE ResourceId = ".$ResourceId);
1092  while ($ClassId = $DB->FetchField("ClassificationId"))
1093  {
1094  $Class = new Classification($ClassId);
1095  $Class->RecalcResourceCount();
1096  }
1097  }
1098  $UpdateModTime = TRUE;
1099  }
1100  break;
1101 
1103  # if value passed in was object
1104  if (is_object($NewValue))
1105  {
1106  # retrieve user ID from object
1107  $UserId = $NewValue->Get("UserId");
1108  }
1109  # else if value passed in was user name
1110  elseif (is_string($NewValue) && strlen($NewValue))
1111  {
1112  # create user object and retrieve user ID from there
1113  $User = new CWUser($NewValue);
1114  $UserId = $User->Get("UserId");
1115  }
1116  else
1117  {
1118  # assume value is user ID and use value directly
1119  $UserId = $NewValue;
1120  }
1121 
1122  if ($this->DBFields[$DBFieldName] != $UserId)
1123  {
1124  # save value directly to DB
1125  $DB->Query("UPDATE Resources SET `"
1126  .$DBFieldName."` = '".$UserId."' "
1127  ."WHERE ResourceId = ".$ResourceId);
1128 
1129  # save value locally
1130  $this->DBFields[$DBFieldName] = $UserId;
1131  $UpdateModTime = TRUE;
1132  }
1133  break;
1134 
1136  # if we were given a date object
1137  if (is_object($NewValue))
1138  {
1139  # use supplied date object
1140  $Date = $NewValue;
1141  }
1142  else
1143  {
1144  # create date object
1145  $Date = new Date($NewValue);
1146  }
1147 
1148  $OldDate = new Date(
1149  $this->DBFields[$DBFieldName."Begin"],
1150  $this->DBFields[$DBFieldName."End"]);
1151 
1152  if ($OldDate->BeginDate() != $Date->BeginDate() ||
1153  $OldDate->EndDate() != $Date->EndDate() ||
1154  $OldDate->Precision() != $Date->Precision() )
1155  {
1156  # extract values from date object and store in DB
1157  $BeginDate = "'".$Date->BeginDate()."'";
1158  if (strlen($BeginDate) < 3) { $BeginDate = "NULL"; }
1159  $EndDate = "'".$Date->EndDate()."'";
1160  if (strlen($EndDate) < 3) { $EndDate = "NULL"; }
1161 
1162  $DB->Query("UPDATE Resources SET "
1163  .$DBFieldName."Begin = ".$BeginDate.", "
1164  .$DBFieldName."End = ".$EndDate.", "
1165  .$DBFieldName."Precision = '".$Date->Precision()."' "
1166  ."WHERE ResourceId = ".$ResourceId);
1167 
1168  # save values locally
1169  $this->DBFields[$DBFieldName."Begin"] = $Date->BeginDate();
1170  $this->DBFields[$DBFieldName."End"] = $Date->EndDate();
1171  $this->DBFields[$DBFieldName."Precision"] = $Date->Precision();
1172  $UpdateModTime=TRUE;
1173  }
1174  break;
1175 
1177  if (is_null($NewValue) || !strlen(trim($NewValue)))
1178  {
1179  $DateValue = $NewValue;
1180 
1181  if (!is_null($this->DBFields[$DBFieldName]))
1182  {
1183  # save value directly to DB
1184  $DB->Query("UPDATE Resources SET "
1185  ."`".$DBFieldName."` = NULL "
1186  ."WHERE ResourceId = ".$ResourceId);
1187  $UpdateModTime = TRUE;
1188  }
1189  }
1190  else
1191  {
1192  # assume value is date and use directly
1193  $TimestampValue = strtotime($NewValue);
1194 
1195  # use the new value if the date is valid
1196  if ($TimestampValue !== FALSE && $TimestampValue >= 0)
1197  {
1198  $DateValue = date("Y-m-d H:i:s", $TimestampValue);
1199 
1200  if ($this->DBFields[$DBFieldName] != $DateValue)
1201  {
1202  # save value directly to DB
1203  $DB->Query("UPDATE Resources SET "
1204  ."`".$DBFieldName."` = '".addslashes($DateValue)."' "
1205  ."WHERE ResourceId = ".$ResourceId);
1206  $UpdateModTime=TRUE;
1207  }
1208  }
1209 
1210  # continue using the old value if invalid
1211  else
1212  {
1213  $DateValue = $this->Get($Field);
1214  }
1215  }
1216 
1217  # save value locally
1218  $this->DBFields[$DBFieldName] = $DateValue;
1219  break;
1220 
1222  $OldValue = $this->Get($Field);
1223 
1224  # if incoming value is array
1225  if (is_array($NewValue))
1226  {
1227  if ($OldValue != $NewValue)
1228  {
1229  if ($Reset)
1230  {
1231  # Remove values that were in the old value, but not the new one:
1232  $ToRemove = array_diff(array_keys($OldValue), array_keys($NewValue));
1233  foreach ($ToRemove as $ClassificationId)
1234  {
1235  $this->RemoveAssociation("ResourceClassInts",
1236  "ClassificationId",
1237  $ClassificationId);
1238  $Class = new Classification($ClassificationId);
1239  if ($Class->Status() == Classification::CLASSSTAT_OK)
1240  $Class->RecalcResourceCount();
1241  }
1242  }
1243 
1244  # for each element of array
1245  foreach ($NewValue as
1246  $ClassificationId => $ClassificationName)
1247  {
1248  $Class = new Classification($ClassificationId);
1249  if ($Class->Status() == Classification::CLASSSTAT_OK)
1250  {
1251  # associate with resource if not already associated
1252  if ($this->AddAssociation("ResourceClassInts",
1253  "ClassificationId",
1254  $ClassificationId) )
1255  {
1256  $Class->UpdateLastAssigned();
1257  $Class->RecalcResourceCount();
1258  }
1259  }
1260  }
1261 
1262  $UpdateModTime=TRUE;
1263  }
1264  }
1265  else
1266  {
1267  # associate with resource if not already associated
1268  if (is_object($NewValue))
1269  {
1270  $Class = $NewValue;
1271  $NewValue = $Class->Id();
1272  }
1273  else
1274  {
1275  $Class = new Classification($NewValue);
1276  }
1277 
1278  if (!array_key_exists($Class->Id(), $OldValue))
1279  {
1280 
1281  $this->AddAssociation("ResourceClassInts",
1282  "ClassificationId",
1283  $NewValue);
1284  $Class->UpdateLastAssigned();
1285  $Class->RecalcResourceCount();
1286  $UpdateModTime=TRUE;
1287  }
1288  }
1289 
1290  # clear our classification cache
1291  if ($UpdateModTime)
1292  {
1293  unset($this->ClassificationCache);
1294  }
1295  break;
1296 
1299  $OldValue = $this->Get($Field);
1300 
1301  # Clear other values if this field expects unique options
1302  if ($Field->AllowMultiple() === FALSE)
1303  {
1304  # If we're fed an array for a unique option,
1305  # just use the last element of the array
1306  if (is_array($NewValue)){
1307  $NewValue = array_pop($NewValue);
1308  }
1309 
1310  if (!array_key_exists($NewValue, $OldValue))
1311  {
1312 
1313  $this->RemoveAllAssociations("ResourceNameInts",
1314  "ControlledNameId",
1315  $Field );
1316  $UpdateModTime=TRUE;
1317  }
1318  }
1319 
1320  # if incoming value is array
1321  if (is_array($NewValue) && ($Field->AllowMultiple() !== FALSE) )
1322  {
1323  if ($OldValue != $NewValue)
1324  {
1325  if ($Reset)
1326  {
1327  $ToRemove = array_diff(array_keys($OldValue), array_keys($NewValue));
1328  foreach ($ToRemove as $CNId)
1329  {
1330  $this->RemoveAssociation("ResourceNameInts",
1331  "ControlledNameId",
1332  $CNId);
1333  }
1334  }
1335 
1336  # for each element of array
1337  foreach ($NewValue as $ControlledNameId => $ControlledName)
1338  {
1339  # associate with resource if not already associated
1340  if ($this->AddAssociation("ResourceNameInts",
1341  "ControlledNameId",
1342  $ControlledNameId))
1343  {
1344  $CN = new ControlledName( $ControlledNameId );
1345  $CN->UpdateLastAssigned();
1346  }
1347  }
1348  $UpdateModTime=TRUE;
1349  }
1350  }
1351  else
1352  {
1353  # associate with resource if not already associated
1354  if (is_object($NewValue)) { $NewValue = $NewValue->Id(); }
1355  if (!array_key_exists($NewValue, $OldValue))
1356  {
1357  $this->AddAssociation("ResourceNameInts",
1358  "ControlledNameId",
1359  $NewValue);
1360  $UpdateModTime=TRUE;
1361  }
1362  }
1363 
1364  if ($UpdateModTime)
1365  {
1366  # clear our controlled name cache
1367  unset($this->ControlledNameCache);
1368  unset($this->ControlledNameVariantCache);
1369  }
1370 
1371  break;
1372 
1374  # associate value(s) with resource
1375  $this->AddAssociation(
1376  "ResourceImageInts", "ImageId", $NewValue, $Field);
1377  break;
1378 
1380  # convert incoming value to array if necessary
1381  if (!is_array($NewValue)) { $NewValue = array($NewValue); }
1382 
1383  # for each incoming file
1384  $Factory = new FileFactory($Field->Id());
1385  foreach ($NewValue as $File)
1386  {
1387  # make copy of file
1388  $NewFile = $Factory->Copy($File);
1389 
1390  # associate copy with this resource and field
1391  $NewFile->ResourceId($this->Id);
1392  $NewFile->FieldId($Field->Id());
1393  }
1394  # Since we make a fresh copy of the File whenever Set is called,
1395  # we'll always update the modification time for this field.
1396  $UpdateModTime = TRUE;
1397  break;
1398 
1400  # convert incoming value to array to simplify the workflow
1401  if (is_scalar($NewValue) || $NewValue instanceof Resource)
1402  {
1403  $NewValue = array($NewValue);
1404  }
1405 
1406  # delete existing resource references
1407  $this->ClearByField($Field);
1408 
1409  # add each reference
1410  foreach ($NewValue as $ReferenceOrId)
1411  {
1412  # initially issume it's a reference ID and not an object...
1413  $ReferenceId = $ReferenceOrId;
1414 
1415  # ... but get the reference ID if it's an object
1416  if ($ReferenceOrId instanceof Resource)
1417  {
1418  $ReferenceId = $ReferenceOrId->Id();
1419  }
1420 
1421  # skip blank reference IDs
1422  if (strlen(trim($ReferenceId)) < 1)
1423  {
1424  continue;
1425  }
1426 
1427  # skip reference IDs that don't look right
1428  if (!is_numeric($ReferenceId))
1429  {
1430  continue;
1431  }
1432 
1433  # skip references to the current resource
1434  if ($ReferenceId == $this->Id())
1435  {
1436  continue;
1437  }
1438 
1439  # add the reference to the references table
1440  $DB->Query("
1441  INSERT INTO ReferenceInts (
1442  FieldId,
1443  SrcResourceId,
1444  DstResourceId)
1445  VALUES (
1446  ".addslashes($Field->Id()).",
1447  ".addslashes($this->Id()).",
1448  ".addslashes($ReferenceId).")");
1449  }
1450  break;
1451 
1452  default:
1453  # ERROR OUT
1454  exit("<br>SPT - ERROR: attempt to set unknown resource field type<br>\n");
1455  break;
1456  }
1457 
1458  if ($UpdateModTime && !$this->IsTempResource())
1459  {
1460  # update modification timestamps
1461  global $G_User;
1462  $UserId = $G_User->IsLoggedIn() ? $G_User->Get("UserId") : -1;
1463  $DB->Query("DELETE FROM ResourceFieldTimestamps "
1464  ."WHERE ResourceId=".$this->Id." AND "
1465  ."FieldId=".$Field->Id() );
1466  $DB->Query("INSERT INTO ResourceFieldTimestamps "
1467  ."(ResourceId,FieldId,ModifiedBy,Timestamp) VALUES ("
1468  .$this->Id.",".$Field->Id().","
1469  .$UserId.",NOW())");
1470  }
1471  }
1476  function SetByField($Field, $NewValue) { $this->Set($Field, $NewValue); }
1477 
1478  # set value by field ID
1479  function SetByFieldId($FieldId, $NewValue)
1480  {
1481  $Field = $this->Schema->GetField($FieldId);
1482  $this->Set($Field, $NewValue);
1483  }
1484 
1485  # set qualifier by field name
1486  function SetQualifier($FieldName, $NewValue)
1487  {
1488  $Field = $this->Schema->GetFieldByName($FieldName);
1489  $this->SetQualifierByField($Field, $NewValue);
1490  }
1491 
1492  # set qualifier by field ID
1493  function SetQualifierByFieldId($FieldId, $NewValue)
1494  {
1495  $Field = $this->Schema->GetField($FieldId);
1496  $this->SetQualifierByField($Field, $NewValue);
1497  }
1498 
1499  # set qualifier using field object
1500  function SetQualifierByField($Field, $NewValue)
1501  {
1502  # if field uses qualifiers and uses item-level qualifiers
1503  if ($Field->UsesQualifiers() && $Field->HasItemLevelQualifiers())
1504  {
1505  # if qualifier object passed in
1506  if (is_object($NewValue))
1507  {
1508  # grab qualifier ID from object
1509  $QualifierId = $NewValue->Id();
1510  }
1511  else
1512  {
1513  # assume value passed in is qualifier ID
1514  $QualifierId = $NewValue;
1515  }
1516 
1517  # update qualifier value in database
1518  $DBFieldName = $Field->DBFieldName();
1519  $this->DB->Query("UPDATE Resources SET "
1520  .$DBFieldName."Qualifier = '".$QualifierId."' "
1521  ."WHERE ResourceId = ".$this->Id);
1522 
1523  # update local qualifier value
1524  $this->DBFields[$DBFieldName."Qualifier"] = $QualifierId;
1525  }
1526  }
1527 
1528  # clear value by field ID
1529  function ClearByFieldId($FieldId, $ValueToClear = NULL)
1530  {
1531  $Field = $this->Schema->GetField($FieldId);
1532  $this->ClearByField($Field, $ValueToClear);
1533  }
1534 
1535  # clear value using field object
1536  function Clear($Field, $ValueToClear = NULL)
1537  {
1538  # convert field name to object if necessary
1539  if (!is_object($Field))
1540  {
1541  $Field = $this->Schema->GetFieldByName($Field);
1542  }
1543 
1544  # grab commonly-used values for local use
1545  $DB = $this->DB;
1546  $ResourceId = $this->Id;
1547 
1548  # grab database field name
1549  $DBFieldName = $Field->DBFieldName();
1550 
1551  $UpdateModTime=FALSE;
1552 
1553  # store value in DB based on field type
1554  switch ($Field->Type())
1555  {
1563  if (strlen($this->DBFields[$DBFieldName])>0)
1564  {
1565  # clear value in DB
1566  $DB->Query("UPDATE Resources SET `"
1567  .$DBFieldName."` = NULL "
1568  ."WHERE ResourceId = ".$ResourceId);
1569 
1570  # clear value locally
1571  $this->DBFields[$DBFieldName] = NULL;
1572  $UpdateModTime=TRUE;
1573  }
1574  break;
1575 
1577  if (!is_null($this->DBFields[$DBFieldName."X"]) ||
1578  !is_null($this->DBFields[$DBFieldName."Y"]) )
1579  {
1580  # Clear DB Values
1581  $DB->Query("UPDATE Resources SET "
1582  ."`".$DBFieldName."X` = NULL ,"
1583  ."`".$DBFieldName."Y` = NULL "
1584  ."WHERE ResourceId = ".$ResourceId);
1585 
1586  # Clear local values
1587  $this->DBFields[$DBFieldName."X"] = NULL;
1588  $this->DBFields[$DBFieldName."Y"] = NULL;
1589  $UpdateModTime=TRUE;
1590  }
1591  break;
1592 
1594  if (!is_null($this->DBFields[$DBFieldName."Begin"]) ||
1595  !is_null($this->DBFields[$DBFieldName."End"]) ||
1596  !is_null($this->DBFields[$DBFieldName."Precision"]))
1597  {
1598  # clear date object values in DB
1599  $DB->Query("UPDATE Resources SET "
1600  .$DBFieldName."Begin = '', "
1601  .$DBFieldName."End = '', "
1602  .$DBFieldName."Precision = '' "
1603  ."WHERE ResourceId = ".$ResourceId);
1604 
1605  # clear value locally
1606  $this->DBFields[$DBFieldName."Begin"] = NULL;
1607  $this->DBFields[$DBFieldName."End"] = NULL;
1608  $this->DBFields[$DBFieldName."Precision"] = NULL;
1609  $UpdateModTime=TRUE;
1610  }
1611  break;
1612 
1614  $OldValue = $this->Get($Field);
1615 
1616  # if value to clear supplied
1617  if ($ValueToClear !== NULL)
1618  {
1619  # if supplied value is array
1620  if (is_array($ValueToClear))
1621  {
1622  # for each element of array
1623  foreach ($ValueToClear as $ClassificationId => $Dummy)
1624  {
1625  if (array_key_exists($ClassificationId, $OldValue))
1626  {
1627  # remove association with resource (if any)
1628  $this->RemoveAssociation("ResourceClassInts",
1629  "ClassificationId",
1630  $ClassificationId);
1631  $Class = new Classification($ClassificationId);
1632  $Class->RecalcResourceCount();
1633  $UpdateModTime=TRUE;
1634  }
1635  }
1636  }
1637  else
1638  {
1639  if (array_key_exists($ValueToClear, $OldValue))
1640  {
1641  # remove association with resource (if any)
1642  $this->RemoveAssociation("ResourceClassInts",
1643  "ClassificationId",
1644  $ValueToClear);
1645  $Class = new Classification($ValueToClear);
1646  $Class->RecalcResourceCount();
1647  $UpdateModTime=TRUE;
1648  }
1649  }
1650  }
1651  else
1652  {
1653  if (count($OldValue)>0)
1654  {
1655  # remove all associations for resource and field
1656  $this->RemoveAllAssociations("ResourceClassInts", "ClassificationId", $Field);
1657 
1658  # recompute resource count
1659  $Values = $this->Get($Field);
1660  foreach ($Values as $ClassificationId => $Dummy)
1661  {
1662  $Class = new Classification($ClassificationId);
1663  $Class->RecalcResourceCount();
1664  }
1665  $UpdateModTime=TRUE;
1666  }
1667  }
1668 
1669  # clear our classification cache
1670  if ($UpdateModTime)
1671  {
1672  unset($this->ClassificationCache);
1673  }
1674  break;
1675 
1678  $OldValue = $this->Get($Field);
1679  # if value to clear supplied
1680  if ($ValueToClear !== NULL)
1681  {
1682  # if incoming value is array
1683  if (is_array($ValueToClear))
1684  {
1685  # for each element of array
1686  foreach ($ValueToClear as $ControlledNameId =>
1687  $ControlledName)
1688  {
1689  if (array_key_exists($ControlledNameId, $OldValue))
1690  {
1691  # remove association with resource (if any)
1692  $this->RemoveAssociation("ResourceNameInts",
1693  "ControlledNameId",
1694  $ControlledNameId);
1695  $UpdateModTime=TRUE;
1696  }
1697  }
1698  }
1699  else
1700  {
1701  if (array_key_exists($ValueToClear, $OldValue))
1702  {
1703  # remove association with resource (if any)
1704  $this->RemoveAssociation("ResourceNameInts",
1705  "ControlledNameId",
1706  $ValueToClear);
1707  $UpdateModTime=TRUE;
1708  }
1709  }
1710  }
1711  else
1712  {
1713  if (count($OldValue)>0)
1714  {
1715  # remove all associations for resource and field
1716  $this->RemoveAllAssociations("ResourceNameInts", "ControlledNameId", $Field);
1717  $UpdateModTime=TRUE;
1718  }
1719  }
1720 
1721  if ($UpdateModTime)
1722  {
1723  # clear our controlled name cache
1724  unset($this->ControlledNameCache);
1725  unset($this->ControlledNameVariantCache);
1726  }
1727  break;
1728 
1730  # if value to clear supplied
1731  if ($ValueToClear !== NULL)
1732  {
1733  # convert value to array if necessary
1734  $Files = $ValueToClear;
1735  if (!is_array($Files)) { $Files = array($Files); }
1736 
1737  # convert values to objects if necessary
1738  foreach ($Files as $Index => $File)
1739  {
1740  if (!is_object($File))
1741  {
1742  $Files[$Index] = new File($File);
1743  }
1744  }
1745  }
1746  else
1747  {
1748  # use all files associated with resource
1749  $Files = $this->Get($Field, TRUE);
1750  }
1751 
1752  # delete files
1753  foreach ($Files as $File) { $File->Delete(); }
1754  break;
1755 
1757  # if value to clear supplied
1758  if ($ValueToClear !== NULL)
1759  {
1760  # convert value to array if necessary
1761  $Images = $ValueToClear;
1762  if (!is_array($Images)) { $Images = array($Images); }
1763 
1764  # convert values to objects if necessary
1765  foreach ($Images as $Index => $Image)
1766  {
1767  if (!is_object($Image))
1768  {
1769  $Images[$Index] = new SPTImage($Image);
1770  }
1771  }
1772  }
1773  else
1774  {
1775  # use all images associated with resource
1776  $Images = $this->Get($Field, TRUE);
1777  }
1778 
1779  # delete images if we are the last resource referencing
1780  # a particular image.
1781  foreach ($Images as $Image) {
1782  $Cnt = $this->DB->Query(
1783  "SELECT COUNT(*) AS Cnt FROM ResourceImageInts WHERE ".
1784  "ImageId=".$Image->Id(), "Cnt");
1785  if ($Cnt==1)
1786  $Image->Delete();
1787  }
1788 
1789  # remove connections to images
1790  $UpdateModTime = $this->RemoveAssociation(
1791  "ResourceImageInts", "ImageId", $Images, $Field);
1792  break;
1793 
1795  # remove references from the references table
1796  $DB->Query("
1797  DELETE FROM ReferenceInts
1798  WHERE FieldId = '".addslashes($Field->Id())."'
1799  AND SrcResourceId = '".addslashes($this->Id())."'");
1800  break;
1801 
1802  default:
1803  # ERROR OUT
1804  exit("<br>SPT - ERROR: attempt to clear unknown resource field type<br>\n");
1805  break;
1806  }
1807 
1808  if ($UpdateModTime && !$this->IsTempResource())
1809  {
1810  # update modification timestamps
1811  global $G_User;
1812  $UserId = $G_User->IsLoggedIn() ? $G_User->Get("UserId") : -1;
1813  $DB->Query("DELETE FROM ResourceFieldTimestamps "
1814  ."WHERE ResourceId=".$this->Id." AND "
1815  ."FieldId=".$Field->Id() );
1816  $DB->Query("INSERT INTO ResourceFieldTimestamps "
1817  ."(ResourceId,FieldId,ModifiedBy,Timestamp) VALUES ("
1818  .$this->Id.",".$Field->Id().","
1819  .$UserId.",NOW())");
1820  }
1821  }
1822  function ClearByField($Field, $ValueToClear = NULL)
1823  { $this->Clear($Field, $ValueToClear); }
1824 
1825 
1826  # --- Field-Specific or Type-Specific Attribute Retrieval Methods -------
1827 
1828  # return 2D array of classifications associated with resource
1829  # (first index is classification (field) name, second index is classification ID)
1830  function Classifications()
1831  {
1832  $DB = $this->DB;
1833 
1834  # start with empty array
1835  $Names = array();
1836 
1837  # for each controlled name
1838  $DB->Query("SELECT ClassificationName, MetadataFields.FieldName, "
1839  ."ResourceClassInts.ClassificationId FROM ResourceClassInts, "
1840  ."Classifications, MetadataFields "
1841  ."WHERE ResourceClassInts.ResourceId = ".$this->Id." "
1842  ."AND ResourceClassInts.ClassificationId = Classifications.ClassificationId "
1843  ."AND Classifications.FieldId = MetadataFields.FieldId ");
1844  while ($Record = $DB->FetchRow())
1845  {
1846  # add name to array
1847  $Names[$Record["FieldName"]][$Record["ClassificationId"]] =
1848  $Record["ClassificationName"];
1849  }
1850 
1851  # return array to caller
1852  return $Names;
1853  }
1854 
1855 
1856  # --- Ratings Methods ---------------------------------------------------
1857 
1858  # return cumulative rating (range is usually 0-100)
1859  function CumulativeRating() { return $this->CumulativeRating; }
1860 
1861  # return cumulative rating scaled to 1/10th (range is usually 0-10)
1863  {
1864  if ($this->CumulativeRating == NULL)
1865  {
1866  return NULL;
1867  }
1868  else
1869  {
1870  return intval(($this->CumulativeRating + 5) / 10);
1871  }
1872  }
1873 
1874  # return current number of ratings for resource
1875  function NumberOfRatings()
1876  {
1877  # if number of ratings not already set
1878  if (!isset($this->NumberOfRatings))
1879  {
1880  # obtain number of ratings
1881  $this->NumberOfRatings =
1882  $this->DB->Query("SELECT Count(*) AS NumberOfRatings "
1883  ."FROM ResourceRatings "
1884  ."WHERE ResourceId = ".$this->Id,
1885  "NumberOfRatings"
1886  );
1887 
1888  # recalculate cumulative rating if it looks erroneous
1889  if (($this->NumberOfRatings > 0) && !$this->CumulativeRating())
1890  {
1891  $this->UpdateCumulativeRating();
1892  }
1893  }
1894 
1895  # return number of ratings to caller
1896  return $this->NumberOfRatings;
1897  }
1898 
1899  # update individual rating for resource
1900  function Rating($NewRating = NULL, $UserId = NULL)
1901  {
1902  $DB = $this->DB;
1903 
1904  # if user ID not supplied
1905  if ($UserId == NULL)
1906  {
1907  # if user is logged in
1908  global $User;
1909  if ($User->IsLoggedIn())
1910  {
1911  # use ID of current user
1912  $UserId = $User->Get("UserId");
1913  }
1914  else
1915  {
1916  # return NULL to caller
1917  return NULL;
1918  }
1919  }
1920 
1921  # sanitize $NewRating
1922  if (!is_null($NewRating))
1923  {
1924  $NewRating = intval($NewRating);
1925  }
1926 
1927  # if there is a rating for resource and user
1928  $DB->Query("SELECT Rating FROM ResourceRatings "
1929  ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
1930  if ($Record = $DB->FetchRow())
1931  {
1932  # if new rating was supplied
1933  if ($NewRating != NULL)
1934  {
1935  # update existing rating
1936  $DB->Query("UPDATE ResourceRatings "
1937  ."SET Rating = ${NewRating}, DateRated = NOW() "
1938  ."WHERE UserId = ${UserId} AND ResourceId = ".$this->Id);
1939 
1940  # update cumulative rating value
1941  $this->UpdateCumulativeRating();
1942 
1943  # return value is new rating
1944  $Rating = $NewRating;
1945  }
1946  else
1947  {
1948  # get rating value to return to caller
1949  $Rating = $Record["Rating"];
1950  }
1951  }
1952  else
1953  {
1954  # if new rating was supplied
1955  if ($NewRating != NULL)
1956  {
1957  # add new rating
1958  $DB->Query("INSERT INTO ResourceRatings "
1959  ."(ResourceId, UserId, DateRated, Rating) "
1960  ."VALUES ("
1961  .$this->Id.", "
1962  ."${UserId}, "
1963  ."NOW(), "
1964  ."${NewRating})");
1965 
1966  # update cumulative rating value
1967  $this->UpdateCumulativeRating();
1968 
1969  # return value is new rating
1970  $Rating = $NewRating;
1971  }
1972  else
1973  {
1974  # return value is NULL
1975  $Rating = NULL;
1976  }
1977  }
1978 
1979  # return rating value to caller
1980  return $Rating;
1981  }
1982 
1983 
1984  # --- Resource Comment Methods ------------------------------------------
1985 
1986  # return comments as array of Message objects
1987  function Comments()
1988  {
1989  # read in comments if not already loaded
1990  if (!isset($this->Comments))
1991  {
1992  $this->DB->Query("SELECT MessageId FROM Messages "
1993  ."WHERE ParentId = ".$this->Id
1994  ." AND ParentType = 2 "
1995  ."ORDER BY DatePosted DESC");
1996  while ($MessageId = $this->DB->FetchField("MessageId"))
1997  {
1998  $this->Comments[] = new Message($MessageId);
1999  }
2000  }
2001 
2002  # return array of comments to caller
2003  return $this->Comments;
2004  }
2005 
2006  # return current number of comments
2007  function NumberOfComments()
2008  {
2009  # obtain number of comments if not already set
2010  if (!isset($this->NumberOfComments))
2011  {
2012  $this->NumberOfComments =
2013  $this->DB->Query("SELECT Count(*) AS NumberOfComments "
2014  ."FROM Messages "
2015  ."WHERE ParentId = ".$this->Id
2016  ." AND ParentType = 2",
2017  "NumberOfComments"
2018  );
2019  }
2020 
2021  # return number of comments to caller
2022  return $this->NumberOfComments;
2023  }
2024 
2025 
2026  # --- Permission Methods -------------------------------------------------
2027 
2035  function UserCanView(User $User)
2036  {
2037  return $this->CheckSchemaPermissions($User, "View" );
2038  }
2039 
2046  function UserCanEdit($User)
2047  {
2048  return $this->CheckSchemaPermissions($User, "Edit");
2049  }
2050 
2057  function UserCanAuthor($User)
2058  {
2059  return $this->CheckSchemaPermissions($User, "Author");
2060  }
2061 
2068  function UserCanViewField($User, $FieldOrFieldName)
2069  {
2070  return $this->CheckFieldPermissions( $User, $FieldOrFieldName, "View" );
2071  }
2072 
2079  function UserCanEditField($User, $FieldOrFieldName)
2080  {
2081  return $this->CheckFieldPermissions( $User, $FieldOrFieldName, "Edit" );
2082  }
2083 
2090  function UserCanAuthorField($User, $FieldOrFieldName)
2091  {
2092  return $this->CheckFieldPermissions( $User, $FieldOrFieldName, "Author" );
2093  }
2094 
2102  function UserCanModifyField($User, $FieldOrFieldName)
2103  {
2104  $CheckFn = "UserCan".(($this->Id()<0) ? "Author" : "Edit")."Field";
2105 
2106  return $this->$CheckFn($User, $FieldOrFieldName);
2107  }
2108 
2109  # ---- PRIVATE INTERFACE -------------------------------------------------
2110 
2111  private $DB;
2112  private $Schema;
2113  private $DBFields;
2114  private $Id;
2115  private $NumberOfRatings;
2116  private $CumulativeRating;
2117  private $NumberOfComments;
2118  private $Comments;
2119  private $LastStatus;
2120  private $ControlledNameCache;
2121  private $ControlledNameVariantCache;
2122  private $ClassificationCache;
2123  private $PermissionCache;
2124 
2131  private function CheckSchemaPermissions($User, $CheckType)
2132  {
2133  # checks against invalid reosurces should always fail
2134  if ($this->Status() !== 1) { return FALSE; }
2135 
2136  # construct a key to use for our permissions cache
2137  $CacheKey = "UserCan".$CheckType.$User->Id();
2138 
2139  # if we don't have a cached value for this perm, compute one
2140  if (!isset($this->PermissionCache[$CacheKey]))
2141  {
2142  # get privilege set for user
2143  $UserPrivs = $User->Privileges();
2144 
2145  # get privileges for schema
2146  $PermsFn = $CheckType."ingPrivileges";
2147  $SchemaPrivs = $this->Schema->$PermsFn();
2148 
2149  # check passes if user privileges are greater than resource set
2150  $CheckResult = $UserPrivs->IsGreaterThan($SchemaPrivs, $this);
2151 
2152  # allow plugins to modify result of permission check
2153  $SignalResult = $GLOBALS["AF"]->SignalEvent(
2154  "EVENT_RESOURCE_".strtoupper($CheckType)."_PERMISSION_CHECK",
2155  array(
2156  "Resource" => $this,
2157  "User" => $User,
2158  "Can".$CheckType => $CheckResult));
2159  $CheckResult = $SignalResult["Can".$CheckType];
2160 
2161  # save the result of this check in our cache
2162  $this->PermissionCache[$CacheKey] = $CheckResult;
2163  }
2164 
2165  # return the cached value
2166  return $this->PermissionCache[$CacheKey];
2167  }
2168 
2176  private function CheckFieldPermissions($User, $FieldOrFieldName, $CheckType)
2177  {
2178  # checks against invalid resources should always fail
2179  if ($this->Status() !== 1) { return FALSE; }
2180 
2181  # get field object (if not supplied)
2182  $Field = is_object($FieldOrFieldName) ? $FieldOrFieldName
2183  : $this->Schema->GetFieldByName($FieldOrFieldName);
2184 
2185  # checks against invalid fields should also fail
2186  if (!($Field instanceof MetadataField)) { return FALSE; }
2187 
2188  # construct a key to use for our permissions cache
2189  $CacheKey = "UserCan".$CheckType."Field".$Field->Id()."-".$User->Id();
2190 
2191  # if we don't have a cahced value, compute one
2192  if (!isset($this->PermissionCache[$CacheKey]))
2193  {
2194  # checks for disabled fields should not pass
2195  if (!$Field->Enabled())
2196  {
2197  $CheckResult = FALSE;
2198  }
2199  else
2200  {
2201  # be sure schema privs allow View/Edit/Author for this resource
2202  $SchemaCheckFn = "UserCan".$CheckType;
2203  if ($this->$SchemaCheckFn($User))
2204  {
2205  # get appropriate privilege set for field
2206  $PermsFn = $CheckType."ingPrivileges";
2207  $FieldPrivs = $Field->$PermsFn();
2208 
2209  # get privilege set for user
2210  $UserPrivs = $User->Privileges();
2211 
2212  # user can View/Edit/Author if privileges are greater than field set
2213  $CheckResult = $UserPrivs->IsGreaterThan($FieldPrivs, $this);
2214  }
2215  else
2216  {
2217  $CheckResult = FALSE;
2218  }
2219  }
2220 
2221  # allow plugins to modify result of permission check
2222  $SignalResult = $GLOBALS["AF"]->SignalEvent(
2223  "EVENT_FIELD_".strtoupper($CheckType)."_PERMISSION_CHECK", array(
2224  "Field" => $Field,
2225  "Resource" => $this,
2226  "User" => $User,
2227  "Can".$CheckType => $CheckResult));
2228  $CheckResult = $SignalResult["Can".$CheckType];
2229 
2230  # save the result of this check in our cache
2231  $this->PermissionCache[$CacheKey] = $CheckResult;
2232  }
2233 
2234  # return cached permission value
2235  return $this->PermissionCache[$CacheKey];
2236  }
2237 
2238  # recalculate and save cumulative rating value for resource
2239  private function UpdateCumulativeRating()
2240  {
2241  # grab totals from DB
2242  $this->DB->Query("SELECT COUNT(Rating) AS Count, "
2243  ."SUM(Rating) AS Total FROM ResourceRatings "
2244  ."WHERE ResourceId = ".$this->Id);
2245  $Record = $this->DB->FetchRow();
2246 
2247  # calculate new cumulative rating
2248  $this->CumulativeRating = round($Record["Total"] / $Record["Count"]);
2249 
2250  # save new cumulative rating in DB
2251  $this->DB->Query("UPDATE Resources "
2252  ."SET CumulativeRating = ".$this->CumulativeRating." "
2253  ."WHERE ResourceId = ".$this->Id);
2254  }
2255 
2266  private function AddAssociation($TableName, $FieldName, $Value, $Field = NULL)
2267  {
2268  # We should ignore duplicate key errors when doing inserts:
2269  $this->DB->SetQueryErrorsToIgnore( array(
2270  "/INSERT INTO ".$TableName."/" =>
2271  "/Duplicate entry '[0-9]+-[0-9]+' for key/"));
2272 
2273  # start out assuming no association will be added
2274  $AssociationAdded = FALSE;
2275 
2276  # convert new value to array if necessary
2277  $Values = is_array($Value) ? $Value : array($Value);
2278 
2279  # for each new value
2280  foreach ($Values as $Value)
2281  {
2282  # retrieve ID from value if necessary
2283  if (is_object($Value)) { $Value = $Value->Id(); }
2284 
2285  # Try to insert a new entry for this association.
2286  $this->DB->Query("INSERT INTO ".$TableName." SET"
2287  ." ResourceId = ".intval($this->Id)
2288  .", ".$FieldName." = ".intval($Value)
2289  .($Field ? ", FieldId = ".intval($Field->Id()) : ""));
2290 
2291  # If the insert ran without a duplicate key error,
2292  # then we added an assocation:
2293  if ($this->DB->IgnoredError() === FALSE)
2294  $AssociationAdded = TRUE;
2295  }
2296 
2297  # Clear ignored errors:
2298  $this->DB->SetQueryErrorsToIgnore( NULL );
2299 
2300  # report to caller whether association was added
2301  return $AssociationAdded;
2302  }
2303 
2314  private function RemoveAssociation($TableName, $FieldName, $Value, $Field = NULL)
2315  {
2316  # start out assuming no association will be removed
2317  $AssociationRemoved = FALSE;
2318 
2319  # convert value to array if necessary
2320  $Values = is_array($Value) ? $Value : array($Value);
2321 
2322  # for each value
2323  foreach ($Values as $Value)
2324  {
2325  # retrieve ID from value if necessary
2326  if (is_object($Value)) { $Value = $Value->Id(); }
2327 
2328  # remove any intersections with target ID from DB
2329  $this->DB->Query("DELETE FROM ".$TableName
2330  ." WHERE ResourceId = ".intval($this->Id)
2331  .($Field ? " AND FieldId = ".intval($Field->Id()) : "")
2332  ." AND ".$FieldName." = ".intval($Value));
2333  }
2334 
2335  # report to caller whether association was added
2336  return $AssociationRemoved;
2337  }
2338 
2339  # remove all intersections for resource and field (if any)
2340  private function RemoveAllAssociations($TableName, $TargetFieldName, $Field)
2341  {
2342  # retrieve list of entries for this field and resource
2343  $Entries = $this->Get($Field);
2344 
2345  # Divide them into chunks of not more than 50:
2346  foreach (array_chunk($Entries, 100, TRUE) as $Chunk)
2347  {
2348  # Construct a query that will remove assocations in this chunk:
2349  $this->DB->Query("DELETE FROM ".$TableName
2350  ." WHERE ResourceId = ".intval($this->Id)
2351  ." AND ".$TargetFieldName." IN "
2352  ."(".implode(",", array_keys($Chunk)).")");
2353  }
2354  }
2355 }
GetByField($FieldNameOrObject, $ReturnObject=FALSE, $IncludeVariants=FALSE)
Old method for retrieving values, deprecated in favor of Get().
Definition: Resource.php:644
GetFilesForResource($ResourceOrResourceId, $ReturnObjects=TRUE)
Retrieve all files (names or objects) for specified resource.
Definition: FileFactory.php:38
SetQualifier($FieldName, $NewValue)
Definition: Resource.php:1486
Metadata schema (in effect a Factory class for MetadataField).
Abstraction for forum messages and resource comments.
Definition: Message.php:15
SQL database abstraction object with smart query caching.
UserCanModifyField($User, $FieldOrFieldName)
Check whether user is allowed to modify (Edit for perm resources, Author for temp) specified metadata...
Definition: Resource.php:2102
GetAsArray($IncludeDisabledFields=FALSE, $ReturnObjects=TRUE)
Retrieve all resource values as an array.
Definition: Resource.php:679
Set($FieldNameOrObject, $NewValue, $Reset=FALSE)
Set value using field name or field object.
Definition: Resource.php:972
Id()
Retrieve numerical resource ID.
Definition: Resource.php:256
UserCanEditField($User, $FieldOrFieldName)
Check whether user is allowed to edit specified metadata field.
Definition: Resource.php:2079
SetQualifierByField($Field, $NewValue)
Definition: Resource.php:1500
Rating($NewRating=NULL, $UserId=NULL)
Definition: Resource.php:1900
Status()
Retrieve result of last operation if available.
Definition: Resource.php:250
NumberOfComments()
Definition: Resource.php:2007
NumberOfRatings()
Definition: Resource.php:1875
GetQualifier($FieldName, $ReturnObject=TRUE)
Retrieve qualifier by field name.
Definition: Resource.php:741
Factory object for Folder class, used to retrieve and manage Folders and groups of Folders...
Copy($FileToCopy)
Create copy of File and return to caller.
Definition: FileFactory.php:84
Metadata type representing non-hierarchical controlled vocabulary values.
UserCanEdit($User)
Determine if the given user can edit the resource.
Definition: Resource.php:2046
const MDFTYPE_CONTROLLEDNAME
CWIS-specific user factory class.
PHP
Definition: OAIClient.php:39
Factory for manipulating File objects.
Definition: FileFactory.php:13
GetQualifierByFieldId($FieldId, $ReturnObject=TRUE)
Retrieve qualifier by field ID.
Definition: Resource.php:755
Encapsulates a full-size, preview, and thumbnail image.
Definition: SPTImage.php:13
UserCanAuthorField($User, $FieldOrFieldName)
Check whether user is allowed to author specified metadata field.
Definition: Resource.php:2090
UserCanView(User $User)
Determine if the given user can view the resource, e.g., on the full record page. ...
Definition: Resource.php:2035
Clear($Field, $ValueToClear=NULL)
Definition: Resource.php:1536
UserCanAuthor($User)
Determine if the given user can edit the resource.
Definition: Resource.php:2057
GetByFieldId($FieldId, $ReturnObject=FALSE, $IncludeVariants=FALSE)
Retrieve value using field ID.
Definition: Resource.php:661
IsTempResource($NewSetting=NULL)
Get/set whether resource is a temporary record.
Definition: Resource.php:270
Get($FieldNameOrObject, $ReturnObject=FALSE, $IncludeVariants=FALSE)
Retrieve value using field name or field object.
Definition: Resource.php:348
SetByField($Field, $NewValue)
Method replaced by Resource::Set(), preserved for backward compatibility.
Definition: Resource.php:1476
Object representing a locally-defined type of metadata field.
__construct($ResourceId)
Object constructor for loading an existing resource.
Definition: Resource.php:23
GetMapped($MappedName, $ReturnObject=FALSE, $IncludeVariants=FALSE)
Retrieve value using standard (mapped) field name.
Definition: Resource.php:725
Represents a "resource" in CWIS.
Definition: Resource.php:13
GetQualifierByField($Field, $ReturnObject=TRUE)
Retrieve qualifier by Field object.
Definition: Resource.php:769
ClearByFieldId($FieldId, $ValueToClear=NULL)
Definition: Resource.php:1529
const CLASSSTAT_OK
Status code indicating operation completed successfully.
SetQualifierByFieldId($FieldId, $NewValue)
Definition: Resource.php:1493
SchemaId()
Retrieve ID of schema for resource.
Definition: Resource.php:262
ScaledCumulativeRating()
Definition: Resource.php:1862
const UPDATEMETHOD_ONRECORDCREATE
static Create($SchemaId)
Create a new resource.
Definition: Resource.php:59
UserCanViewField($User, $FieldOrFieldName)
Check whether user is allowed to view specified metadata field.
Definition: Resource.php:2068
Metadata type representing hierarchical ("Tree") controlled vocabulary values.
SetByFieldId($FieldId, $NewValue)
Definition: Resource.php:1479
Classifications()
Definition: Resource.php:1830
ClearByField($Field, $ValueToClear=NULL)
Definition: Resource.php:1822
Class representing a stored (usually uploaded) file.
Definition: File.php:13
Factory for Resource objects.
CWIS-specific user class.
Definition: CWUser.php:13
CumulativeRating()
Definition: Resource.php:1859
FieldIsSet($FieldNameOrObject, $IgnorePadding=FALSE)
Determine if the value for a field is set.
Definition: Resource.php:900
Delete()
Remove resource (and accompanying associations) from database and delete any associated files...
Definition: Resource.php:143