CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
10 class MetadataField {
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
129 function GetAllowedConversionTypes()
130 {
131 # determine type list based on our type
132 switch ($this->Type())
133 {
134 case MetadataSchema::MDFTYPE_TEXT:
135 case MetadataSchema::MDFTYPE_PARAGRAPH:
136 case MetadataSchema::MDFTYPE_NUMBER:
137 case MetadataSchema::MDFTYPE_FLAG:
138 case MetadataSchema::MDFTYPE_URL:
139 $AllowedTypes = array(
140 MetadataSchema::MDFTYPE_TEXT => "Text",
141 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
142 MetadataSchema::MDFTYPE_NUMBER => "Number",
143 MetadataSchema::MDFTYPE_FLAG => "Flag",
144 MetadataSchema::MDFTYPE_URL => "Url"
145 );
146 break;
147
148 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
149 case MetadataSchema::MDFTYPE_OPTION:
150 $AllowedTypes = array(
151 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
152 MetadataSchema::MDFTYPE_OPTION => "Option",
153 );
154 break;
155
156 case MetadataSchema::MDFTYPE_DATE:
157 $AllowedTypes = array(
158 MetadataSchema::MDFTYPE_TEXT => "Text",
159 MetadataSchema::MDFTYPE_DATE => "Date",
160 );
161 break;
162
163 case MetadataSchema::MDFTYPE_IMAGE:
164 $AllowedTypes = array(
165 MetadataSchema::MDFTYPE_TEXT => "Text",
166 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
167 );
168 break;
169
170 case MetadataSchema::MDFTYPE_TIMESTAMP:
171 case MetadataSchema::MDFTYPE_TREE:
172 case MetadataSchema::MDFTYPE_USER:
173 case MetadataSchema::MDFTYPE_FILE:
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 {
249 $DisplayOrder = MetadataFieldOrder::GetDisplayOrderObject();
250 $EditOrder = MetadataFieldOrder::GetEditOrderObject();
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 {
530 case MetadataSchema::MDFTYPE_TREE:
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
544 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
545 case MetadataSchema::MDFTYPE_OPTION:
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
559 case MetadataSchema::MDFTYPE_FLAG:
560 $PossibleValues[0] = $this->FlagOffLabel();
561 $PossibleValues[1] = $this->FlagOnLabel();
562 break;
563
564 case MetadataSchema::MDFTYPE_USER:
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)
600 function GetCountOfPossibleValues()
601 {
602 # retrieve values based on field type
603 switch ($this->Type())
604 {
605 case MetadataSchema::MDFTYPE_TREE:
606 $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
607 ." FROM Classifications WHERE FieldId = ".$this->Id(),
608 "ValueCount");
609 break;
610
611 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
612 case MetadataSchema::MDFTYPE_OPTION:
613 $Count = $this->DB->Query("SELECT count(*) AS ValueCount"
614 ." FROM ControlledNames WHERE FieldId = ".$this->Id(),
615 "ValueCount");
616 break;
617
618 case MetadataSchema::MDFTYPE_FLAG:
619 $Count = 2;
620 break;
621
622 case MetadataSchema::MDFTYPE_USER:
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 {
643 case MetadataSchema::MDFTYPE_TREE:
644 $Id = $this->DB->Query("SELECT ClassificationId FROM Classifications"
645 ." WHERE ClassificationName = '".addslashes($Value)."'"
646 ." AND FieldId = ".$this->Id(),
647 "ClassificationId");
648 break;
649
650 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
651 case MetadataSchema::MDFTYPE_OPTION:
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 {
675 case MetadataSchema::MDFTYPE_TREE:
676 $Value = $this->DB->Query("SELECT ClassificationName FROM Classifications"
677 ." WHERE ClassificationId = '".intval($Id)."'"
678 ." AND FieldId = ".$this->Id(),
679 "ClassificationName");
680 break;
681
682 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
683 case MetadataSchema::MDFTYPE_OPTION:
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
710 function ValueUseCount($Value)
711 {
712 # retrieve ID if object passed in
713 if (is_object($Value) && method_exists($Value, "Id"))
714 {
715 $Value = $Value->Id();
716 }
717
718 # check value based on field type
719 $DBFieldName = $this->DBFields["DBFieldName"];
720 switch ($this->Type())
721 {
722 case MetadataSchema::MDFTYPE_TEXT:
723 case MetadataSchema::MDFTYPE_PARAGRAPH:
724 case MetadataSchema::MDFTYPE_NUMBER:
725 case MetadataSchema::MDFTYPE_USER:
726 case MetadataSchema::MDFTYPE_IMAGE:
727 case MetadataSchema::MDFTYPE_TIMESTAMP:
728 case MetadataSchema::MDFTYPE_URL:
729 case MetadataSchema::MDFTYPE_FLAG:
730 case MetadataSchema::MDFTYPE_FILE:
731 $UseCount = $this->DB->Query("SELECT COUNT(*) AS UseCount"
732 ." FROM Resources"
733 ." WHERE `".$DBFieldName."` = '".addslashes($Value)."'",
734 "UseCount");
735 break;
736
737 case MetadataSchema::MDFTYPE_TREE:
738 $UseCount = $this->DB->Query("SELECT COUNT(*) AS UseCount"
739 ." FROM ResourceClassInts"
740 ." WHERE ClassificationId = ".intval($Value),
741 "UseCount");
742 break;
743
744 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
745 case MetadataSchema::MDFTYPE_OPTION:
746 $UseCount = $this->DB->Query("SELECT COUNT(*) AS UseCount"
747 ." FROM ResourceNameInts"
748 ." WHERE ControlledNameId = ".intval($Value),
749 "UseCount");
750 break;
751
752 case MetadataSchema::MDFTYPE_POINT:
753 $UseCount = $this->DB->Query("SELECT COUNT(*) AS UseCount"
754 ." FROM Resources"
755 ." WHERE `".$DBFieldName."X` = '".$Value["X"]."'"
756 ." AND `".$DBFieldName."Y` = '".$Value["Y"]."'",
757 "UseCount");
758 break;
759
760 default:
761 throw new Exception(__CLASS__."::".__METHOD__."() called for"
762 ." unsupported field type (".$this->Type().").");
763 break;
764 }
765
766 # report use count to caller
767 return $UseCount;
768 }
769
770 # get/set whether field uses item-level qualifiers
771 function HasItemLevelQualifiers($NewValue = DB_NOVALUE)
772 {
773 # if value provided different from present value
774 if (($NewValue != DB_NOVALUE)
775 && ($NewValue != $this->DBFields["HasItemLevelQualifiers"]))
776 {
777 # check if qualifier column currently exists
778 $QualColName = $this->DBFieldName()."Qualifier";
779 $QualColExists = $this->DB->FieldExists("Resources", $QualColName);
780
781 # if new value indicates qualifiers should now be used
782 if ($NewValue == TRUE)
783 {
784 # if qualifier column does not exist in DB for this field
785 if ($QualColExists == FALSE)
786 {
787 # add qualifier column in DB for this field
788 $this->DB->Query("ALTER TABLE Resources ADD COLUMN `"
789 .$QualColName."` INT");
790 }
791 }
792 else
793 {
794 # if qualifier column exists in DB for this field
795 if ($QualColExists == TRUE)
796 {
797 # remove qualifier column from DB for this field
798 $this->DB->Query("ALTER TABLE Resources DROP COLUMN `"
799 .$QualColName."`");
800 }
801 }
802 }
803
804 return $this->UpdateValue("HasItemLevelQualifiers", $NewValue);
805 }
806
807 # get list of qualifiers associated with field
808 function AssociatedQualifierList()
809 {
810 # start with empty list
811 $List = array();
812
813 # for each associated qualifier
814 $this->DB->Query("SELECT QualifierId FROM FieldQualifierInts"
815 ." WHERE MetadataFieldId = ".$this->DBFields["FieldId"]);
816 while ($Record = $this->DB->FetchRow())
817 {
818 # load qualifier object
819 $Qual = new Qualifier($Record["QualifierId"]);
820
821 # add qualifier ID and name to list
822 $List[$Qual->Id()] = $Qual->Name();
823 }
824
825 # return list to caller
826 return $List;
827 }
828
829 # get list of qualifiers not associated with field
830 function UnassociatedQualifierList()
831 {
832 # grab list of associated qualifiers
833 $AssociatedQualifiers = $this->AssociatedQualifierList();
834
835 # get list of all qualifiers
836 $QFactory = new QualifierFactory();
837 $AllQualifiers = $QFactory->QualifierList();
838
839 # return list of unassociated qualifiers
840 return array_diff($AllQualifiers, $AssociatedQualifiers);
841 }
842
843 # add qualifier association
844 function AssociateWithQualifier($QualifierIdOrObject)
845 {
846 # if qualifier object passed in
847 if (is_object($QualifierIdOrObject))
848 {
849 # grab qualifier ID from object
850 $QualifierIdOrObject = $QualifierIdOrObject->Id();
851 }
852
853 # if not already associated
854 $RecordCount = $this->DB->Query(
855 "SELECT COUNT(*) AS RecordCount FROM FieldQualifierInts"
856 ." WHERE QualifierId = ".$QualifierIdOrObject
857 ." AND MetadataFieldId = ".$this->Id(), "RecordCount");
858 if ($RecordCount < 1)
859 {
860 # associate field with qualifier
861 $this->DB->Query("INSERT INTO FieldQualifierInts SET"
862 ." QualifierId = ".$QualifierIdOrObject.","
863 ." MetadataFieldId = ".$this->Id());
864 }
865 }
866
867 # delete qualifier association
868 function UnassociateWithQualifier($QualifierIdOrObject)
869 {
870 # if qualifier object passed in
871 if (is_object($QualifierIdOrObject))
872 {
873 # grab qualifier ID from object
874 $QualifierIdOrObject = $QualifierIdOrObject->Id();
875 }
876
877 # delete intersection record from database
878 $this->DB->Query("DELETE FROM FieldQualifierInts WHERE QualifierId = "
879 .$QualifierIdOrObject." AND MetadataFieldId = ".
880 $this->Id());
881 }
882
883 # retrieve item factory object for this field
884 function GetFactory()
885 {
886 switch ($this->Type())
887 {
888 case MetadataSchema::MDFTYPE_TREE:
889 $Factory = new ClassificationFactory($this->Id());
890 break;
891
892 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
893 case MetadataSchema::MDFTYPE_OPTION:
894 $Factory = new ControlledNameFactory($this->Id());
895 break;
896
897 default:
898 $Factory = NULL;
899 break;
900 }
901
902 return $Factory;
903 }
904
905
906 # ---- PRIVATE INTERFACE -------------------------------------------------
907
908 private $DB;
909 private $DBFields;
910 private $ErrorStatus;
911
915 public static $FieldTypeHumanEnums = array(
916 MetadataSchema::MDFTYPE_TEXT => "Text",
917 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
918 MetadataSchema::MDFTYPE_NUMBER => "Number",
919 MetadataSchema::MDFTYPE_DATE => "Date",
920 MetadataSchema::MDFTYPE_TIMESTAMP => "Timestamp",
921 MetadataSchema::MDFTYPE_FLAG => "Flag",
922 MetadataSchema::MDFTYPE_TREE => "Tree",
923 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "Controlled Name",
924 MetadataSchema::MDFTYPE_OPTION => "Option",
925 MetadataSchema::MDFTYPE_USER => "User",
926 MetadataSchema::MDFTYPE_IMAGE => "Image",
927 MetadataSchema::MDFTYPE_FILE => "File",
928 MetadataSchema::MDFTYPE_URL => "URL",
929 MetadataSchema::MDFTYPE_POINT => "Point");
930
931 # field type DB/PHP enum translations
932 public static $FieldTypeDBEnums = array(
933 MetadataSchema::MDFTYPE_TEXT => "Text",
934 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
935 MetadataSchema::MDFTYPE_NUMBER => "Number",
936 MetadataSchema::MDFTYPE_DATE => "Date",
937 MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
938 MetadataSchema::MDFTYPE_FLAG => "Flag",
939 MetadataSchema::MDFTYPE_TREE => "Tree",
940 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
941 MetadataSchema::MDFTYPE_OPTION => "Option",
942 MetadataSchema::MDFTYPE_USER => "User",
943 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
944 MetadataSchema::MDFTYPE_FILE => "File",
945 MetadataSchema::MDFTYPE_URL => "Url",
946 MetadataSchema::MDFTYPE_POINT => "Point"
947 );
948 public static $FieldTypeDBAllowedEnums = array(
949 MetadataSchema::MDFTYPE_TEXT => "Text",
950 MetadataSchema::MDFTYPE_PARAGRAPH => "Paragraph",
951 MetadataSchema::MDFTYPE_NUMBER => "Number",
952 MetadataSchema::MDFTYPE_DATE => "Date",
953 MetadataSchema::MDFTYPE_TIMESTAMP => "TimeStamp",
954 MetadataSchema::MDFTYPE_FLAG => "Flag",
955 MetadataSchema::MDFTYPE_TREE => "Tree",
956 MetadataSchema::MDFTYPE_CONTROLLEDNAME => "ControlledName",
957 MetadataSchema::MDFTYPE_OPTION => "Option",
958 MetadataSchema::MDFTYPE_USER => "User",
959 MetadataSchema::MDFTYPE_IMAGE => "Still Image",
960 MetadataSchema::MDFTYPE_FILE => "File",
961 MetadataSchema::MDFTYPE_URL => "Url",
962 MetadataSchema::MDFTYPE_POINT => "Point"
963 );
964 public static $FieldTypePHPEnums = array(
965 "Text" => MetadataSchema::MDFTYPE_TEXT,
966 "Paragraph" => MetadataSchema::MDFTYPE_PARAGRAPH,
967 "Number" => MetadataSchema::MDFTYPE_NUMBER,
968 "Date" => MetadataSchema::MDFTYPE_DATE,
969 "TimeStamp" => MetadataSchema::MDFTYPE_TIMESTAMP,
970 "Flag" => MetadataSchema::MDFTYPE_FLAG,
971 "Tree" => MetadataSchema::MDFTYPE_TREE,
972 "ControlledName" => MetadataSchema::MDFTYPE_CONTROLLEDNAME,
973 "Option" => MetadataSchema::MDFTYPE_OPTION,
974 "User" => MetadataSchema::MDFTYPE_USER,
975 "Still Image" => MetadataSchema::MDFTYPE_IMAGE,
976 "File" => MetadataSchema::MDFTYPE_FILE,
977 "Url" => MetadataSchema::MDFTYPE_URL,
978 "Point" => MetadataSchema::MDFTYPE_POINT
979 );
980
981 public static $UpdateTypes = array(
982 MetadataField::UPDATEMETHOD_NOAUTOUPDATE => "Do not update automatically",
983 MetadataField::UPDATEMETHOD_ONRECORDCREATE => "Update on record creation",
984 MetadataField::UPDATEMETHOD_BUTTON => "Provide an update button",
985 MetadataField::UPDATEMETHOD_ONRECORDEDIT => "Update when record is edited",
986 MetadataField::UPDATEMETHOD_ONRECORDCHANGE => "Update when record is changed"
987 );
988
989
990 # object constructor (only for use by MetadataSchema object)
991 function MetadataField($FieldId, $FieldName = NULL, $FieldType = NULL,
992 $Optional = TRUE, $DefaultValue = NULL)
993 {
994 # assume everything will be okay
995 $this->ErrorStatus = MetadataSchema::MDFSTAT_OK;
996
997 # grab our own database handle
998 $this->DB = new Database();
999 $DB = $this->DB;
1000
1001 # if field ID supplied
1002 if ($FieldId != NULL)
1003 {
1004 # look up field in database
1005 $DB->Query("SELECT * FROM MetadataFields WHERE FieldId = ".intval($FieldId));
1006 $Record = $DB->FetchRow();
1007 }
1008
1009 # if no field ID supplied or if record not found in database
1010 if (($FieldId == NULL) || ($Record == NULL))
1011 {
1012 # error out if valid field type not supplied
1013 if (empty(MetadataField::$FieldTypeDBEnums[$FieldType]))
1014 {
1015 $this->ErrorStatus = MetadataSchema::MDFSTAT_FIELDDOESNOTEXIST;
1016 return;
1017 }
1018
1019 # if field name supplied
1020 $FieldName = trim($FieldName);
1021 if (strlen($FieldName) > 0)
1022 {
1023 # error out if field name is duplicate
1024 $DuplicateCount = $DB->Query("
1025 SELECT COUNT(*) AS RecordCount FROM MetadataFields
1026 WHERE FieldName = '".addslashes($FieldName)."'
1027 OR Label = '".addslashes($FieldName)."'",
1028 "RecordCount");
1029
1030 if ($DuplicateCount > 0)
1031 {
1032 $this->ErrorStatus = MetadataSchema::MDFSTAT_DUPLICATENAME;
1033 return;
1034 }
1035 }
1036
1037 # grab current user ID
1038 global $G_User;
1039 $UserId = $G_User->Get("UserId");
1040
1041 # lock DB tables and get next temporary field ID
1042 $Schema = new MetadataSchema();
1043 $DB->Query("LOCK TABLES MetadataFields WRITE");
1044 $FieldId = $Schema->GetNextTempItemId();
1045
1046 # add field to MDF table in database
1047 $DB->Query("
1048 INSERT INTO MetadataFields
1049 (FieldId, FieldName, FieldType, LastModifiedById) VALUES
1050 (".intval($FieldId).",
1051 '".addslashes($FieldName)."',
1052 '".MetadataField::$FieldTypeDBEnums[$FieldType]."',
1053 '".$UserId."')");
1054
1055 # release DB tables
1056 $DB->Query("UNLOCK TABLES");
1057
1058 # re-read record from database
1059 $DB->Query("
1060 SELECT * FROM MetadataFields
1061 WHERE FieldId = ".intval($FieldId));
1062 $this->DBFields = $DB->FetchRow();
1063 $this->DBFields["DBFieldName"] =
1064 $this->NormalizeFieldNameForDB($this->DBFields["FieldName"]);
1065
1066 # set field defaults
1067 $this->SetDefaults();
1068 $this->Optional($Optional ? TRUE : FALSE);
1069
1070 # set the default value if specified since NULL is invalid for some
1071 # field types
1072 if (!is_null($DefaultValue))
1073 {
1074 $this->DefaultValue($DefaultValue);
1075 }
1076 }
1077 else
1078 {
1079 # save values locally
1080 $this->DBFields = $Record;
1081 $this->DBFields["DBFieldName"] =
1082 $this->NormalizeFieldNameForDB($Record["FieldName"]);
1083 }
1084 }
1085
1089 public static $FixedDefaults = array(
1090 "Label" => NULL,
1091 "Description" => NULL,
1092 "Instructions" => NULL,
1093 "Enabled" => TRUE,
1094 "Optional" => TRUE,
1095 "Editable" => TRUE,
1096 "Viewable" => TRUE,
1097 "AllowMultiple" => FALSE,
1098 "IncludeInKeywordSearch" => FALSE,
1099 "IncludeInAdvancedSearch" => FALSE,
1100 "IncludeInSortOptions" => TRUE,
1101 "IncludeInRecommender" => FALSE,
1102 "ParagraphRows" => 4,
1103 "ParagraphCols" => 50,
1104 "MinValue" => 1,
1105 "FlagOnLabel" => "On",
1106 "FlagOffLabel" => "Off",
1107 "DateFormat" => NULL,
1108 "RecommenderWeight" => 1,
1109 "MaxHeight" => 500,
1110 "MaxWidth" => 500,
1111 "MaxPreviewHeight" => 100,
1112 "MaxPreviewWidth" => 100,
1113 "MaxThumbnailHeight" => 50,
1114 "MaxThumbnailWidth" => 50,
1115 "DefaultAltText" => NULL,
1116 "UsesQualifiers" => FALSE,
1117 "HasItemLevelQualifiers" => FALSE,
1118 "ShowQualifiers" => FALSE,
1119 "DefaultQualifier" => NULL,
1120 "AllowHTML" => FALSE,
1121 "UseWysiwygEditor" => FALSE,
1122 "UseForOaiSets" => FALSE,
1123 "NumAjaxResults" => 50,
1124 "ViewingPrivilege" => NULL,
1125 "AuthoringPrivilege" => PRIV_MYRESOURCEADMIN,
1126 "EditingPrivilege" => PRIV_RESOURCEADMIN,
1127 "ImagePreviewPrivilege" => NULL,
1128 "TreeBrowsingPrivilege" => NULL,
1129 "ViewingUserIsValue" => self::USERISVALUE_UNSET,
1130 "AuthoringUserIsValue" => self::USERISVALUE_UNSET,
1131 "EditingUserIsValue" => self::USERISVALUE_UNSET,
1132 "ViewingUserValue" => NULL,
1133 "AuthoringUserValue" => NULL,
1134 "EditingUserValue" => NULL,
1135 "PointPrecision" => 8,
1136 "PointDecimalDigits" => 5,
1137 "UserPrivilegeRestrictions" => array(),
1138 "UpdateMethod" => "NoAutoUpdate",
1139 # 9999 is the default max value because default number field length is 4
1140 "MaxValue" => 9999);
1141
1145 public static $TypeBasedDefaults = array(
1146 MetadataSchema::MDFTYPE_TEXT => array(
1147 "DefaultValue" => NULL,
1148 "SearchWeight" => 1,
1149 "TextFieldSize" => 50,
1150 "MaxLength" => 100),
1151 MetadataSchema::MDFTYPE_PARAGRAPH => array(
1152 "DefaultValue" => NULL,
1153 "SearchWeight" => 1,
1154 "TextFieldSize" => 50,
1155 "MaxLength" => 100),
1156 MetadataSchema::MDFTYPE_NUMBER => array(
1157 "DefaultValue" => NULL,
1158 "SearchWeight" => 1,
1159 "TextFieldSize" => 4,
1160 "MaxLength" => 100),
1161 MetadataSchema::MDFTYPE_DATE => array(
1162 "DefaultValue" => NULL,
1163 "SearchWeight" => 1,
1164 "TextFieldSize" => 10,
1165 "MaxLength" => 100),
1166 MetadataSchema::MDFTYPE_TIMESTAMP => array(
1167 "DefaultValue" => NULL,
1168 "SearchWeight" => 1,
1169 "TextFieldSize" => 50,
1170 "MaxLength" => 100),
1171 MetadataSchema::MDFTYPE_FLAG => array(
1172 "DefaultValue" => NULL,
1173 "SearchWeight" => 1,
1174 "TextFieldSize" => 50,
1175 "MaxLength" => 100),
1176 MetadataSchema::MDFTYPE_TREE => array(
1177 "DefaultValue" => NULL,
1178 "SearchWeight" => 1,
1179 "TextFieldSize" => 50,
1180 "MaxLength" => 100),
1181 MetadataSchema::MDFTYPE_CONTROLLEDNAME => array(
1182 "DefaultValue" => NULL,
1183 "SearchWeight" => 3,
1184 "TextFieldSize" => 50,
1185 "MaxLength" => 100),
1186 MetadataSchema::MDFTYPE_OPTION => array(
1187 "DefaultValue" => NULL,
1188 "SearchWeight" => 3,
1189 "TextFieldSize" => 50,
1190 "MaxLength" => 100),
1191 MetadataSchema::MDFTYPE_USER => array(
1192 "DefaultValue" => NULL,
1193 "SearchWeight" => 1,
1194 "TextFieldSize" => 50,
1195 "MaxLength" => 100),
1196 MetadataSchema::MDFTYPE_IMAGE => array(
1197 "DefaultValue" => NULL,
1198 "SearchWeight" => 1,
1199 "TextFieldSize" => 50,
1200 "MaxLength" => 100),
1201 MetadataSchema::MDFTYPE_FILE => array(
1202 "DefaultValue" => NULL,
1203 "SearchWeight" => 1,
1204 "TextFieldSize" => 50,
1205 "MaxLength" => 100),
1206 MetadataSchema::MDFTYPE_URL => array(
1207 "DefaultValue" => NULL,
1208 "SearchWeight" => 1,
1209 "TextFieldSize" => 50,
1210 "MaxLength" => 255),
1211 MetadataSchema::MDFTYPE_POINT => array(
1212 "DefaultValue" => array("X" => NULL, "Y" => NULL),
1213 "SearchWeight" => 1,
1214 "TextFieldSize" => 10,
1215 "MaxLength" => 100));
1216
1221 public function SetDefaults()
1222 {
1223 # set defaults that are the same for every field
1224 foreach (self::$FixedDefaults as $Key => $Value)
1225 {
1226 $this->$Key($Value);
1227 }
1228
1229 # set defaults that depend on the type of the field
1230 foreach (self::$TypeBasedDefaults[$this->Type()] as $Key => $Value)
1231 {
1232 $this->$Key($Value);
1233 }
1234
1235 # tweak the update method if dealing with the date of record creation
1236 if ($this->Name() == "Date Of Record Creation")
1237 {
1238 $this->UpdateMethod("OnRecordCreate");
1239 }
1240 }
1241
1242 # remove field from database (only for use by MetadataSchema object)
1243 function Drop()
1244 {
1245 # clear other database entries as appropriate for field type
1246 $DB = $this->DB;
1247 $DBFieldName = $this->DBFields["DBFieldName"];
1248 switch (MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]])
1249 {
1250 case MetadataSchema::MDFTYPE_TEXT:
1251 case MetadataSchema::MDFTYPE_PARAGRAPH:
1252 case MetadataSchema::MDFTYPE_NUMBER:
1253 case MetadataSchema::MDFTYPE_USER:
1254 case MetadataSchema::MDFTYPE_IMAGE:
1255 case MetadataSchema::MDFTYPE_TIMESTAMP:
1256 case MetadataSchema::MDFTYPE_URL:
1257 case MetadataSchema::MDFTYPE_FLAG:
1258 # remove field from resources table
1259 if ($DB->FieldExists("Resources", $DBFieldName))
1260 {
1261 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."`");
1262 }
1263 break;
1264
1265 case MetadataSchema::MDFTYPE_POINT:
1266 if ($DB->FieldExists("Resources", $DBFieldName."X"))
1267 {
1268 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."X`");
1269 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Y`");
1270 }
1271 break;
1272
1273 case MetadataSchema::MDFTYPE_DATE:
1274 # remove fields from resources table
1275 if ($DB->FieldExists("Resources", $DBFieldName."Begin"))
1276 {
1277 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Begin`");
1278 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."End`");
1279 $DB->Query("ALTER TABLE Resources DROP COLUMN `".$DBFieldName."Precision`");
1280 }
1281 break;
1282
1283 case MetadataSchema::MDFTYPE_TREE:
1284 $DB->Query("SELECT ClassificationId FROM Classifications "
1285 ."WHERE FieldId = ".$this->Id());
1286 $TempDB = new Database();
1287 while ($ClassificationId = $DB->FetchField("ClassificationId"))
1288 {
1289 # remove any resource / name intersections
1290 $TempDB->Query("DELETE FROM ResourceClassInts WHERE "
1291 ."ClassificationId = ".$ClassificationId);
1292
1293 # remove controlled name
1294 $TempDB->Query("DELETE FROM Classifications WHERE "
1295 ."ClassificationId = ".$ClassificationId);
1296 }
1297 break;
1298
1299 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
1300 case MetadataSchema::MDFTYPE_OPTION:
1301 $DB->Query("SELECT ControlledNameId FROM ControlledNames "
1302 ."WHERE FieldId = ".$this->Id());
1303 $TempDB = new Database();
1304 while ($ControlledNameId = $DB->FetchField("ControlledNameId"))
1305 {
1306 # remove any resource / name intersections
1307 $TempDB->Query("DELETE FROM ResourceNameInts WHERE "
1308 ."ControlledNameId = ".$ControlledNameId);
1309
1310 # remove any variant names
1311 $TempDB->Query("DELETE FROM VariantNames WHERE "
1312 ."ControlledNameId = ".$ControlledNameId);
1313
1314 # remove controlled name
1315 $TempDB->Query("DELETE FROM ControlledNames WHERE "
1316 ."ControlledNameId = ".$ControlledNameId);
1317 }
1318 break;
1319
1320 case MetadataSchema::MDFTYPE_FILE:
1321 # for each file associated with this field
1322 $DB->Query("SELECT FileId FROM Files WHERE FieldId = '".$this->Id()."'");
1323 while ($FileId = $DB->FetchRow())
1324 {
1325 # delete file
1326 $File = new File(intval($FileId));
1327 $File->Delete();
1328 }
1329 break;
1330 }
1331
1332 # remove field from database
1333 $DB->Query("DELETE FROM MetadataFields "
1334 ."WHERE FieldId = '".$this->DBFields["FieldId"]."'");
1335
1336 # remove any qualifier associations
1337 $DB->Query("DELETE FROM FieldQualifierInts WHERE MetadataFieldId = '"
1338 .$this->DBFields["FieldId"]."'");
1339
1340 # remove the field from the display and edit order
1341 try
1342 {
1343 $DisplayOrder = MetadataFieldOrder::GetDisplayOrderObject();
1344 $EditOrder = MetadataFieldOrder::GetEditOrderObject();
1345
1346 # remove it from the dispaly and edit oorder
1347 $DisplayOrder->RemoveItem($this->Id(), "MetadataField");
1348 $EditOrder->RemoveItem($this->Id(), "MetadataField");
1349
1350 # remove field from any metadata field groups in the display order
1351 foreach ($DisplayOrder->GetItemIds() as $Item)
1352 {
1353 if ($Item["Type"] == "MetadataFieldGroup")
1354 {
1355 $Group = new MetadataFieldGroup($Item["ID"]);
1356 $Group->RemoveItem($this->Id(), "MetadataField");
1357 }
1358 }
1359
1360 # remove field from any metadata field groups in the edit order
1361 foreach ($EditOrder->GetItemIds() as $Item)
1362 {
1363 if ($Item["Type"] == "MetadataFieldGroup")
1364 {
1365 $Group = new MetadataFieldGroup($Item["ID"]);
1366 $Group->RemoveItem($this->Id(), "MetadataField");
1367 }
1368 }
1369 } catch (Exception $Exception) {}
1370 }
1371
1372 # modify any database fields
1373 private function ModifyField($NewName = NULL, $NewType = NULL)
1374 {
1375 # grab old DB field name
1376 $OldDBFieldName = $this->DBFields["DBFieldName"];
1377 $OldFieldType = NULL;
1378
1379 # if new field name supplied
1380 if ($NewName != NULL)
1381 {
1382 # cache the old name for options and controllednames below
1383 $OldName = $this->DBFields["FieldName"];
1384
1385 # store new name
1386 $this->UpdateValue("FieldName", $NewName);
1387
1388 # determine new DB field name
1389 $NewDBFieldName = $this->NormalizeFieldNameForDB($NewName);
1390
1391 # store new database field name
1392 $this->DBFields["DBFieldName"] = $NewDBFieldName;
1393 }
1394 else
1395 {
1396 # set new field name equal to old field name
1397 $NewDBFieldName = $OldDBFieldName;
1398 }
1399
1400 # if new type supplied
1401 if ($NewType != NULL)
1402 {
1403 # grab old field type
1404 $OldFieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
1405
1406 # store new field type
1407 $this->UpdateValue("FieldType", MetadataField::$FieldTypeDBEnums[$NewType]);
1408 }
1409
1410 # if this is not a temporary field
1411 if ($this->Id() >= 0)
1412 {
1413 # modify field in DB as appropriate for field type
1414 $DB = $this->DB;
1415 $FieldType = MetadataField::$FieldTypePHPEnums[$this->DBFields["FieldType"]];
1416 switch ($FieldType)
1417 {
1418 case MetadataSchema::MDFTYPE_TEXT:
1419 case MetadataSchema::MDFTYPE_PARAGRAPH:
1420 case MetadataSchema::MDFTYPE_URL:
1421 # alter field declaration in Resources table
1422 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1423 .$OldDBFieldName."` `"
1424 .$NewDBFieldName."` TEXT "
1425 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1426 break;
1427
1428 case MetadataSchema::MDFTYPE_NUMBER:
1429 case MetadataSchema::MDFTYPE_USER:
1430 # alter field declaration in Resources table
1431 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1432 .$OldDBFieldName."` `"
1433 .$NewDBFieldName."` INT "
1434 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1435 break;
1436
1437 case MetadataSchema::MDFTYPE_POINT:
1438 $Precision = $this->UpdateValue("PointPrecision",
1439 DB_NOVALUE);
1440 $Digits = $this->UpdateValue("PointDecimalDigits",
1441 DB_NOVALUE);
1442 $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
1443 ."`".$OldDBFieldName."X` "
1444 ."`".$NewDBFieldName."X`".
1445 " DECIMAL(".$Precision.",".$Digits.")");
1446 $DB->Query("ALTER TABLE Resources CHANGE COLUMN "
1447 ."`".$OldDBFieldName."Y` "
1448 ."`".$NewDBFieldName."Y`".
1449 " DECIMAL(".$Precision.",".$Digits.")");
1450 break;
1451
1452 case MetadataSchema::MDFTYPE_FILE:
1453 # if DB field name has changed
1454 if ($NewDBFieldName != $OldDBFieldName)
1455 {
1456 # alter field declaration in Resources table
1457 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1458 .$OldDBFieldName."` `"
1459 .$NewDBFieldName."` TEXT");
1460 }
1461 break;
1462
1463 case MetadataSchema::MDFTYPE_IMAGE:
1464 # if DB field name has changed
1465 if ($NewDBFieldName != $OldDBFieldName)
1466 {
1467 # alter field declaration in Resources table
1468 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1469 .$OldDBFieldName."` `"
1470 .$NewDBFieldName."` INT");
1471 }
1472 break;
1473
1474 case MetadataSchema::MDFTYPE_FLAG:
1475 # alter field declaration in Resources table
1476 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1477 .$OldDBFieldName."` `"
1478 .$NewDBFieldName."` INT"
1479 ." DEFAULT ".intval($this->DefaultValue()));
1480
1481 # set any unset values to default
1482 $DB->Query("UPDATE Resources SET `".$NewDBFieldName
1483 ."` = ".intval($this->DefaultValue())
1484 ." WHERE `".$NewDBFieldName."` IS NULL");
1485 break;
1486
1487 case MetadataSchema::MDFTYPE_DATE:
1488 # if new type supplied and new type is different from old
1489 if (($NewType != NULL) && ($NewType != $OldFieldType))
1490 {
1491 # if old type was time stamp
1492 if ($OldFieldType == MetadataSchema::MDFTYPE_TIMESTAMP)
1493 {
1494 # change time stamp field in resources table to begin date
1495 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1496 .$OldDBFieldName."` `"
1497 .$NewDBFieldName."Begin` DATE "
1498 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1499
1500 # add end date and precision fields
1501 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."End"
1502 ."` DATE");
1503 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$NewDBFieldName."Precision`"
1504 ." INT ".($Optional ? "" : "NOT NULL"));
1505
1506 # set precision to reflect time stamp content
1507 $DB->Query("UPDATE Resources SET `".$NewDBFieldName."Precision` = "
1508 .(DATEPRE_BEGINYEAR|DATEPRE_BEGINMONTH|DATEPRE_BEGINDAY));
1509 }
1510 else
1511 {
1512 exit("<br>ERROR: Attempt to convert metadata field to date from type other than timestamp<br>\n");
1513 }
1514 }
1515 else
1516 {
1517 # change name of fields
1518 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1519 .$OldDBFieldName."Begin` `"
1520 .$NewDBFieldName."Begin` DATE "
1521 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1522 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1523 .$OldDBFieldName."End` `"
1524 .$NewDBFieldName."End` DATE "
1525 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1526 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1527 .$OldDBFieldName."Precision` `"
1528 .$NewDBFieldName."Precision` INT "
1529 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1530 }
1531 break;
1532
1533 case MetadataSchema::MDFTYPE_TIMESTAMP:
1534 # if new type supplied and new type is different from old
1535 if (($NewType != NULL) && ($NewType != $OldFieldType))
1536 {
1537 # if old type was date
1538 if ($OldFieldType == MetadataSchema::MDFTYPE_DATE)
1539 {
1540 # change begin date field in resource table to time stamp
1541 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1542 .$OldDBFieldName."Begin` `"
1543 .$NewDBFieldName."` DATETIME "
1544 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1545
1546 # drop end date and precision fields
1547 $DB->Query("ALTER TABLE Resources DROP COLUMN `"
1548 .$OldDBFieldName."End`");
1549 $DB->Query("ALTER TABLE Resources DROP COLUMN `"
1550 .$OldDBFieldName."Precision`");
1551 }
1552 else
1553 {
1554 exit("<br>ERROR: Attempt to convert metadata field to time stamp from type other than date<br>\n");
1555 }
1556 }
1557 else
1558 {
1559 # change name of field
1560 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1561 .$OldDBFieldName."` `"
1562 .$NewDBFieldName."` DATETIME "
1563 .($this->DBFields["Optional"] ? "" : "NOT NULL"));
1564 }
1565 break;
1566
1567 case MetadataSchema::MDFTYPE_TREE:
1568 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
1569 case MetadataSchema::MDFTYPE_OPTION:
1570 break;
1571 }
1572
1573 # if qualifier DB field exists
1574 if ($DB->FieldExists("Resources", $OldDBFieldName."Qualifier"))
1575 {
1576 # rename qualifier DB field
1577 $DB->Query("ALTER TABLE Resources CHANGE COLUMN `"
1578 .$OldDBFieldName."Qualifier` `"
1579 .$NewDBFieldName."Qualifier` INT ");
1580 }
1581 }
1582 }
1583
1584 # convenience functions to supply parameters to Database->UpdateValue()
1585 private function UpdateValue($FieldName, $NewValue)
1586 {
1587 return $this->DB->UpdateValue("MetadataFields", $FieldName, $NewValue,
1588 "FieldId = ".intval($this->DBFields["FieldId"]),
1589 $this->DBFields);
1590 }
1591 private function UpdateIntValue($FieldName, $NewValue)
1592 {
1593 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1594 "FieldId = ".intval($this->DBFields["FieldId"]),
1595 $this->DBFields);
1596 }
1597 private function UpdateFloatValue($FieldName, $NewValue)
1598 {
1599 return $this->DB->UpdateFloatValue("MetadataFields", $FieldName, $NewValue,
1600 "FieldId = ".intval($this->DBFields["FieldId"]),
1601 $this->DBFields);
1602 }
1603 private function UpdateBoolValue($FieldName, $NewValue)
1604 {
1605 $NewValue = $this->TranslateStringToConstants($NewValue);
1606 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1607 "FieldId = ".intval($this->DBFields["FieldId"]),
1608 $this->DBFields);
1609 }
1610 private function UpdateConstValue($FieldName, $NewValue, $ClassName=NULL)
1611 {
1612 $NewValue = $this->TranslateStringToConstants($NewValue, $ClassName);
1613 return $this->DB->UpdateIntValue("MetadataFields", $FieldName, $NewValue,
1614 "FieldId = ".intval($this->DBFields["FieldId"]),
1615 $this->DBFields);
1616 }
1617
1618 # normalize field name for use as database field name
1619 private function NormalizeFieldNameForDB($Name)
1620 {
1621 return preg_replace("/[^a-z0-9]/i", "", $Name);
1622 }
1623
1624 # add any needed database fields and/or entries
1625 private function AddDatabaseFields()
1626 {
1627 # grab values for common use
1628 $DB = $this->DB;
1629 $FieldName = $this->Name();
1630 $DBFieldName = $this->DBFieldName();
1631 $Optional = $this->Optional();
1632 $DefaultValue = $this->DefaultValue();
1633
1634 # set up field(s) based on field type
1635 switch ($this->Type())
1636 {
1637 case MetadataSchema::MDFTYPE_TEXT:
1638 case MetadataSchema::MDFTYPE_PARAGRAPH:
1639 case MetadataSchema::MDFTYPE_URL:
1640 # add field to resources table (if not already present)
1641 if (!$DB->FieldExists("Resources", $DBFieldName))
1642 {
1643 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1644 ."` TEXT ".($Optional ? "" : "NOT NULL"));
1645 }
1646
1647 # if default value supplied
1648 if ($DefaultValue != NULL)
1649 {
1650 # set all existing records to default value
1651 $DB->Query("UPDATE Resources SET `"
1652 .$DBFieldName."` = '".addslashes($DefaultValue)."'");
1653 }
1654 break;
1655
1656 case MetadataSchema::MDFTYPE_NUMBER:
1657 # add field to resources table (if not already present)
1658 if (!$DB->FieldExists("Resources", $DBFieldName))
1659 {
1660 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1661 ."` INT ".($Optional ? "" : "NOT NULL"));
1662 }
1663
1664 # if default value supplied
1665 if ($DefaultValue != NULL)
1666 {
1667 # set all existing records to default value
1668 $DB->Query("UPDATE Resources SET `"
1669 .$DBFieldName."` = '".addslashes($DefaultValue)."'");
1670 }
1671 break;
1672
1673 case MetadataSchema::MDFTYPE_POINT:
1674 if (!$DB->FieldExists("Resources", $DBFieldName."X"))
1675 {
1676 $Precision = $this->UpdateValue("PointPrecision",
1677 DB_NOVALUE);
1678 $Digits = $this->UpdateValue("PointDecimalDigits",
1679 DB_NOVALUE);
1680
1681 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1682 .$DBFieldName."X`".
1683 " DECIMAL(".$Precision.",".$Digits.")");
1684 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1685 .$DBFieldName."Y`".
1686 " DECIMAL(".$Precision.",".$Digits.")");
1687 }
1688
1689 break;
1690 case MetadataSchema::MDFTYPE_FLAG:
1691 # if field is not already present in database
1692 if (!$DB->FieldExists("Resources", $DBFieldName))
1693 {
1694 # add field to resources table
1695 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1696 ."` INT DEFAULT ".intval($DefaultValue));
1697
1698 # set all existing records to default value
1699 $DB->Query("UPDATE Resources SET `"
1700 .$DBFieldName."` = ".intval($DefaultValue));
1701 }
1702 break;
1703
1704 case MetadataSchema::MDFTYPE_USER:
1705 # add field to resources table (if not already present)
1706 if (!$DB->FieldExists("Resources", $DBFieldName))
1707 {
1708 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1709 ."` INT ".($Optional ? "" : "NOT NULL"));
1710 }
1711 break;
1712
1713 case MetadataSchema::MDFTYPE_FILE:
1714 # add fields to resources table (if not already present)
1715 if (!$DB->FieldExists("Resources", $DBFieldName))
1716 {
1717 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1718 .$DBFieldName."` TEXT");
1719 }
1720 break;
1721
1722 case MetadataSchema::MDFTYPE_IMAGE:
1723 # add fields to resources table (if not already present)
1724 if (!$DB->FieldExists("Resources", $DBFieldName))
1725 {
1726 $DB->Query("ALTER TABLE Resources ADD COLUMN `"
1727 .$DBFieldName."` INT");
1728 }
1729 break;
1730
1731 case MetadataSchema::MDFTYPE_DATE:
1732 # add fields to resources table (if not already present)
1733 if (!$DB->FieldExists("Resources", $DBFieldName."Begin"))
1734 {
1735 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Begin`"
1736 ." DATE ".($Optional ? "" : "NOT NULL"));
1737 }
1738 if (!$DB->FieldExists("Resources", $DBFieldName."End"))
1739 {
1740 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."End`"
1741 ." DATE");
1742 }
1743 if (!$DB->FieldExists("Resources", $DBFieldName."Precision"))
1744 {
1745 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName."Precision`"
1746 ." INT ".($Optional ? "" : "NOT NULL"));
1747 }
1748 break;
1749
1750 case MetadataSchema::MDFTYPE_TIMESTAMP:
1751 # add fields to resources table (if not already present)
1752 if (!$DB->FieldExists("Resources", $DBFieldName))
1753 {
1754 $DB->Query("ALTER TABLE Resources ADD COLUMN `".$DBFieldName
1755 ."` DATETIME ".($Optional ? "" : "NOT NULL"));
1756 }
1757 break;
1758
1759 case MetadataSchema::MDFTYPE_TREE:
1760 case MetadataSchema::MDFTYPE_CONTROLLEDNAME:
1761 case MetadataSchema::MDFTYPE_OPTION:
1762 break;
1763
1764 default:
1765 exit("<br>ERROR: Attempt to add database fields for illegal metadata field type<br>\n");
1766 break;
1767 }
1768 }
1769
1777 private function TranslateStringToConstants($CString, $ClassName = NULL)
1778 {
1779 # if not a string return value unchanged to caller
1780 if (!is_string($CString) || ($CString === DB_NOVALUE))
1781 {
1782 $ReturnValue = $CString;
1783 }
1784 # handle booleans as a special case
1785 elseif (strtoupper(trim($CString)) == "TRUE")
1786 {
1787 $ReturnValue = TRUE;
1788 }
1789 elseif (strtoupper(trim($CString)) == "FALSE")
1790 {
1791 $ReturnValue = FALSE;
1792 }
1793 else
1794 {
1795 # assume no values will be found
1796 $ReturnValue = NULL;
1797
1798 # split apart any ORed-together values
1799 $Values = explode("|", $CString);
1800
1801 # for each value found
1802 foreach ($Values as $Value)
1803 {
1804 # trim off any extraneous whitespace
1805 $Value = trim($Value);
1806
1807 # add class name prefix to constant name if requested
1808 if ($ClassName) { $Value = $ClassName."::".$Value; }
1809
1810 # if value corresponds to a constant
1811 if (defined($Value))
1812 {
1813 # add constant to return value
1814 $ReturnValue = ($ReturnValue === NULL)
1815 ? constant($Value)
1816 : ($ReturnValue | constant($Value));
1817 }
1818 }
1819
1820 # if no corresponding constants were found
1821 if ($ReturnValue === NULL)
1822 {
1823 # return original value to caller
1824 $ReturnValue = $CString;
1825 }
1826 }
1827
1828 # return result to caller
1829 return $ReturnValue;
1830 }
1831
1832 }