CWIS Developer Documentation
MetadataField.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: MetadataField.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2012 Edward Almasy and Internet Scout
7 # http://scout.wisc.edu
8 #
9 
11 
12  # ---- PUBLIC INTERFACE --------------------------------------------------
13 
14  # Update methods for timestamp fields
15  const UPDATEMETHOD_NOAUTOUPDATE = "NoAutoUpdate";
16  const UPDATEMETHOD_ONRECORDCREATE = "OnRecordCreate";
17  const UPDATEMETHOD_BUTTON = "Button";
18  const UPDATEMETHOD_ONRECORDEDIT = "OnRecordEdit";
19  const UPDATEMETHOD_ONRECORDCHANGE = "OnRecordChange";
20 
21  # values for the *UserIsValue fields
22  const USERISVALUE_OR = -1;
23  const USERISVALUE_UNSET = 0;
24  const USERISVALUE_AND = 1;
25 
26  # get current error status of object
27  function Status() { return $this->ErrorStatus; }
28 
29  # get/set type of field as enumerated value
30  function Type($NewValue = DB_NOVALUE)
31  {
32  # if new value supplied
33  if (($NewValue != DB_NOVALUE)
34  && ($NewValue != MetadataField::$FieldTypePHPEnums[
35  $this->DBFields["FieldType"]]))
36  {
37  # update database fields and store new type
38  $this->ModifyField(NULL, $NewValue);
39  }
40 
41  # return type to caller
42  return MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
43  }
44 
45  # get type of field as type name (string)
46  function TypeAsName()
47  {
48  return $this->DBFields["FieldType"];
49  }
50 
51  # get displayable name for the field
52  # first tries to get label but uses field name if label isn't set
53  function GetDisplayName()
54  {
55  return strlen($this->Label()) ? $this->Label() : $this->Name();
56  }
57 
58  # get/set name of field
59  # once the name is set to a valid value, it cannot be changed
60  function Name($NewName = DB_NOVALUE)
61  {
62  # if new name specified
63  if ($NewName != DB_NOVALUE
64  && trim($NewName) != $this->DBFields["FieldName"])
65  {
66  # if field name is invalid
67  $NewName = trim($NewName);
68  if (!preg_match("/^[[:alnum:] \(\)]+$/", $NewName))
69  {
70  # set error status to indicate illegal name
71  $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALNAME;
72  }
73  else
74  {
75  # check for duplicate name
76  $DuplicateCount = $this->DB->Query("
77  SELECT COUNT(*) AS RecordCount FROM MetadataFields
78  WHERE FieldName = '".addslashes($NewName)."'",
79  "RecordCount");
80 
81  # if field name is duplicate
82  if ($DuplicateCount > 0)
83  {
84  # set error status to indicate duplicate name
85  $this->ErrorStatus = MetadataSchema::MDFSTAT_DUPLICATENAME;
86  }
87  else
88  {
89  # modify database declaration to reflect new field name
90  $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
91  $this->ModifyField($NewName);
92  }
93  }
94  }
95 
96  # return value to caller
97  return $this->DBFields["FieldName"];
98  }
99 
100  # get/set label of field
101  public function Label($NewLabel = DB_NOVALUE)
102  {
103  $ValidValueExp = '/^[[:alnum:] ]*$/';
104  $Value = $this->DBFields["Label"];
105 
106  # if a new label was specified
107  if ($NewLabel !== DB_NOVALUE && trim($NewLabel) != $Value)
108  {
109  $NewLabel = trim($NewLabel);
110 
111  # if field label is valid
112  if (preg_match($ValidValueExp, $NewLabel))
113  {
114  $this->UpdateValue("Label", $NewLabel);
115  $Value = $NewLabel;
116  }
117 
118  # the field label is invalid
119  else
120  {
121  $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALLABEL;
122  }
123  }
124 
125  return $Value;
126  }
127 
128  # get associative array (enumeration => string) containing field types we can convert to
130  {
131  # determine type list based on our type
132  switch ($this->Type())
133  {
139  $AllowedTypes = array(
141  MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
142  MetadataSchema::MDFTYPE_NUMBER => "Number",
145  );
146  break;
147 
150  $AllowedTypes = array(
151  MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
152  MetadataSchema::MDFTYPE_OPTION => "Option",
153  );
154  break;
155 
157  $AllowedTypes = array(
160  );
161  break;
162 
164  $AllowedTypes = array(
166  MetadataSchema::MDFTYPE_IMAGE => "Still Image",
167  );
168  break;
169 
174  default:
175  $AllowedTypes = array();
176  break;
177  }
178 
179  # return type list to caller
180  return $AllowedTypes;
181  }
182 
183  # get/set whether item is temporary instance
184  function IsTempItem($NewSetting = NULL)
185  {
186  $ItemTableName = "MetadataFields";
187  $ItemIdFieldName = "FieldId";
188  $ItemFactoryObjectName = "MetadataSchema";
189  $ItemAssociationTables = array(
190  "FieldQualifierInts",
191  );
192  $ItemAssociationFieldName = "MetadataFieldId";
193 
194  # if new temp item setting supplied
195  if (!is_null($NewSetting))
196  {
197  # if caller requested to switch
198  if (($this->Id() < 0 && $NewSetting == FALSE)
199  || ($this->Id() >= 0 && $NewSetting == TRUE))
200  {
201  # if field name is invalid
202  if (strlen($this->NormalizeFieldNameForDB($this->Name())) < 1)
203  {
204  # set error status to indicate illegal name
205  $this->ErrorStatus = MetadataSchema::MDFSTAT_ILLEGALNAME;
206  }
207  else
208  {
209  # lock DB tables to prevent next ID from being grabbed
210  $DB = $this->DB;
211  $DB->Query("LOCK TABLES ".$ItemTableName." WRITE,".
212  "APSessions WRITE, APSessionData WRITE");
213 
214  # get next temp item ID
215  $OldItemId = $this->Id();
216  $Factory = new $ItemFactoryObjectName();
217  if ($NewSetting == TRUE)
218  {
219  $NewId = $Factory->GetNextTempItemId();
220  }
221  else
222  {
223  $NewId = $Factory->GetNextItemId();
224  }
225 
226  # change item ID
227  $DB->Query("UPDATE ".$ItemTableName." SET ".$ItemIdFieldName." = ".
228  $NewId. " WHERE ".$ItemIdFieldName." = ".$OldItemId);
229 
230  # release DB tables
231  $DB->Query("UNLOCK TABLES");
232 
233  # change associations
234  foreach ($ItemAssociationTables as $TableName)
235  {
236  $DB->Query("UPDATE ".$TableName." SET ".$ItemAssociationFieldName." = ".
237  $NewId. " WHERE ".$ItemAssociationFieldName." = ".$OldItemId);
238  }
239 
240  # if changing item from temp to non-temp
241  if ($NewSetting == FALSE)
242  {
243  # add any needed database fields and/or entries
244  $this->AddDatabaseFields();
245 
246  # set field order values for new field
247  try
248  {
251 
252  $DisplayOrder->AppendItem($NewId, "MetadataField");
253  $EditOrder->AppendItem($NewId, "MetadataField");
254  } catch (Exception $Exception) {}
255  }
256 
257  # update metadata field id
258  $this->DBFields["FieldId"] = $NewId;
259  }
260  }
261  }
262 
263  # report to caller whether we are a temp item
264  return ($this->Id() < 0) ? TRUE : FALSE;
265  }
266 
267  # get field attributes
268  function Id() { return $this->DBFields["FieldId"]; }
269  function DBFieldName() { return $this->DBFields["DBFieldName"]; }
270 
271  # get/set field attributes
272  function Description($NewValue = DB_NOVALUE)
273  { return $this->UpdateValue("Description", $NewValue); }
274  function Instructions($NewValue = DB_NOVALUE)
275  { return $this->UpdateValue("Instructions", $NewValue); }
276  function Owner($NewValue = DB_NOVALUE)
277  { return $this->UpdateValue("Owner", $NewValue); }
278  function RequiredBySPT($NewValue = DB_NOVALUE)
279  { return $this->UpdateBoolValue("RequiredBySPT", $NewValue); }
280  function Enabled($NewValue = DB_NOVALUE)
281  { return $this->UpdateBoolValue("Enabled", $NewValue); }
282  function Optional($NewValue = DB_NOVALUE)
283  { return $this->UpdateBoolValue("Optional", $NewValue); }
284  function Editable($NewValue = DB_NOVALUE)
285  { return $this->UpdateBoolValue("Editable", $NewValue); }
286  function Viewable($NewValue = DB_NOVALUE)
287  { return $this->UpdateBoolValue("Viewable", $NewValue); }
288  function AllowMultiple($NewValue = DB_NOVALUE)
289  { return $this->UpdateBoolValue("AllowMultiple", $NewValue); }
290  function IncludeInKeywordSearch($NewValue = DB_NOVALUE)
291  { return $this->UpdateBoolValue("IncludeInKeywordSearch", $NewValue); }
292  function IncludeInAdvancedSearch($NewValue = DB_NOVALUE)
293  { return $this->UpdateBoolValue("IncludeInAdvancedSearch", $NewValue); }
294  function IncludeInSortOptions($NewValue = DB_NOVALUE)
295  { return $this->UpdateBoolValue("IncludeInSortOptions", $NewValue); }
296  function IncludeInRecommender($NewValue = DB_NOVALUE)
297  { return $this->UpdateBoolValue("IncludeInRecommender", $NewValue); }
298  function TextFieldSize($NewValue = DB_NOVALUE)
299  { return $this->UpdateIntValue("TextFieldSize", $NewValue); }
300  function MaxLength($NewValue = DB_NOVALUE)
301  { return $this->UpdateIntValue("MaxLength", $NewValue); }
302  function ParagraphRows($NewValue = DB_NOVALUE)
303  { return $this->UpdateIntValue("ParagraphRows", $NewValue); }
304  function ParagraphCols($NewValue = DB_NOVALUE)
305  { return $this->UpdateIntValue("ParagraphCols", $NewValue); }
306  function MinValue($NewValue = DB_NOVALUE)
307  { return $this->UpdateFloatValue("MinValue", $NewValue); }
308  function MaxValue($NewValue = DB_NOVALUE)
309  { return $this->UpdateFloatValue("MaxValue", $NewValue); }
310  function FlagOnLabel($NewValue = DB_NOVALUE)
311  { return $this->UpdateValue("FlagOnLabel", $NewValue); }
312  function FlagOffLabel($NewValue = DB_NOVALUE)
313  { return $this->UpdateValue("FlagOffLabel", $NewValue); }
314  function DateFormat($NewValue = DB_NOVALUE)
315  { return $this->UpdateValue("DateFormat", $NewValue); }
316  function SearchWeight($NewValue = DB_NOVALUE)
317  { return $this->UpdateIntValue("SearchWeight", $NewValue); }
318  function RecommenderWeight($NewValue = DB_NOVALUE)
319  { return $this->UpdateIntValue("RecommenderWeight", $NewValue); }
320  function MaxHeight($NewValue = DB_NOVALUE)
321  { return $this->UpdateIntValue("MaxHeight", $NewValue); }
322  function MaxWidth($NewValue = DB_NOVALUE)
323  { return $this->UpdateIntValue("MaxWidth", $NewValue); }
324  function MaxPreviewHeight($NewValue = DB_NOVALUE)
325  { return $this->UpdateIntValue("MaxPreviewHeight", $NewValue); }
326  function MaxPreviewWidth($NewValue = DB_NOVALUE)
327  { return $this->UpdateIntValue("MaxPreviewWidth", $NewValue); }
328  function MaxThumbnailHeight($NewValue = DB_NOVALUE)
329  { return $this->UpdateIntValue("MaxThumbnailHeight", $NewValue); }
330  function MaxThumbnailWidth($NewValue = DB_NOVALUE)
331  { return $this->UpdateIntValue("MaxThumbnailWidth", $NewValue); }
332  function DefaultAltText($NewValue = DB_NOVALUE)
333  { return $this->UpdateValue("DefaultAltText", $NewValue); }
334  function UsesQualifiers($NewValue = DB_NOVALUE)
335  { return $this->UpdateBoolValue("UsesQualifiers", $NewValue); }
336  function ShowQualifiers($NewValue = DB_NOVALUE)
337  { return $this->UpdateBoolValue("ShowQualifiers", $NewValue); }
338  function DefaultQualifier($NewValue = DB_NOVALUE)
339  { return $this->UpdateValue("DefaultQualifier", $NewValue); }
340  function AllowHTML($NewValue = DB_NOVALUE)
341  { return $this->UpdateBoolValue("AllowHTML", $NewValue); }
342  function UseWysiwygEditor($NewValue = DB_NOVALUE)
343  { return $this->UpdateBoolValue("UseWysiwygEditor", $NewValue); }
344  function UseForOaiSets($NewValue = DB_NOVALUE)
345  { return $this->UpdateBoolValue("UseForOaiSets", $NewValue); }
346  function NumAjaxResults($NewValue = DB_NOVALUE)
347  { return $this->UpdateIntValue("NumAjaxResults", $NewValue); }
348  function ViewingPrivilege($NewValue = DB_NOVALUE)
349  { return $this->UpdateConstValue("ViewingPrivilege", $NewValue); }
350  function AuthoringPrivilege($NewValue = DB_NOVALUE)
351  { return $this->UpdateConstValue("AuthoringPrivilege", $NewValue); }
352  function EditingPrivilege($NewValue = DB_NOVALUE)
353  { return $this->UpdateConstValue("EditingPrivilege", $NewValue); }
354  function ImagePreviewPrivilege($NewValue = DB_NOVALUE)
355  { return $this->UpdateConstValue("ImagePreviewPrivilege", $NewValue); }
356  function TreeBrowsingPrivilege($NewValue = DB_NOVALUE)
357  { return $this->UpdateConstValue("TreeBrowsingPrivilege", $NewValue); }
358  function EnableOnOwnerReturn($NewValue = DB_NOVALUE)
359  { return $this->UpdateBoolValue("EnableOnOwnerReturn", $NewValue); }
360  function ViewingUserIsValue($NewValue = DB_NOVALUE)
361  { return $this->UpdateConstValue("ViewingUserIsValue", $NewValue, "MetadataField"); }
362  function AuthoringUserIsValue($NewValue = DB_NOVALUE)
363  { return $this->UpdateConstValue("AuthoringUserIsValue", $NewValue, "MetadataField"); }
364  function EditingUserIsValue($NewValue = DB_NOVALUE)
365  { return $this->UpdateConstValue("EditingUserIsValue", $NewValue, "MetadataField"); }
366  function ViewingUserValue($NewValue = DB_NOVALUE)
367  { return $this->UpdateIntValue("ViewingUserValue", $NewValue, "MetadataField"); }
368  function AuthoringUserValue($NewValue = DB_NOVALUE)
369  { return $this->UpdateIntValue("AuthoringUserValue", $NewValue, "MetadataField"); }
370  function EditingUserValue($NewValue = DB_NOVALUE)
371  { return $this->UpdateIntValue("EditingUserValue", $NewValue, "MetadataField"); }
372 
373  function UserPrivilegeRestrictions($NewValue = DB_NOVALUE)
374  {
375  # new value
376  if ($NewValue != DB_NOVALUE)
377  {
378  $NewValue = serialize((array) $NewValue);
379  }
380 
381  $Value = $this->UpdateValue("UserPrivilegeRestrictions", $NewValue);
382 
383  # value set
384  if (strlen($Value))
385  {
386  $Value = (array) unserialize($Value);
387  }
388 
389  # no value set, set it to an empty array
390  else
391  {
392  $Value = $this->UserPrivilegeRestrictions(array());
393  }
394 
395  return $Value;
396  }
397 
398  function PointPrecision($NewValue = DB_NOVALUE)
399  {
400  if ($NewValue !== DB_NOVALUE && $this->Id() >= 0
401  && $this->Type() == MetadataSchema::MDFTYPE_POINT)
402  {
403  $OldValue = $this->UpdateValue("PointPrecision", DB_NOVALUE);
404 
405  if ($NewValue != $OldValue)
406  {
407  $Decimals = $this->UpdateValue("PointDecimalDigits", DB_NOVALUE);
408  $TotalDigits = $NewValue + $Decimals;
409 
410  $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
411  ."`".$this->DBFields["DBFieldName"]."X` "
412  ."DECIMAL(".$TotalDigits.",".$Decimals.")");
413  $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
414  ."`".$this->DBFields["DBFieldName"]."Y` "
415  ."DECIMAL(".$TotalDigits.",".$Decimals.")");
416  }
417  }
418 
419  return $this->UpdateValue("PointPrecision", $NewValue);
420  }
421 
422  function PointDecimalDigits($NewValue = DB_NOVALUE)
423  {
424  if ($NewValue !== DB_NOVALUE && $this->Id() >= 0
425  && $this->Type() == MetadataSchema::MDFTYPE_POINT)
426  {
427  $OldValue = $this->UpdateValue("PointDecimalDigits", DB_NOVALUE);
428 
429  if ($NewValue != $OldValue)
430  {
431  $Precision = $this->UpdateValue("PointPrecision", DB_NOVALUE);
432 
433  $TotalDigits = $NewValue + $Precision;
434 
435  $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
436  ."`".$this->DBFields["DBFieldName"]."X` "
437  ."DECIMAL(".$TotalDigits.",".$NewValue.")");
438  $this->DB->Query("ALTER TABLE Resources MODIFY COLUMN "
439  ."`".$this->DBFields["DBFieldName"]."Y` "
440  ."DECIMAL(".$TotalDigits.",".$NewValue.")");
441  }
442  }
443 
444  return $this->UpdateValue("PointDecimalDigits", $NewValue);
445  }
446 
447  function DefaultValue($NewValue = DB_NOVALUE)
448  {
449  if ($this->Type() == MetadataSchema::MDFTYPE_POINT)
450  {
451  # valid value given
452  if ($NewValue !== DB_NOVALUE &&
453  isset($NewValue["X"]) && isset($NewValue["Y"]))
454  {
455  $NewValue = $NewValue["X"].",".$NewValue["Y"];
456  }
457 
458  # invalid value given
459  else
460  {
461  $NewValue = DB_NOVALUE;
462  }
463 
464  $Value = $this->UpdateValue("DefaultValue", $NewValue);
465 
466  if (is_array($Value))
467  {
468  $tmp = explode(",", $Value);
469 
470  if (count($tmp)==2)
471  {
472  return array("X" => $tmp[0], "Y" => $tmp[1]);
473  }
474  }
475 
476  return array("X" => NULL, "Y" => NULL);
477  }
478 
479  else if ($this->Type() == MetadataSchema::MDFTYPE_OPTION)
480  {
481  # multiple default values to set
482  if (is_array($NewValue))
483  {
484  # empty array
485  if (count($NewValue) == 0)
486  {
487  $NewValue = NULL;
488  }
489 
490  # multiple defaults are allowed
491  else if ($this->AllowMultiple())
492  {
493  $NewValue = serialize($NewValue);
494  }
495 
496  # only one default is allowed so get the first one
497  else
498  {
499  $NewValue = array_shift($NewValue);
500  }
501  }
502 
503  $Result = $this->UpdateValue("DefaultValue", $NewValue);
504 
505  return empty($Result) || is_numeric($Result) ?
506  $Result : unserialize($Result);
507  }
508 
509  return $this->UpdateValue("DefaultValue", $NewValue);
510  }
511 
517  function UpdateMethod($NewValue = DB_NOVALUE)
518  {
519  return $this->UpdateValue("UpdateMethod", $NewValue);
520  }
521 
522  # get possible values (only meaningful for Trees, Controlled Names, Options,
523  # Flags, and Users)
524  # (index for returned array is IDs for values)
525  function GetPossibleValues($MaxNumberOfValues = NULL, $Offset=0)
526  {
527  # retrieve values based on field type
528  switch ($this->Type())
529  {
531  $QueryString = "SELECT ClassificationId, ClassificationName"
532  ." FROM Classifications WHERE FieldId = ".$this->Id()
533  ." ORDER BY ClassificationName";
534  if ($MaxNumberOfValues)
535  {
536  $QueryString .= " LIMIT ".intval($MaxNumberOfValues)." OFFSET "
537  .intval($Offset);
538  }
539  $this->DB->Query($QueryString);
540  $PossibleValues = $this->DB->FetchColumn(
541  "ClassificationName", "ClassificationId");
542  break;
543 
546  $QueryString = "SELECT ControlledNameId, ControlledName"
547  ." FROM ControlledNames WHERE FieldId = ".$this->Id()
548  ." ORDER BY ControlledName";
549  if ($MaxNumberOfValues)
550  {
551  $QueryString .= " LIMIT ".intval($MaxNumberOfValues)." OFFSET "
552  .intval($Offset);
553  }
554  $this->DB->Query($QueryString);
555  $PossibleValues = $this->DB->FetchColumn(
556  "ControlledName", "ControlledNameId");
557  break;
558 
560  $PossibleValues[0] = $this->FlagOffLabel();
561  $PossibleValues[1] = $this->FlagOnLabel();
562  break;
563 
565  $UserFactory = new UserFactory($this->DB);
566  $Restrictions = $this->UserPrivilegeRestrictions();
567  $PossibleValues = array();
568 
569  if (count($Restrictions))
570  {
571  $PossibleValues = call_user_func_array(
572  array($UserFactory, "GetUsersWithPrivileges"),
573  $Restrictions);
574  }
575 
576  else
577  {
578  $Users = $UserFactory->GetMatchingUsers(".*.");
579 
580  foreach ($Users as $Id => $Data)
581  {
582  $PossibleValues[$Id] = $Data["UserName"];
583  }
584  }
585 
586  break;
587 
588  default:
589  # for everything else return an empty array
590  $PossibleValues = array();
591  break;
592  }
593 
594  # return array of possible values to caller
595  return $PossibleValues;
596  }
597 
598  # get count of possible values (only meaningful for Trees, Controlled Names,
599  # Options, and Users)
601  {
602  # retrieve values based on field type
603  switch ($this->Type())
604  {
606  $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
607  ." FROM Classifications WHERE FieldId = ".$this->Id(),
608  "ValueCount");
609  break;
610 
613  $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
614  ." FROM ControlledNames WHERE FieldId = ".$this->Id(),
615  "ValueCount");
616  break;
617 
619  $Count = 2;
620  break;
621 
623  $Count = count($this->GetPossibleValues());
624  break;
625 
626  default:
627  # for everything else return an empty array
628  $Count = 0;
629  break;
630  }
631 
632  # return count of possible values to caller
633  return $Count;
634  }
635 
636  # get ID for specified value (only meaningful for Trees / Controlled Names / Options)
637  # (returns NULL if value not found)
638  function GetIdForValue($Value)
639  {
640  # retrieve ID based on field type
641  switch ($this->Type())
642  {
644  $Id = $this->DB->Query("SELECT ClassificationId FROM Classifications"
645  ." WHERE ClassificationName = '".addslashes($Value)."'"
646  ." AND FieldId = ".$this->Id(),
647  "ClassificationId");
648  break;
649 
652  $Id = $this->DB->Query("SELECT ControlledNameId FROM ControlledNames"
653  ." WHERE ControlledName = '".addslashes($Value)."'"
654  ." AND FieldId = ".$this->Id(),
655  "ControlledNameId");
656  break;
657 
658  default:
659  # for everything else return NULL
660  $Id = NULL;
661  break;
662  }
663 
664  # return ID for value to caller
665  return $Id;
666  }
667 
668  # get value for specified ID (only meaningful for Trees / Controlled Names / Options)
669  # (returns NULL if ID not found)
670  function GetValueForId($Id)
671  {
672  # retrieve ID based on field type
673  switch ($this->Type())
674  {
676  $Value = $this->DB->Query("SELECT ClassificationName FROM Classifications"
677  ." WHERE ClassificationId = '".intval($Id)."'"
678  ." AND FieldId = ".$this->Id(),
679  "ClassificationName");
680  break;
681 
684  $Value = $this->DB->Query("SELECT ControlledName FROM ControlledNames"
685  ." WHERE ControlledNameId = '".intval($Id)."'"
686  ." AND FieldId = ".$this->Id(),
687  "ControlledName");
688  break;
689 
690  default:
691  # for everything else return NULL
692  $Value = NULL;
693  break;
694  }
695 
696  # return ID for value to caller
697  return $Value;
698  }
699 
700 
701 
702  # get/set whether field uses item-level qualifiers
703  function HasItemLevelQualifiers($NewValue = DB_NOVALUE)
704  {
705  # if value provided different from present value
706  if (($NewValue != DB_NOVALUE)
707  && ($NewValue != $this->DBFields["HasItemLevelQualifiers"]))
708  {
709  # check if qualifier column currently exists
710  $QualColName = $this->DBFieldName()."Qualifier";
711  $QualColExists = $this->DB->FieldExists("Resources", $QualColName);
712 
713  # if new value indicates qualifiers should now be used
714  if ($NewValue == TRUE)
715  {
716  # if qualifier column does not exist in DB for this field
717  if ($QualColExists == FALSE)
718  {
719  # add qualifier column in DB for this field
720  $this->DB->Query("ALTER TABLE Resources ADD COLUMN `"
721  .$QualColName."` INT");
722  }
723  }
724  else
725  {
726  # if qualifier column exists in DB for this field
727  if ($QualColExists == TRUE)
728  {
729  # remove qualifier column from DB for this field
730  $this->DB->Query("ALTER TABLE Resources DROP COLUMN `"
731  .$QualColName."`");
732  }
733  }
734  }
735 
736  return $this->UpdateValue("HasItemLevelQualifiers", $NewValue);
737  }
738 
739  # get list of qualifiers associated with field
741  {
742  # start with empty list
743  $List = array();
744 
745  # for each associated qualifier
746  $this->DB->Query("SELECT QualifierId FROM FieldQualifierInts"
747  ." WHERE MetadataFieldId = ".$this->DBFields["FieldId"]);
748  while ($Record = $this->DB->FetchRow())
749  {
750  # load qualifier object
751  $Qual = new Qualifier($Record["QualifierId"]);
752 
753  # add qualifier ID and name to list
754  $List[$Qual->Id()] = $Qual->Name();
755  }
756 
757  # return list to caller
758  return $List;
759  }
760 
761  # get list of qualifiers not associated with field
763  {
764  # grab list of associated qualifiers
765  $AssociatedQualifiers = $this->AssociatedQualifierList();
766 
767  # get list of all qualifiers
768  $QFactory = new QualifierFactory();
769  $AllQualifiers = $QFactory->QualifierList();
770 
771  # return list of unassociated qualifiers
772  return array_diff($AllQualifiers, $AssociatedQualifiers);
773  }
774 
775  # add qualifier association
776  function AssociateWithQualifier($QualifierIdOrObject)
777  {
778  # if qualifier object passed in
779  if (is_object($QualifierIdOrObject))
780  {
781  # grab qualifier ID from object
782  $QualifierIdOrObject = $QualifierIdOrObject->Id();
783  }
784 
785  # if not already associated
786  $RecordCount = $this->DB->Query(
787  "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
788  ." WHERE QualifierId = ".$QualifierIdOrObject
789  ." AND MetadataFieldId = ".$this->Id(), "RecordCount");
790  if ($RecordCount < 1)
791  {
792  # associate field with qualifier
793  $this->DB->Query("INSERT INTO FieldQualifierInts SET"
794  ." QualifierId = ".$QualifierIdOrObject.","
795  ." MetadataFieldId = ".$this->Id());
796  }
797  }
798 
799  # delete qualifier association
800  function UnassociateWithQualifier($QualifierIdOrObject)
801  {
802  # if qualifier object passed in
803  if (is_object($QualifierIdOrObject))
804  {
805  # grab qualifier ID from object
806  $QualifierIdOrObject = $QualifierIdOrObject->Id();
807  }
808 
809  # delete intersection record from database
810  $this->DB->Query("DELETE FROM FieldQualifierInts WHERE QualifierId = "
811  .$QualifierIdOrObject." AND MetadataFieldId = ".
812  $this->Id());
813  }
814 
815  # retrieve item factory object for this field
816  function GetFactory()
817  {
818  switch ($this->Type())
819  {
821  $Factory = new ClassificationFactory($this->Id());
822  break;
823 
826  $Factory = new ControlledNameFactory($this->Id());
827  break;
828 
829  default:
830  $Factory = NULL;
831  break;
832  }
833 
834  return $Factory;
835  }
836 
837 
838  # ---- PRIVATE INTERFACE -------------------------------------------------
839 
840  private $DB;
841  private $DBFields;
842  private $ErrorStatus;
843 
847  public static $FieldTypeHumanEnums = array(
849  MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
850  MetadataSchema::MDFTYPE_NUMBER => "Number",
852  MetadataSchema::MDFTYPE_TIMESTAMP => "Timestamp",
855  MetadataSchema::MDFTYPE_CONTROLLEDNAME => "Controlled Name",
856  MetadataSchema::MDFTYPE_OPTION => "Option",
861  MetadataSchema::MDFTYPE_POINT => "Point");
862 
863  # field type DB/PHP enum translations
864  public static $FieldTypeDBEnums = array(
866  MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
867  MetadataSchema::MDFTYPE_NUMBER => "Number",
869  MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
872  MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
873  MetadataSchema::MDFTYPE_OPTION => "Option",
875  MetadataSchema::MDFTYPE_IMAGE => "Still Image",
879  );
880  public static $FieldTypeDBAllowedEnums = array(
882  MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
883  MetadataSchema::MDFTYPE_NUMBER => "Number",
885  MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
888  MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
889  MetadataSchema::MDFTYPE_OPTION => "Option",
891  MetadataSchema::MDFTYPE_IMAGE => "Still Image",
895  );
896  public static $FieldTypePHPEnums = array(
898  "Paragraph" => MetadataSchema::MDFTYPE_PARAGRAPH,
899  "Number" => MetadataSchema::MDFTYPE_NUMBER,
901  "TimeStamp" => MetadataSchema::MDFTYPE_TIMESTAMP,
904  "ControlledName" => MetadataSchema::MDFTYPE_CONTROLLEDNAME,
905  "Option" => MetadataSchema::MDFTYPE_OPTION,
907  "Still Image" => MetadataSchema::MDFTYPE_IMAGE,
911  );
912 
913  public static $UpdateTypes = array(
914  MetadataField::UPDATEMETHOD_NOAUTOUPDATE => "Do not update automatically",
915  MetadataField::UPDATEMETHOD_ONRECORDCREATE => "Update on record creation",
916  MetadataField::UPDATEMETHOD_BUTTON => "Provide an update button",
917  MetadataField::UPDATEMETHOD_ONRECORDEDIT => "Update when record is edited",
918  MetadataField::UPDATEMETHOD_ONRECORDCHANGE => "Update when record is changed"
919  );
920 
921 
922  # object constructor (only for use by MetadataSchema object)
923  function MetadataField($FieldId, $FieldName = NULL, $FieldType = NULL,
924  $Optional = TRUE, $DefaultValue = NULL)
925  {
926  # assume everything will be okay
927  $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
928 
929  # grab our own database handle
930  $this->DB = new Database();
931  $DB = $this->DB;
932 
933  # if field ID supplied
934  if ($FieldId != NULL)
935  {
936  # look up field in database
937  $DB->Query("SELECT * FROM MetadataFields WHERE FieldId = ".intval($FieldId));
938  $Record = $DB->FetchRow();
939  }
940 
941  # if no field ID supplied or if record not found in database
942  if (($FieldId == NULL) || ($Record == NULL))
943  {
944  # error out if valid field type not supplied
945  if (empty(MetadataField::$FieldTypeDBEnums[$FieldType]))
946  {
947  $this->ErrorStatus = MetadataSchema::MDFSTAT_FIELDDOESNOTEXIST;
948  return;
949  }
950 
951  # if field name supplied
952  $FieldName = trim($FieldName);
953  if (strlen($FieldName) > 0)
954  {
955  # error out if field name is duplicate
956  $DuplicateCount = $DB->Query("
957  SELECT COUNT(*) AS RecordCount FROM MetadataFields
958  WHERE FieldName = '".addslashes($FieldName)."'
959  OR Label = '".addslashes($FieldName)."'",
960  "RecordCount");
961 
962  if ($DuplicateCount > 0)
963  {
964  $this->ErrorStatus = MetadataSchema::MDFSTAT_DUPLICATENAME;
965  return;
966  }
967  }
968 
969  # grab current user ID
970  global $G_User;
971  $UserId = $G_User->Get("UserId");
972 
973  # lock DB tables and get next temporary field ID
974  $Schema = new MetadataSchema();
975  $DB->Query("LOCK TABLES MetadataFields WRITE");
976  $FieldId = $Schema->GetNextTempItemId();
977 
978  # add field to MDF table in database
979  $DB->Query("
980  INSERT INTO MetadataFields
981  (FieldId, FieldName, FieldType, LastModifiedById) VALUES
982  (".intval($FieldId).",
983  '".addslashes($FieldName)."',
984  '".MetadataField::$FieldTypeDBEnums[$FieldType]."',
985  '".$UserId."')");
986 
987  # release DB tables
988  $DB->Query("UNLOCK TABLES");
989 
990  # re-read record from database
991  $DB->Query("
992  SELECT * FROM MetadataFields
993  WHERE FieldId = ".intval($FieldId));
994  $this->DBFields = $DB->FetchRow();
995  $this->DBFields["DBFieldName"] =
996  $this->NormalizeFieldNameForDB($this->DBFields["FieldName"]);
997 
998  # set field defaults
999  $this->SetDefaults();
1000  $this->Optional($Optional ? TRUE : FALSE);
1001 
1002  # set the default value if specified since NULL is invalid for some
1003  # field types
1004  if (!is_null($DefaultValue))
1005  {
1006  $this->DefaultValue($DefaultValue);
1007  }
1008  }
1009  else
1010  {
1011  # save values locally
1012  $this->DBFields = $Record;
1013  $this->DBFields["DBFieldName"] =
1014  $this->NormalizeFieldNameForDB($Record["FieldName"]);
1015  }
1016  }
1017 
1021  public static $FixedDefaults = array(
1022  "Label" => NULL,
1023  "Description" => NULL,
1024  "Instructions" => NULL,
1025  "Enabled" => TRUE,
1026  "Optional" => TRUE,
1027  "Editable" => TRUE,
1028  "Viewable" => TRUE,
1029  "AllowMultiple" => FALSE,
1030  "IncludeInKeywordSearch" => FALSE,
1031  "IncludeInAdvancedSearch" => FALSE,
1032  "IncludeInSortOptions" => TRUE,
1033  "IncludeInRecommender" => FALSE,
1034  "ParagraphRows" => 4,
1035  "ParagraphCols" => 50,
1036  "MinValue" => 1,
1037  "FlagOnLabel" => "On",
1038  "FlagOffLabel" => "Off",
1039  "DateFormat" => NULL,
1040  "RecommenderWeight" => 1,
1041  "MaxHeight" => 500,
1042  "MaxWidth" => 500,
1043  "MaxPreviewHeight" => 100,
1044  "MaxPreviewWidth" => 100,
1045  "MaxThumbnailHeight" => 50,
1046  "MaxThumbnailWidth" => 50,
1047  "DefaultAltText" => NULL,
1048  "UsesQualifiers" => FALSE,
1049  "HasItemLevelQualifiers" => FALSE,
1050  "ShowQualifiers" => FALSE,
1051  "DefaultQualifier" => NULL,
1052  "AllowHTML" => FALSE,
1053  "UseWysiwygEditor" => FALSE,
1054  "UseForOaiSets" => FALSE,
1055  "NumAjaxResults" => 50,
1056  "ViewingPrivilege" => NULL,
1057  "AuthoringPrivilege" => PRIV_MYRESOURCEADMIN,
1058  "EditingPrivilege" => PRIV_RESOURCEADMIN,
1059  "ImagePreviewPrivilege" => NULL,
1060  "TreeBrowsingPrivilege" => NULL,
1061  "ViewingUserIsValue" => self::USERISVALUE_UNSET,
1062  "AuthoringUserIsValue" => self::USERISVALUE_UNSET,
1063  "EditingUserIsValue" => self::USERISVALUE_UNSET,
1064  "ViewingUserValue" => NULL,
1065  "AuthoringUserValue" => NULL,
1066  "EditingUserValue" => NULL,
1067  "PointPrecision" => 8,
1068  "PointDecimalDigits" => 5,
1069  "UserPrivilegeRestrictions" => array(),
1070  "UpdateMethod" => "NoAutoUpdate",
1071  # 9999 is the default max value because default number field length is 4
1072  "MaxValue" => 9999);
1073 
1077  public static $TypeBasedDefaults = array(
1079  "DefaultValue" => NULL,
1080  "SearchWeight" => 1,
1081  "TextFieldSize" => 50,
1082  "MaxLength" => 100),
1084  "DefaultValue" => NULL,
1085  "SearchWeight" => 1,
1086  "TextFieldSize" => 50,
1087  "MaxLength" => 100),
1089  "DefaultValue" => NULL,
1090  "SearchWeight" => 1,
1091  "TextFieldSize" => 4,
1092  "MaxLength" => 100),
1094  "DefaultValue" => NULL,
1095  "SearchWeight" => 1,
1096  "TextFieldSize" => 10,
1097  "MaxLength" => 100),
1099  "DefaultValue" => NULL,
1100  "SearchWeight" => 1,
1101  "TextFieldSize" => 50,
1102  "MaxLength" => 100),
1104  "DefaultValue" => NULL,
1105  "SearchWeight" => 1,
1106  "TextFieldSize" => 50,
1107  "MaxLength" => 100),
1109  "DefaultValue" => NULL,
1110  "SearchWeight" => 1,
1111  "TextFieldSize" => 50,
1112  "MaxLength" => 100),
1114  "DefaultValue" => NULL,
1115  "SearchWeight" => 3,
1116  "TextFieldSize" => 50,
1117  "MaxLength" => 100),
1119  "DefaultValue" => NULL,
1120  "SearchWeight" => 3,
1121  "TextFieldSize" => 50,
1122  "MaxLength" => 100),
1124  "DefaultValue" => NULL,
1125  "SearchWeight" => 1,
1126  "TextFieldSize" => 50,
1127  "MaxLength" => 100),
1129  "DefaultValue" => NULL,
1130  "SearchWeight" => 1,
1131  "TextFieldSize" => 50,
1132  "MaxLength" => 100),
1134  "DefaultValue" => NULL,
1135  "SearchWeight" => 1,
1136  "TextFieldSize" => 50,
1137  "MaxLength" => 100),
1138  MetadataSchema::MDFTYPE_URL => array(
1139  "DefaultValue" => NULL,
1140  "SearchWeight" => 1,
1141  "TextFieldSize" => 50,
1142  "MaxLength" => 255),
1144  "DefaultValue" => array("X" => NULL, "Y" => NULL),
1145  "SearchWeight" => 1,
1146  "TextFieldSize" => 10,
1147  "MaxLength" => 100));
1148 
1153  public function SetDefaults()
1154  {
1155  # set defaults that are the same for every field
1156  foreach (self::$FixedDefaults as $Key => $Value)
1157  {
1158  $this->$Key($Value);
1159  }
1160 
1161  # set defaults that depend on the type of the field
1162  foreach (self::$TypeBasedDefaults[$this->Type()] as $Key => $Value)
1163  {
1164  $this->$Key($Value);
1165  }
1166 
1167  # tweak the update method if dealing with the date of record creation
1168  if ($this->Name() == "Date Of Record Creation")
1169  {
1170  $this->UpdateMethod("OnRecordCreate");
1171  }
1172  }
1173 
1174  # remove field from database (only for use by MetadataSchema object)
1175  function Drop()
1176  {
1177  # clear other database entries as appropriate for field type
1178  $DB = $this->DB;
1179  $DBFieldName = $this->DBFields["DBFieldName"];
1180  switch (MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]])
1181  {
1189  # remove field from resources table
1190  if ($DB->FieldExists("Resources", $DBFieldName))
1191  {
1192  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."`");
1193  }
1194  break;
1195 
1197  if ($DB->FieldExists("Resources", $DBFieldName."X"))
1198  {
1199  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."X`");
1200  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Y`");
1201  }
1202  break;
1203 
1205  # remove field from resources table
1206  if ($DB->FieldExists("Resources", $DBFieldName))
1207  {
1208  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."`");
1209  }
1210  break;
1211 
1213  # remove fields from resources table
1214  if ($DB->FieldExists("Resources", $DBFieldName."Begin"))
1215  {
1216  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Begin`");
1217  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."End`");
1218  $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Precision`");
1219  }
1220  break;
1221 
1223  $DB->Query("SELECT ClassificationId FROM Classifications "
1224  ."WHERE FieldId = ".$this->Id());
1225  $TempDB = new Database();
1226  while ($ClassificationId = $DB->FetchField("ClassificationId"))
1227  {
1228  # remove any resource / name intersections
1229  $TempDB->Query("DELETE FROM ResourceClassInts WHERE "
1230  ."ClassificationId = ".$ClassificationId);
1231 
1232  # remove controlled name
1233  $TempDB->Query("DELETE FROM Classifications WHERE "
1234  ."ClassificationId = ".$ClassificationId);
1235  }
1236  break;
1237 
1240  $DB->Query("SELECT ControlledNameId FROM ControlledNames "
1241  ."WHERE FieldId = ".$this->Id());
1242  $TempDB = new Database();
1243  while ($ControlledNameId = $DB->FetchField("ControlledNameId"))
1244  {
1245  # remove any resource / name intersections
1246  $TempDB->Query("DELETE FROM ResourceNameInts WHERE "
1247  ."ControlledNameId = ".$ControlledNameId);
1248 
1249  # remove any variant names
1250  $TempDB->Query("DELETE FROM VariantNames WHERE "
1251  ."ControlledNameId = ".$ControlledNameId);
1252 
1253  # remove controlled name
1254  $TempDB->Query("DELETE FROM ControlledNames WHERE "
1255  ."ControlledNameId = ".$ControlledNameId);
1256  }
1257  break;
1258 
1260  # for each file associated with this field
1261  $DB->Query("SELECT FileId FROM Files WHERE FieldId = '".$this->Id()."'");
1262  while ($FileId = $DB->FetchRow())
1263  {
1264  # delete file
1265  $File = new File(intval($FileId));
1266  $File->Delete();
1267  }
1268  break;
1269  }
1270 
1271  # remove field from database
1272  $DB->Query("DELETE FROM MetadataFields "
1273  ."WHERE FieldId = '".$this->DBFields["FieldId"]."'");
1274 
1275  # remove any qualifier associations
1276  $DB->Query("DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
1277  .$this->DBFields["FieldId"]."'");
1278 
1279  # remove the field from the display and edit order
1280  try
1281  {
1284 
1285  # remove it from the dispaly and edit oorder
1286  $DisplayOrder->RemoveItem($this->Id(), "MetadataField");
1287  $EditOrder->RemoveItem($this->Id(), "MetadataField");
1288 
1289  # remove field from any metadata field groups in the display order
1290  foreach ($DisplayOrder->GetItemIds() as $Item)
1291  {
1292  if ($Item["Type"] == "MetadataFieldGroup")
1293  {
1294  $Group = new MetadataFieldGroup($Item["ID"]);
1295  $Group->RemoveItem($this->Id(), "MetadataField");
1296  }
1297  }
1298 
1299  # remove field from any metadata field groups in the edit order
1300  foreach ($EditOrder->GetItemIds() as $Item)
1301  {
1302  if ($Item["Type"] == "MetadataFieldGroup")
1303  {
1304  $Group = new MetadataFieldGroup($Item["ID"]);
1305  $Group->RemoveItem($this->Id(), "MetadataField");
1306  }
1307  }
1308  } catch (Exception $Exception) {}
1309  }
1310 
1311  # modify any database fields
1312  private function ModifyField($NewName = NULL, $NewType = NULL)
1313  {
1314  # grab old DB field name
1315  $OldDBFieldName = $this->DBFields["DBFieldName"];
1316  $OldFieldType = NULL;
1317 
1318  # if new field name supplied
1319  if ($NewName != NULL)
1320  {
1321  # cache the old name for options and controllednames below
1322  $OldName = $this->DBFields["FieldName"];
1323 
1324  # store new name
1325  $this->UpdateValue("FieldName", $NewName);
1326 
1327  # determine new DB field name
1328  $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
1329 
1330  # store new database field name
1331  $this->DBFields["DBFieldName"] = $NewDBFieldName;
1332  }
1333  else
1334  {
1335  # set new field name equal to old field name
1336  $NewDBFieldName = $OldDBFieldName;
1337  }
1338 
1339  # if new type supplied
1340  if ($NewType != NULL)
1341  {
1342  # grab old field type
1343  $OldFieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
1344 
1345  # store new field type
1346  $this->UpdateValue("FieldType", MetadataField::$FieldTypeDBEnums[$NewType]);
1347  }
1348 
1349  # if this is not a temporary field
1350  if ($this->Id() >= 0)
1351  {
1352  # modify field in DB as appropriate for field type
1353  $DB = $this->DB;
1354  $FieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
1355  switch ($FieldType)
1356  {
1360  # alter field declaration in Resources table
1361  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1362  .$OldDBFieldName."` `"
1363  .$NewDBFieldName."` TEXT "
1364  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1365  break;
1366 
1369  # alter field declaration in Resources table
1370  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1371  .$OldDBFieldName."` `"
1372  .$NewDBFieldName."` INT "
1373  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1374  break;
1375 
1377  $Precision = $this->UpdateValue("PointPrecision",
1378  DB_NOVALUE);
1379  $Digits = $this->UpdateValue("PointDecimalDigits",
1380  DB_NOVALUE);
1381  $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
1382  ."`".$OldDBFieldName."X` "
1383  ."`".$NewDBFieldName."X`".
1384  " DECIMAL(".$Precision.",".$Digits.")");
1385  $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
1386  ."`".$OldDBFieldName."Y` "
1387  ."`".$NewDBFieldName."Y`".
1388  " DECIMAL(".$Precision.",".$Digits.")");
1389  break;
1390 
1392  # if DB field name has changed
1393  if ($NewDBFieldName != $OldDBFieldName)
1394  {
1395  # alter field declaration in Resources table
1396  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1397  .$OldDBFieldName."` `"
1398  .$NewDBFieldName."` TEXT");
1399  }
1400  break;
1401 
1403  # if DB field name has changed
1404  if ($NewDBFieldName != $OldDBFieldName)
1405  {
1406  # alter field declaration in Resources table
1407  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1408  .$OldDBFieldName."` `"
1409  .$NewDBFieldName."` INT");
1410  }
1411  break;
1412 
1414  # alter field declaration in Resources table
1415  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1416  .$OldDBFieldName."` `"
1417  .$NewDBFieldName."` INT"
1418  ." DEFAULT ".intval($this->DefaultValue()));
1419 
1420  # set any unset values to default
1421  $DB->Query("UPDATE Resources SET `".$NewDBFieldName
1422  ."` = ".intval($this->DefaultValue())
1423  ." WHERE `".$NewDBFieldName."` IS NULL");
1424  break;
1425 
1427  # if new type supplied and new type is different from old
1428  if (($NewType != NULL) && ($NewType != $OldFieldType))
1429  {
1430  # if old type was time stamp
1431  if ($OldFieldType == MetadataSchema::MDFTYPE_TIMESTAMP)
1432  {
1433  # change time stamp field in resources table to begin date
1434  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1435  .$OldDBFieldName."` `"
1436  .$NewDBFieldName."Begin` DATE "
1437  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1438 
1439  # add end date and precision fields
1440  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."End"
1441  ."` DATE");
1442  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."Precision`"
1443  ." INT ".($Optional ? "" : "NOT NULL"));
1444 
1445  # set precision to reflect time stamp content
1446  $DB->Query("UPDATE Resources SET `".$NewDBFieldName."Precision` = "
1447  .(DATEPRE_BEGINYEAR|DATEPRE_BEGINMONTH|DATEPRE_BEGINDAY));
1448  }
1449  else
1450  {
1451  exit("<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
1452  }
1453  }
1454  else
1455  {
1456  # change name of fields
1457  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1458  .$OldDBFieldName."Begin` `"
1459  .$NewDBFieldName."Begin` DATE "
1460  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1461  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1462  .$OldDBFieldName."End` `"
1463  .$NewDBFieldName."End` DATE "
1464  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1465  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1466  .$OldDBFieldName."Precision` `"
1467  .$NewDBFieldName."Precision` INT "
1468  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1469  }
1470  break;
1471 
1473  # if new type supplied and new type is different from old
1474  if (($NewType != NULL) && ($NewType != $OldFieldType))
1475  {
1476  # if old type was date
1477  if ($OldFieldType == MetadataSchema::MDFTYPE_DATE)
1478  {
1479  # change begin date field in resource table to time stamp
1480  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1481  .$OldDBFieldName."Begin` `"
1482  .$NewDBFieldName."` DATETIME "
1483  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1484 
1485  # drop end date and precision fields
1486  $DB->Query("ALTER TABLE Resources DROP COLUMN `"
1487  .$OldDBFieldName."End`");
1488  $DB->Query("ALTER TABLE Resources DROP COLUMN `"
1489  .$OldDBFieldName."Precision`");
1490  }
1491  else
1492  {
1493  exit("<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
1494  }
1495  }
1496  else
1497  {
1498  # change name of field
1499  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1500  .$OldDBFieldName."` `"
1501  .$NewDBFieldName."` DATETIME "
1502  .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1503  }
1504  break;
1505 
1509  break;
1510  }
1511 
1512  # if qualifier DB field exists
1513  if ($DB->FieldExists("Resources", $OldDBFieldName."Qualifier"))
1514  {
1515  # rename qualifier DB field
1516  $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1517  .$OldDBFieldName."Qualifier` `"
1518  .$NewDBFieldName."Qualifier` INT ");
1519  }
1520  }
1521  }
1522 
1523  # convenience functions to supply parameters to Database->UpdateValue()
1524  private function UpdateValue($FieldName, $NewValue)
1525  {
1526  return $this->DB->UpdateValue("MetadataFields", $FieldName, $NewValue,
1527  "FieldId = ".intval($this->DBFields["FieldId"]),
1528  $this->DBFields);
1529  }
1530  private function UpdateIntValue($FieldName, $NewValue)
1531  {
1532  return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1533  "FieldId = ".intval($this->DBFields["FieldId"]),
1534  $this->DBFields);
1535  }
1536  private function UpdateFloatValue($FieldName, $NewValue)
1537  {
1538  return $this->DB->UpdateFloatValue("MetadataFields", $FieldName, $NewValue,
1539  "FieldId = ".intval($this->DBFields["FieldId"]),
1540  $this->DBFields);
1541  }
1542  private function UpdateBoolValue($FieldName, $NewValue)
1543  {
1544  $NewValue = $this->TranslateStringToConstants($NewValue);
1545  return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1546  "FieldId = ".intval($this->DBFields["FieldId"]),
1547  $this->DBFields);
1548  }
1549  private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
1550  {
1551  $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
1552  return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1553  "FieldId = ".intval($this->DBFields["FieldId"]),
1554  $this->DBFields);
1555  }
1556 
1557  # normalize field name for use as database field name
1558  private function NormalizeFieldNameForDB($Name)
1559  {
1560  return preg_replace("/[^a-z0-9]/i", "", $Name);
1561  }
1562 
1563  # add any needed database fields and/or entries
1564  private function AddDatabaseFields()
1565  {
1566  # grab values for common use
1567  $DB = $this->DB;
1568  $FieldName = $this->Name();
1569  $DBFieldName = $this->DBFieldName();
1570  $Optional = $this->Optional();
1571  $DefaultValue = $this->DefaultValue();
1572 
1573  # set up field(s) based on field type
1574  switch ($this->Type())
1575  {
1579  # add field to resources table (if not already present)
1580  if (!$DB->FieldExists("Resources", $DBFieldName))
1581  {
1582  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1583  ."` TEXT ".($Optional ? "" : "NOT NULL"));
1584  }
1585 
1586  # if default value supplied
1587  if ($DefaultValue != NULL)
1588  {
1589  # set all existing records to default value
1590  $DB->Query("UPDATE Resources SET `"
1591  .$DBFieldName."` = '".addslashes($DefaultValue)."'");
1592  }
1593  break;
1594 
1596  # add field to resources table (if not already present)
1597  if (!$DB->FieldExists("Resources", $DBFieldName))
1598  {
1599  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1600  ."` INT ".($Optional ? "" : "NOT NULL"));
1601  }
1602 
1603  # if default value supplied
1604  if ($DefaultValue != NULL)
1605  {
1606  # set all existing records to default value
1607  $DB->Query("UPDATE Resources SET `"
1608  .$DBFieldName."` = '".addslashes($DefaultValue)."'");
1609  }
1610  break;
1611 
1613  if (!$DB->FieldExists("Resources", $DBFieldName."X"))
1614  {
1615  $Precision = $this->UpdateValue("PointPrecision",
1616  DB_NOVALUE);
1617  $Digits = $this->UpdateValue("PointDecimalDigits",
1618  DB_NOVALUE);
1619 
1620  $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1621  .$DBFieldName."X`".
1622  " DECIMAL(".$Precision.",".$Digits.")");
1623  $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1624  .$DBFieldName."Y`".
1625  " DECIMAL(".$Precision.",".$Digits.")");
1626  }
1627 
1628  break;
1630  # if field is not already present in database
1631  if (!$DB->FieldExists("Resources", $DBFieldName))
1632  {
1633  # add field to resources table
1634  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1635  ."` INT DEFAULT ".intval($DefaultValue));
1636 
1637  # set all existing records to default value
1638  $DB->Query("UPDATE Resources SET `"
1639  .$DBFieldName."` = ".intval($DefaultValue));
1640  }
1641  break;
1642 
1644  # add field to resources table (if not already present)
1645  if (!$DB->FieldExists("Resources", $DBFieldName))
1646  {
1647  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1648  ."` INT ".($Optional ? "" : "NOT NULL"));
1649  }
1650  break;
1651 
1653  # add fields to resources table (if not already present)
1654  if (!$DB->FieldExists("Resources", $DBFieldName))
1655  {
1656  $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1657  .$DBFieldName."` TEXT");
1658  }
1659  break;
1660 
1662  # add fields to resources table (if not already present)
1663  if (!$DB->FieldExists("Resources", $DBFieldName))
1664  {
1665  $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1666  .$DBFieldName."` INT");
1667  }
1668  break;
1669 
1671  # add fields to resources table (if not already present)
1672  if (!$DB->FieldExists("Resources", $DBFieldName."Begin"))
1673  {
1674  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Begin`"
1675  ." DATE ".($Optional ? "" : "NOT NULL"));
1676  }
1677  if (!$DB->FieldExists("Resources", $DBFieldName."End"))
1678  {
1679  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."End`"
1680  ." DATE");
1681  }
1682  if (!$DB->FieldExists("Resources", $DBFieldName."Precision"))
1683  {
1684  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Precision`"
1685  ." INT ".($Optional ? "" : "NOT NULL"));
1686  }
1687  break;
1688 
1690  # add fields to resources table (if not already present)
1691  if (!$DB->FieldExists("Resources", $DBFieldName))
1692  {
1693  $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1694  ."` DATETIME ".($Optional ? "" : "NOT NULL"));
1695  }
1696  break;
1697 
1701  break;
1702 
1703  default:
1704  exit("<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
1705  break;
1706  }
1707  }
1708 
1716  private function TranslateStringToConstants($CString, $ClassName = NULL)
1717  {
1718  # if not a string return value unchanged to caller
1719  if (!is_string($CString) || ($CString === DB_NOVALUE))
1720  {
1721  $ReturnValue = $CString;
1722  }
1723  # handle booleans as a special case
1724  elseif (strtoupper(trim($CString)) == "TRUE")
1725  {
1726  $ReturnValue = TRUE;
1727  }
1728  elseif (strtoupper(trim($CString)) == "FALSE")
1729  {
1730  $ReturnValue = FALSE;
1731  }
1732  else
1733  {
1734  # assume no values will be found
1735  $ReturnValue = NULL;
1736 
1737  # split apart any ORed-together values
1738  $Values = explode("|", $CString);
1739 
1740  # for each value found
1741  foreach ($Values as $Value)
1742  {
1743  # trim off any extraneous whitespace
1744  $Value = trim($Value);
1745 
1746  # add class name prefix to constant name if requested
1747  if ($ClassName) { $Value = $ClassName."::".$Value; }
1748 
1749  # if value corresponds to a constant
1750  if (defined($Value))
1751  {
1752  # add constant to return value
1753  $ReturnValue = ($ReturnValue === NULL)
1754  ? constant($Value)
1755  : ($ReturnValue | constant($Value));
1756  }
1757  }
1758 
1759  # if no corresponding constants were found
1760  if ($ReturnValue === NULL)
1761  {
1762  # return original value to caller
1763  $ReturnValue = $CString;
1764  }
1765  }
1766 
1767  # return result to caller
1768  return $ReturnValue;
1769  }
1770 
1771  # ---- DEPRECATED --------------------------------------------------------
1772 
1781  function OrderPosition($OrderType, $NewValue = DB_NOVALUE)
1782  {
1783  switch ($OrderType)
1784  {
1786  return $this->UpdateValue("DisplayOrderPosition", $NewValue);
1787  break;
1788 
1790  return $this->UpdateValue("EditingOrderPosition", $NewValue);
1791  break;
1792 
1793  default:
1794  exit("invalid order type passed to MetadataField::OrderPosition");
1795  break;
1796  }
1797  }
1798 
1799 }