CWIS Developer Documentation
MetadataSchema.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: MetadataSchema.php
4 #
5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2012-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis
8 #
9 
13 class MetadataSchema extends ItemFactory {
14 
15  # ---- PUBLIC INTERFACE --------------------------------------------------
16 
17  # metadata field base types
18  # (must parallel MetadataFields.FieldType declaration in install/CreateTables.sql
19  # and MetadataField::$FieldTypeDBEnums declaration below)
20  const MDFTYPE_TEXT = 1;
21  const MDFTYPE_PARAGRAPH = 2;
22  const MDFTYPE_NUMBER = 4;
23  const MDFTYPE_DATE = 8;
24  const MDFTYPE_TIMESTAMP = 16;
25  const MDFTYPE_FLAG = 32;
26  const MDFTYPE_TREE = 64;
28  const MDFTYPE_OPTION = 256;
29  const MDFTYPE_USER = 512;
30  const MDFTYPE_IMAGE = 1024;
31  const MDFTYPE_FILE = 2048;
32  const MDFTYPE_URL = 4096;
33  const MDFTYPE_POINT = 8192;
34  const MDFTYPE_REFERENCE = 16384;
35 
36  # types of field ordering
37  const MDFORDER_DISPLAY = 1;
38  const MDFORDER_EDITING = 2;
40 
41  # error status codes
42  const MDFSTAT_OK = 1;
43  const MDFSTAT_ERROR = 2;
47  const MDFSTAT_ILLEGALNAME = 32;
49  const MDFSTAT_ILLEGALLABEL = 128;
50 
51  # special schema IDs
52  const SCHEMAID_DEFAULT = 0;
53  const SCHEMAID_USER = 1;
54 
55  # resource names
56  const RESOURCENAME_DEFAULT = "Resource";
57  const RESOURCENAME_USER = "User";
58 
59  # names used for display and edit orders
60  const ORDER_DISPLAY_NAME = "Display";
61  const ORDER_EDIT_NAME = "Edit";
62 
71  function __construct($SchemaId = self::SCHEMAID_DEFAULT)
72  {
73  # set schema ID
74  $this->Id = $SchemaId;
75 
76  # set up item factory base class
77  $this->ItemFactory(
78  "MetadataField", "MetadataFields", "FieldId", "FieldName", FALSE,
79  "SchemaId = ".intval($this->Id()));
80 
81  # load schema info from database
82  $this->DB->Query("SELECT * FROM MetadataSchemas"
83  ." WHERE SchemaId = ".intval($SchemaId));
84  if ($this->DB->NumRowsSelected() < 1)
85  {
86  throw new Exception("Attempt to load metadata schema with "
87  ." invalid ID (".$SchemaId.").");
88  }
89  $Info = $this->DB->FetchRow();
90  $this->Name = $Info["Name"];
91  $this->AuthoringPrivileges = new PrivilegeSet($Info["AuthoringPrivileges"]);
92  $this->EditingPrivileges = new PrivilegeSet($Info["EditingPrivileges"]);
93  $this->ViewingPrivileges = new PrivilegeSet($Info["ViewingPrivileges"]);
94  $this->ViewPage = $Info["ViewPage"];
95 
96  # start with field info caching enabled
97  $this->CachingOn = TRUE;
98  }
99 
109  static function GetConstantName($Value, $Prefix = NULL)
110  {
111  # retrieve all constants for class
112  $Reflect = new ReflectionClass(get_class());
113  $Constants = $Reflect->getConstants();
114 
115  # for each constant
116  foreach ($Constants as $CName => $CValue)
117  {
118  # if value matches and prefix (if supplied) matches
119  if (($CValue == $Value)
120  && (($Prefix === NULL) || (strpos($CName, $Prefix) === 0)))
121  {
122  # return name to caller
123  return $CName;
124  }
125  }
126 
127  # report to caller that no matching constant was found
128  return NULL;
129  }
130 
145  static function Create($Name,
146  PrivilegeSet $AuthorPrivs = NULL,
147  PrivilegeSet $EditPrivs = NULL,
148  PrivilegeSet $ViewPrivs = NULL,
149  $ViewPage = "",
150  $ResourceName = NULL)
151  {
152  # supply privilege settings if none provided
153  if ($AuthorPrivs === NULL) { $AuthorPrivs = new PrivilegeSet(); }
154  if ($EditPrivs === NULL) { $EditPrivs = new PrivilegeSet(); }
155  if ($ViewPrivs === NULL) { $ViewPrivs = new PrivilegeSet(); }
156 
157  # add schema to database
158  $DB = new Database;
159  if (strtoupper($Name) == "DEFAULT")
160  {
161  $Id = self::SCHEMAID_DEFAULT;
162  }
163  elseif (strtoupper($Name) == "USER")
164  {
165  $Id = self::SCHEMAID_USER;
166  }
167  else
168  {
169  $Id = $DB->Query("SELECT SchemaId FROM MetadataSchemas"
170  ." ORDER BY SchemaId DESC LIMIT 1", "SchemaId") + 1;
171  }
172  $DB->Query("INSERT INTO MetadataSchemas"
173  ." (SchemaId, Name, ViewPage,"
174  ." AuthoringPrivileges, EditingPrivileges, ViewingPrivileges)"
175  ." VALUES (".intval($Id).","
176  ."'".addslashes($Name)."',"
177  ."'".mysql_escape_string($ViewPage)."',"
178  ."'".mysql_escape_string($AuthorPrivs->Data())."',"
179  ."'".mysql_escape_string($EditPrivs->Data())."',"
180  ."'".mysql_escape_string($ViewPrivs->Data())."')");
181 
182  # construct the new schema
183  $Schema = new MetadataSchema($Id);
184 
185  # set schema name if none supplied
186  if (!strlen($Name))
187  {
188  $Schema->Name("Metadata Schema ".$Id);
189  }
190 
191  # set the resource name if one is supplied
192  if (!is_null($ResourceName))
193  {
194  $Schema->ResourceName($ResourceName);
195  }
196 
197  # Nudge the Edit and Display order so that they will exist
198  $Schema->GetEditOrder();
199  $Schema->GetDisplayOrder();
200 
201  # return the new schema
202  return $Schema;
203  }
204 
210  static function SchemaExistsWithId($SchemaId)
211  {
212  $DB = new Database();
213  $DB->Query("SELECT * FROM MetadataSchemas"
214  ." WHERE SchemaId = ".intval($SchemaId));
215  return ($DB->NumRowsSelected() > 0) ? TRUE : FALSE;
216  }
217 
223  function Id()
224  {
225  # return value to caller
226  return $this->Id;
227  }
228 
234  function Name($NewValue = NULL)
235  {
236  # set new name if one supplied
237  if ($NewValue !== NULL)
238  {
239  $this->DB->Query("UPDATE MetadataSchemas"
240  ." SET Name = '".addslashes($NewValue)."'"
241  ." WHERE SchemaId = '".intval($this->Id)."'");
242  $this->Name = $NewValue;
243  }
244 
245  # get the name if it hasn't been cached yet
246  if (!isset($this->Name))
247  {
248  $this->Name = $this->DB->Query("SELECT * FROM MetadataSchemas"
249  ." WHERE SchemaId = '".intval($this->Id)."'", "Name");
250  }
251 
252  # return current value to caller
253  return $this->Name;
254  }
255 
261  function ResourceName($NewValue = NULL)
262  {
263  # set new resource name if one supplied
264  if ($NewValue !== NULL)
265  {
266  $this->DB->Query("
267  UPDATE MetadataSchemas
268  SET ResourceName = '".addslashes($NewValue)."'
269  WHERE SchemaId = '".intval($this->Id)."'");
270  $this->ResourceName = $NewValue;
271  }
272 
273  # get the name if it hasn't been cached yet
274  if (!isset($this->ResourceName))
275  {
276  $this->ResourceName = $this->DB->Query("
277  SELECT * FROM MetadataSchemas
278  WHERE SchemaId = '".intval($this->Id)."'",
279  "ResourceName");
280 
281  # use the default resource name if one isn't set
282  if (!strlen(trim($this->ResourceName)))
283  {
284  $this->ResourceName = self::RESOURCENAME_DEFAULT;
285  }
286  }
287 
288  # return current value to caller
289  return $this->ResourceName;
290  }
291 
297  function ViewPage($NewValue = NULL)
298  {
299  # set new viewing page if one supplied
300  if ($NewValue !== NULL)
301  {
302  $this->DB->Query("UPDATE MetadataSchemas"
303  ." SET ViewPage = '".addslashes($NewValue)."'"
304  ." WHERE SchemaId = '".intval($this->Id)."'");
305  $this->ViewPage = $NewValue;
306  }
307 
308  # get the view page if it hasn't been cached yet
309  if (!isset($this->ViewPage))
310  {
311  $this->ViewPage = $this->DB->Query("SELECT * FROM MetadataSchemas"
312  ." WHERE SchemaId = '".intval($this->Id)."'", "ViewPage");
313  }
314 
315  # return current value to caller
316  return $this->ViewPage;
317  }
318 
324  function AuthoringPrivileges(PrivilegeSet $NewValue = NULL)
325  {
326  # if new privileges supplied
327  if ($NewValue !== NULL)
328  {
329  # store new privileges in database
330  $this->DB->Query("UPDATE MetadataSchemas"
331  ." SET AuthoringPrivileges = '"
332  .mysql_escape_string($NewValue->Data())."'"
333  ." WHERE SchemaId = ".intval($this->Id));
334  $this->AuthoringPrivileges = $NewValue;
335  }
336 
337  # return current value to caller
338  return $this->AuthoringPrivileges;
339  }
340 
346  function EditingPrivileges(PrivilegeSet $NewValue = NULL)
347  {
348  # if new privileges supplied
349  if ($NewValue !== NULL)
350  {
351  # store new privileges in database
352  $this->DB->Query("UPDATE MetadataSchemas"
353  ." SET EditingPrivileges = '"
354  .mysql_escape_string($NewValue->Data())."'"
355  ." WHERE SchemaId = ".intval($this->Id));
356  $this->EditingPrivileges = $NewValue;
357  }
358 
359  # return current value to caller
360  return $this->EditingPrivileges;
361  }
362 
368  function ViewingPrivileges(PrivilegeSet $NewValue = NULL)
369  {
370  # if new privileges supplied
371  if ($NewValue !== NULL)
372  {
373  # store new privileges in database
374  $this->DB->Query("UPDATE MetadataSchemas"
375  ." SET ViewingPrivileges = '"
376  .mysql_escape_string($NewValue->Data())."'"
377  ." WHERE SchemaId = ".intval($this->Id));
378  $this->ViewingPrivileges = $NewValue;
379  }
380 
381  # return current value to caller
382  return $this->ViewingPrivileges;
383  }
384 
392  function UserCanAuthor($User)
393  {
394  # get authoring privilege set for schema
395  $AuthorPrivs = $this->AuthoringPrivileges();
396 
397  # get privilege set for user
398  $UserPrivs = $User->Privileges();
399 
400  # user can author if privileges are greater than resource set
401  $CanAuthor = $UserPrivs->IsGreaterThan($AuthorPrivs);
402 
403  # allow plugins to modify result of permission check
404  $SignalResult = $GLOBALS["AF"]->SignalEvent(
405  "EVENT_RESOURCE_AUTHOR_PERMISSION_CHECK", array(
406  "Schema" => $this,
407  "User" => $User,
408  "CanAuthor" => $CanAuthor));
409  $CanAuthor = $SignalResult["CanAuthor"];
410 
411  # report back to caller whether user can author field
412  return $CanAuthor;
413  }
414 
421  {
422  # get the query/GET parameters for the view page
423  $Query = parse_url($this->ViewPage(), PHP_URL_QUERY);
424 
425  # the URL couldn't be parsed
426  if (!is_string($Query))
427  {
428  return NULL;
429  }
430 
431  # parse the GET parameters out of the query string
432  $GetVars = ParseQueryString($Query);
433 
434  # search for the ID parameter
435  $Result = array_search("\$ID", $GetVars);
436 
437  return $Result !== FALSE ? $Result : NULL;
438  }
439 
452  function PathMatchesViewPage($Path)
453  {
454  # get the query/GET parameters for the view page
455  $Query = parse_url($this->ViewPage(), PHP_URL_QUERY);
456 
457  # can't perform matching if the URL couldn't be parsed
458  if (!is_string($Query))
459  {
460  return FALSE;
461  }
462 
463  # parse the GET parameters out of the query string
464  $GetVars = ParseQueryString($Query);
465 
466  # now, get the query/GET parameters from the path given
467  $PathQuery = parse_url($Path, PHP_URL_QUERY);
468 
469  # can't perform matching if the URL couldn't be parsed
470  if (!is_string($PathQuery))
471  {
472  return FALSE;
473  }
474 
475  # parse the GET parameters out of the path's query string
476  $PathGetVars = ParseQueryString($PathQuery);
477 
478  # make sure the given path GET parameters contain at least the GET
479  # parameters from the view page and that all non-variable parameters are
480  # equal. the path GET parameters may contain more, which is okay
481  foreach ($GetVars as $GetVarName => $GetVarValue)
482  {
483  # there's a required parameter that is not included in the path GET
484  # parameters
485  if (!array_key_exists($GetVarName, $PathGetVars))
486  {
487  return FALSE;
488  }
489 
490  # require the path's value to be equal to the view page's value if
491  # the view page's value is not a variable,
492  if ($PathGetVars[$GetVarName] != $GetVarValue
493  && (!strlen($GetVarValue) || $GetVarValue{0} != "$"))
494  {
495  return FALSE;
496  }
497  }
498 
499  # the path matches the view page path
500  return TRUE;
501  }
502 
507  function CacheData($NewValue)
508  {
509  $this->CachingOn = $NewValue;
510  }
511 
521  function AddField($FieldName, $FieldType, $Optional = TRUE, $DefaultValue = NULL)
522  {
523  # clear any existing error messages
524  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
525  { unset($this->ErrorMsgs[__METHOD__]); }
526 
527  # create new field
528  try
529  {
530  $Field = MetadataField::Create($this->Id(), $FieldType,
531  $FieldName, $Optional, $DefaultValue);
532  }
533  catch (Exception $Exception)
534  {
535  $this->ErrorMsgs[__METHOD__][] = $Exception->getMessage();
536  $Field = NULL;
537  }
538 
539  # return new field to caller
540  return $Field;
541  }
542 
555  function AddFieldsFromXmlFile($FileName, $TestRun = FALSE)
556  {
557  # clear loading status
558  $this->NewFields = array();
559  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
560  { unset($this->ErrorMsgs[__METHOD__]); }
561 
562  # check that file exists and is readable
563  if (!file_exists($FileName))
564  {
565  $this->ErrorMsgs[__METHOD__][] = "Could not find XML file '"
566  .$FileName."'.";
567  return FALSE;
568  }
569  elseif (!is_readable($FileName))
570  {
571  $this->ErrorMsgs[__METHOD__][] = "Could not read from XML file '"
572  .$FileName."'.";
573  return FALSE;
574  }
575 
576  # load XML from file
577  libxml_use_internal_errors(TRUE);
578  $XmlData = simplexml_load_file($FileName);
579  $Errors = libxml_get_errors();
580  libxml_use_internal_errors(FALSE);
581 
582  # if XML load failed
583  if ($XmlData === FALSE)
584  {
585  # retrieve XML error messages
586  foreach ($Errors as $Err)
587  {
588  $ErrType = ($Err->level == LIBXML_ERR_WARNING) ? "Warning"
589  : (($Err->level == LIBXML_ERR_WARNING) ? "Error"
590  : "Fatal Error");
591  $this->ErrorMsgs[__METHOD__][] = "XML ".$ErrType.": ".$Err->message
592  ." (".$Err->file.":".$Err->line.",".$Err->column.")";
593  }
594  }
595  # else if no metadata fields found record error message
596  elseif (!count($XmlData->MetadataField))
597  {
598  $this->ErrorMsgs[__METHOD__][] = "No metadata fields found.";
599  }
600  # else process metadata fields
601  else
602  {
603  # for each metadata field entry found
604  $FieldsAdded = 0;
605  $FieldIndex = 0;
606  foreach ($XmlData->MetadataField as $FieldXml)
607  {
608  $FieldIndex++;
609 
610  # pull out field type if present
611  if (isset($FieldXml->Type))
612  {
613  $FieldType = "MetadataSchema::".$FieldXml->Type;
614  if (!defined($FieldType))
615  {
616  $FieldType = "MetadataSchema::MDFTYPE_"
617  .strtoupper(preg_replace("/\\s+/", "",
618  $FieldXml->Type));
619  }
620  }
621 
622  # if required values are missing
623  if (!isset($FieldXml->Name) || !isset($FieldXml->Type)
624  || !defined($FieldType))
625  {
626  # add error message about required value missing
627  if (!isset($FieldXml->Name))
628  {
629  $this->ErrorMsgs[__METHOD__][] =
630  "Field name not found (MetadataField #"
631  .$FieldIndex.").";
632  }
633  else
634  {
635  $this->ErrorMsgs[__METHOD__][] =
636  "Valid type not found for field '"
637  .$FieldXml->Name."' (MetadataField #"
638  .$FieldIndex.").";
639  }
640  }
641  # else if there is not already a field with this name
642  elseif (!$this->NameIsInUse(trim($FieldXml->Name)))
643  {
644  # create new field
645  $Field = $this->AddField($FieldXml->Name, constant($FieldType));
646 
647  # if field creation failed
648  if ($Field === NULL)
649  {
650  # add any error message to our error list
651  $ErrorMsgs = $this->ErrorMessages("AddField");
652  foreach ($ErrorMsgs as $Msg)
653  {
654  $this->ErrorMsgs[__METHOD__][] =
655  $Msg." (AddField)";
656  }
657  }
658  else
659  {
660  # add field to list of created fields
661  $this->NewFields[$Field->Id()] = $Field;
662 
663  # for other field attributes
664  foreach ($FieldXml as $MethodName => $Value)
665  {
666  # if tags look valid and have not already been set
667  if (method_exists($Field, $MethodName)
668  && ($MethodName != "Name")
669  && ($MethodName != "Type"))
670  {
671  # if tag indicates privilege set
672  if (preg_match("/^[a-z]+Privileges\$/i",
673  $MethodName))
674  {
675  # save element for later processing
676  $PrivilegesToSet[$Field->Id()][$MethodName] = $Value;
677  }
678  else
679  {
680  # condense down any extraneous whitespace
681  $Value = preg_replace("/\s+/", " ", trim($Value));
682 
683  # set value for field
684  $Field->$MethodName($Value);
685  }
686  }
687  }
688 
689  # save the temp ID so that any privileges to set can be
690  # mapped to the actual ID when the field is made
691  # permanent
692  $TempId = $Field->Id();
693 
694  # make new field permanent
695  $Field->IsTempItem(FALSE);
696 
697  # map privileges to set to the permanent field ID
698  if (isset($PrivilegesToSet) &&
699  isset($PrivilegesToSet[$TempId]) )
700  {
701  # copy the privileges over
702  $PrivilegesToSet[$Field->Id()] =
703  $PrivilegesToSet[$TempId];
704 
705  # remove the values for the temp ID
706  unset($PrivilegesToSet[$TempId]);
707  }
708  }
709  }
710  }
711 
712  # if we have privileges to set
713  if (isset($PrivilegesToSet))
714  {
715  # for each field with privileges
716  foreach ($PrivilegesToSet as $FieldId => $Privileges)
717  {
718  # load the field for which to set the privileges
719  $Field = new MetadataField($FieldId);
720 
721  # for each set of privileges for field
722  foreach ($Privileges as $MethodName => $Value)
723  {
724  # convert privilege value
725  $Value = $this->ConvertXmlToPrivilegeSet($Value);
726 
727  # if conversion failed
728  if ($Value === NULL)
729  {
730  # add resulting error messages to our list
731  $ErrorMsgs = $this->ErrorMessages(
732  "ConvertXmlToPrivilegeSet");
733  foreach ($ErrorMsgs as $Msg)
734  {
735  $this->ErrorMsgs[__METHOD__][] =
736  $Msg." (ConvertXmlToPrivilegeSet)";
737  }
738  }
739  else
740  {
741  # set value for field
742  $Field->$MethodName($Value);
743  }
744  }
745  }
746  }
747 
748  # if errors were found during creation
749  if (array_key_exists(__METHOD__, $this->ErrorMsgs) || $TestRun)
750  {
751  # remove any fields that were created
752  foreach ($this->NewFields as $Field)
753  {
754  $Field->Drop();
755  }
756  $this->NewFields = array();
757  }
758  }
759 
760  # report success or failure based on whether errors were recorded
761  return (array_key_exists(__METHOD__, $this->ErrorMsgs)) ? FALSE : TRUE;
762  }
763 
769  function NewFields()
770  {
771  return $this->NewFields;
772  }
773 
783  function ErrorMessages($Method = NULL)
784  {
785  if ($Method === NULL)
786  {
787  return $this->ErrorMsgs;
788  }
789  else
790  {
791  if (!method_exists($this, $Method))
792  {
793  throw new Exception("Error messages requested for non-existent"
794  ." method (".$Method.").");
795  }
796  return array_key_exists(__CLASS__."::".$Method, $this->ErrorMsgs)
797  ? $this->ErrorMsgs[__CLASS__."::".$Method] : array();
798  }
799  }
800 
810  function AddFieldFromXml($Xml)
811  {
812  # assume field addition will fail
813  $Field = self::MDFSTAT_ERROR;
814 
815  # add XML prefixes if needed
816  $Xml = trim($Xml);
817  if (!preg_match("/^<\?xml/i", $Xml))
818  {
819  if (!preg_match("/^<document>/i", $Xml))
820  {
821  $Xml = "<document>".$Xml."</document>";
822  }
823  $Xml = "<?xml version='1.0'?".">".$Xml;
824  }
825 
826  # parse XML
827  $XmlData = simplexml_load_string($Xml);
828 
829  # if required values are present
830  if (is_object($XmlData)
831  && isset($XmlData->Name)
832  && isset($XmlData->Type)
833  && constant("MetadataSchema::".$XmlData->Type))
834  {
835  # create the metadata field
836  $Field = $this->AddField(
837  $XmlData->Name,
838  constant("MetadataSchema::".$XmlData->Type));
839 
840  # if field creation succeeded
841  if ($Field != NULL)
842  {
843  # for other field attributes
844  foreach ($XmlData as $MethodName => $Value)
845  {
846  # if they look valid and have not already been set
847  if (method_exists($Field, $MethodName)
848  && ($MethodName != "Name")
849  && ($MethodName != "Type"))
850  {
851  # if tag indicates privilege set
852  if (preg_match("/^[a-z]+Privileges\$/i",
853  $MethodName))
854  {
855  # save element for later processing
856  $PrivilegesToSet[$MethodName] = $Value;
857  }
858  else
859  {
860  # condense down any extraneous whitespace
861  $Value = preg_replace("/\s+/", " ", trim($Value));
862 
863  # set value for field
864  $Field->$MethodName($Value);
865  }
866  }
867  }
868 
869  # make new field permanent
870  $Field->IsTempItem(FALSE);
871 
872  # if we have privileges to set
873  if (isset($PrivilegesToSet))
874  {
875  # for each set of privileges for field
876  foreach ($PrivilegesToSet as $MethodName => $Value)
877  {
878  # convert privilege value
879  $Value = $this->ConvertXmlToPrivilegeSet($Value);
880 
881  # if conversion failed
882  if ($Value === NULL)
883  {
884  # add resulting error messages to our list
885  $ErrorMsgs = $this->ErrorMessages(
886  "ConvertXmlToPrivilegeSet");
887  foreach ($ErrorMsgs as $Msg)
888  {
889  $this->ErrorMsgs[__METHOD__][] =
890  $Msg." (ConvertXmlToPrivilegeSet)";
891  }
892  }
893  else
894  {
895  # set value for field
896  $Field->$MethodName($Value);
897  }
898  }
899  }
900  }
901  }
902 
903  # return new field (if any) to caller
904  return $Field;
905  }
906 
912  function DropField($FieldId)
913  {
914  $Field = $this->GetField($FieldId);
915  if ($Field !== NULL)
916  {
917  global $AF;
918  $AF->SignalEvent("EVENT_PRE_FIELD_DELETE",
919  array("FieldId" => $FieldId) );
920 
921  $Field->Drop();
922  return TRUE;
923  }
924  else
925  {
926  return FALSE;
927  }
928  }
929 
935  function GetField($FieldId)
936  {
937  static $Fields;
938 
939  # if caching is off or field is not already loaded
940  if (($this->CachingOn != TRUE) || !isset($Fields[$FieldId]))
941  {
942  # retrieve field
943  try
944  {
945  $Fields[$FieldId] = new MetadataField($FieldId);
946  }
947  catch (Exception $Exception)
948  {
949  $Fields[$FieldId] = NULL;
950  }
951  }
952 
953  # return field to caller
954  return $Fields[$FieldId];
955  }
956 
963  function GetFieldByName($FieldName, $IgnoreCase = FALSE)
964  {
965  $FieldId = $this->GetFieldIdByName($FieldName, $IgnoreCase);
966  return ($FieldId === NULL) ? NULL : $this->GetField($FieldId);
967  }
968 
975  function GetFieldByLabel($FieldLabel, $IgnoreCase = FALSE)
976  {
977  $FieldId = $this->GetFieldIdByLabel($FieldLabel, $IgnoreCase);
978  return ($FieldId === NULL) ? NULL : $this->GetField($FieldId);
979  }
980 
988  function GetFieldIdByName($FieldName, $IgnoreCase = FALSE)
989  {
990  static $FieldIdsByName;
991 
992  # if caching is off or field ID is already loaded
993  if (($this->CachingOn != TRUE) || !isset($FieldIdsByName[$this->Id][$FieldName]))
994  {
995  # retrieve field ID from DB
996  $Condition = $IgnoreCase
997  ? "WHERE LOWER(FieldName) = '".addslashes(strtolower($FieldName))."'"
998  : "WHERE FieldName = '".addslashes($FieldName)."'";
999  $Condition .= " AND SchemaId = ".intval($this->Id);
1000  $FieldIdsByName[$this->Id][$FieldName] = $this->DB->Query(
1001  "SELECT FieldId FROM MetadataFields ".$Condition, "FieldId");
1002  }
1003 
1004  return $FieldIdsByName[$this->Id][$FieldName];
1005  }
1006 
1014  function GetFieldIdByLabel($FieldLabel, $IgnoreCase = FALSE)
1015  {
1016  static $FieldIdsByLabel;
1017 
1018  # if caching is off or field ID is already loaded
1019  if (($this->CachingOn != TRUE) || !isset($FieldIdsByLabel[$FieldLabel]))
1020  {
1021  # retrieve field ID from DB
1022  $Condition = $IgnoreCase
1023  ? "WHERE LOWER(Label) = '".addslashes(strtolower($FieldLabel))."'"
1024  : "WHERE Label = '".addslashes($FieldLabel)."'";
1025  $Condition .= " AND SchemaId = ".intval($this->Id);
1026  $FieldIdsByLabel[$FieldLabel] = $this->DB->Query(
1027  "SELECT FieldId FROM MetadataFields ".$Condition, "FieldId");
1028  }
1029 
1030  return $FieldIdsByLabel[$FieldLabel];
1031  }
1032 
1038  function FieldExists($FieldName) { return $this->NameIsInUse($FieldName); }
1039 
1053  function GetFields($FieldTypes = NULL, $OrderType = NULL,
1054  $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1055  {
1056  # create empty array to pass back
1057  $Fields = array();
1058 
1059  # for each field type in database
1060  $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields"
1061  ." WHERE SchemaId = ".intval($this->Id)
1062  .(!$IncludeDisabledFields ? " AND Enabled != 0" : "")
1063  .(!$IncludeTempFields ? " AND FieldId >= 0" : ""));
1064  while ($Record = $this->DB->FetchRow())
1065  {
1066  # if field type is known
1067  if (array_key_exists($Record["FieldType"], MetadataField::$FieldTypePHPEnums))
1068  {
1069  # if no specific type requested or if field is of requested type
1070  if (($FieldTypes == NULL)
1071  || (MetadataField::$FieldTypePHPEnums[$Record["FieldType"]]
1072  & $FieldTypes))
1073  {
1074  # create field object and add to array to be passed back
1075  $Fields[$Record["FieldId"]] = $this->GetField($Record["FieldId"]);
1076  }
1077  }
1078  }
1079 
1080  # if field sorting requested
1081  if ($OrderType !== NULL)
1082  {
1083  # update field comparison ordering if not set yet
1084  if (!$this->FieldCompareOrdersSet())
1085  {
1086  $this->UpdateFieldCompareOrders();
1087  }
1088 
1089  $this->FieldCompareType = $OrderType;
1090 
1091  # sort field array by requested order type
1092  uasort($Fields, array($this, "CompareFieldOrder"));
1093  }
1094 
1095  # return array of field objects to caller
1096  return $Fields;
1097  }
1098 
1113  function GetFieldNames($FieldTypes = NULL, $OrderType = NULL,
1114  $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1115  {
1116  $Fields = $this->GetFields($FieldTypes, $OrderType,
1117  $IncludeDisabledFields, $IncludeTempFields);
1118 
1119  $FieldNames = array();
1120  foreach($Fields as $Field)
1121  {
1122  $FieldNames[$Field->Id()] = $Field->Name();
1123  }
1124 
1125  return $FieldNames;
1126  }
1127 
1144  function GetFieldsAsOptionList($OptionListName, $FieldTypes = NULL,
1145  $SelectedFieldId = NULL, $IncludeNullOption = TRUE,
1146  $AddEntries = NULL, $AllowMultiple = FALSE)
1147  {
1148  # retrieve requested fields
1149  $FieldNames = $this->GetFieldNames($FieldTypes);
1150 
1151  # transform field names to labels
1152  foreach ($FieldNames as $FieldId => $FieldName)
1153  {
1154  $FieldNames[$FieldId] = $this->GetField($FieldId)->GetDisplayName();
1155  }
1156 
1157  # begin HTML option list
1158  $Html = "<select id=\"".$OptionListName."\" name=\"".$OptionListName."\"";
1159 
1160  # if multiple selections should be allowed
1161  if ($AllowMultiple)
1162  {
1163  $Html .= " multiple=\"multiple\"";
1164  }
1165 
1166  $Html .= ">\n";
1167 
1168  if ($IncludeNullOption)
1169  {
1170  $Html .= "<option value=\"\">--</option>\n";
1171  }
1172 
1173  # make checking for IDs simpler
1174  if (!is_array($SelectedFieldId))
1175  {
1176  $SelectedFieldId = array($SelectedFieldId);
1177  }
1178 
1179  # for each metadata field
1180  foreach ($FieldNames as $Id => $Name)
1181  {
1182  # add entry for field to option list
1183  $Html .= "<option value=\"".$Id."\"";
1184  if (in_array($Id, $SelectedFieldId)) { $Html .= " selected"; }
1185  $Html .= ">".htmlspecialchars($Name)."</option>\n";
1186  }
1187 
1188  # if additional entries were requested
1189  if ($AddEntries)
1190  {
1191  foreach ($AddEntries as $Value => $Label)
1192  {
1193  $Html .= "<option value=\"".$Value."\"";
1194  if (in_array($Value, $SelectedFieldId))
1195  {
1196  $Html .= " selected";
1197  }
1198  $Html .= ">".htmlspecialchars($Label)."</option>\n";
1199  }
1200  }
1201 
1202  # end HTML option list
1203  $Html .= "</select>\n";
1204 
1205  # return constructed HTML to caller
1206  return $Html;
1207  }
1208 
1214  function GetFieldTypes()
1215  {
1217  }
1218 
1225  {
1227  }
1228 
1233  function RemoveQualifierAssociations($QualifierIdOrObject)
1234  {
1235  # sanitize qualifier ID or grab it from object
1236  $QualifierIdOrObject = is_object($QualifierIdOrObject)
1237  ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1238 
1239  # delete intersection records from database
1240  $this->DB->Query("DELETE FROM FieldQualifierInts"
1241  ." WHERE QualifierId = ".$QualifierIdOrObject);
1242  }
1243 
1249  function QualifierIsInUse($QualifierIdOrObject)
1250  {
1251  # sanitize qualifier ID or grab it from object
1252  $QualifierIdOrObject = is_object($QualifierIdOrObject)
1253  ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1254 
1255  # determine whether any fields use qualifier as default
1256  $DefaultCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
1257  ." FROM MetadataFields"
1258  ." WHERE DefaultQualifier = ".$QualifierIdOrObject,
1259  "RecordCount");
1260 
1261  # determine whether any fields are associated with qualifier
1262  $AssociationCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
1263  ." FROM FieldQualifierInts"
1264  ." WHERE QualifierId = ".$QualifierIdOrObject,
1265  "RecordCount");
1266 
1267  # report whether qualifier is in use based on defaults and associations
1268  return (($DefaultCount + $AssociationCount) > 0) ? TRUE : FALSE;
1269  }
1270 
1275  function GetHighestFieldId() { return $this->GetHighestItemId(); }
1276 
1284  static function StdNameToFieldMapping($MappedName, $FieldId = NULL)
1285  {
1286  if ($FieldId !== NULL)
1287  {
1288  self::$FieldMappings[$MappedName] = $FieldId;
1289  }
1290  return isset(self::$FieldMappings[$MappedName])
1291  ? self::$FieldMappings[$MappedName] : NULL;
1292  }
1293 
1300  static function FieldToStdNameMapping($FieldId)
1301  {
1302  if ($FieldId != -1)
1303  {
1304  foreach (self::$FieldMappings as $MappedName => $MappedFieldId)
1305  {
1306  if ($MappedFieldId == $FieldId)
1307  {
1308  return $MappedName;
1309  }
1310  }
1311  }
1312  return NULL;
1313  }
1314 
1322  function GetFieldByMappedName($MappedName)
1323  {
1324  return (self::StdNameToFieldMapping($MappedName) == NULL) ? NULL
1325  : $this->GetField($this->StdNameToFieldMapping($MappedName));
1326  }
1327 
1335  function GetFieldIdByMappedName($MappedName)
1336  {
1337  return self::StdNameToFieldMapping($MappedName);
1338  }
1339 
1344  function GetOwnedFields()
1345  {
1346  $Fields = array();
1347 
1348  $this->DB->Query("SELECT * FROM MetadataFields"
1349  ." WHERE Owner IS NOT NULL AND LENGTH(Owner) > 0"
1350  ." AND SchemaId = ".intval($this->Id));
1351 
1352  while (FALSE !== ($Row = $this->DB->FetchRow()))
1353  {
1354  $FieldId = $Row["FieldId"];
1355  $Fields[$FieldId] = $this->GetField($FieldId);
1356  }
1357 
1358  return $Fields;
1359  }
1360 
1366  static function GetAllSchemas()
1367  {
1368  $Database = new Database();
1369  $Schemas = array();
1370 
1371  # fetch the IDs all of the metadata schemas
1372  $Database->Query("SELECT * FROM MetadataSchemas");
1373  $SchemaIds = $Database->FetchColumn("SchemaId");
1374 
1375  # construct objects from the IDs
1376  foreach ($SchemaIds as $SchemaId)
1377  {
1378  $Schemas[$SchemaId] = new MetadataSchema($SchemaId);
1379  }
1380 
1381  return $Schemas;
1382  }
1383 
1389  static function SetOwnerListRetrievalFunction($Callback)
1390  {
1391  if (is_callable($Callback))
1392  {
1393  self::$OwnerListRetrievalFunction = $Callback;
1394  }
1395  }
1396 
1402  static function NormalizeOwnedFields()
1403  {
1404  # if an owner list retrieval function and default schema exists
1405  if (self::$OwnerListRetrievalFunction
1406  && self::SchemaExistsWithId(self::SCHEMAID_DEFAULT))
1407  {
1408  # retrieve the list of owners that currently exist
1409  $OwnerList = call_user_func(self::$OwnerListRetrievalFunction);
1410 
1411  # an array is expected
1412  if (is_array($OwnerList))
1413  {
1414  $Schema = new MetadataSchema(self::SCHEMAID_DEFAULT);
1415 
1416  # get each metadata field that is owned by a plugin
1417  $OwnedFields = $Schema->GetOwnedFields();
1418 
1419  # loop through each owned field
1420  foreach ($OwnedFields as $OwnedField)
1421  {
1422  # the owner of the current field
1423  $Owner = $OwnedField->Owner();
1424 
1425  # if the owner of the field is in the list of owners that
1426  # currently exist, i.e., available plugins
1427  if (in_array($Owner, $OwnerList))
1428  {
1429  # enable the field and reset its "enable on owner return"
1430  # flag if the "enable on owner return" flag is currently
1431  # set to true. in other words, re-enable the field since
1432  # the owner has returned to the list of existing owners
1433  if ($OwnedField->EnableOnOwnerReturn())
1434  {
1435  $OwnedField->Enabled(TRUE);
1436  $OwnedField->EnableOnOwnerReturn(FALSE);
1437  }
1438  }
1439 
1440  # if the owner of the field is *not* in the list of owners
1441  # that currently exist, i.e., available plugins
1442  else
1443  {
1444  # first, see if the field is currently enabled since it
1445  # will determine whether the field is re-enabled when
1446  # the owner becomes available again
1447  $Enabled = $OwnedField->Enabled();
1448 
1449  # if the field is enabled, set its "enable on owner
1450  # return" flag to true and disable the field. nothing
1451  # needs to be done if the field is already disabled
1452  if ($Enabled)
1453  {
1454  $OwnedField->EnableOnOwnerReturn($Enabled);
1455  $OwnedField->Enabled(FALSE);
1456  }
1457  }
1458  }
1459  }
1460  }
1461  }
1462 
1467  protected function UpdateFieldCompareOrders()
1468  {
1469  $Index = 0;
1470 
1471  foreach ($this->GetDisplayOrder()->GetFields() as $Field)
1472  {
1473  $this->FieldCompareDisplayOrder[$Field->Id()] = $Index++;
1474  }
1475 
1476  $Index = 0;
1477 
1478  foreach ($this->GetEditOrder()->GetFields() as $Field)
1479  {
1480  $this->FieldCompareEditOrder[$Field->Id()] = $Index++;
1481  }
1482  }
1483 
1488  function GetDisplayOrder()
1489  {
1490  # try to fetch an existing display order
1491  $DisplayOrder = MetadataFieldOrder::GetOrderForSchema(
1492  $this,
1493  self::ORDER_DISPLAY_NAME);
1494 
1495  # if the order doesn't exist
1496  if (is_null($DisplayOrder))
1497  {
1498  $OldId = $GLOBALS["SysConfig"]->FieldDisplayFolder();
1499 
1500  # if the older version of MetadataFieldOrder was in use
1501  if ($OldId && $this->Id() == self::SCHEMAID_DEFAULT)
1502  {
1503  # add an entry for the existing folder
1504  $this->DB->Query("
1505  INSERT INTO MetadataFieldOrders
1506  SET SchemaId = '".addslashes($this->Id())."',
1507  OrderId = '".addslashes($OldId)."',
1508  OrderName = '".addslashes(self::ORDER_DISPLAY_NAME)."'");
1509 
1510  # use that folder
1511  $DisplayOrder = new MetadataFieldOrder($OldId);
1512  }
1513 
1514  # otherwise, just create a new order
1515  else
1516  {
1517  $DisplayOrder = MetadataFieldOrder::Create(
1518  $this,
1519  self::ORDER_DISPLAY_NAME,
1520  self::GetOrderForUpgrade($this, self::ORDER_DISPLAY_NAME));
1521  }
1522  }
1523 
1524  return $DisplayOrder;
1525  }
1526 
1531  function GetEditOrder()
1532  {
1533  # try to fetch an existing edit order
1535  $this,
1536  self::ORDER_EDIT_NAME);
1537 
1538  # if the order doesn't exist
1539  if (is_null($EditOrder))
1540  {
1541  $OldId = $GLOBALS["SysConfig"]->FieldEditFolder();
1542 
1543  # if the older version of MetadataFieldOrder was in use
1544  if ($OldId && $this->Id() == self::SCHEMAID_DEFAULT)
1545  {
1546  # add an entry for the existing folder
1547  $this->DB->Query("
1548  INSERT INTO MetadataFieldOrders
1549  SET SchemaId = '".addslashes($this->Id())."',
1550  OrderId = '".addslashes($OldId)."',
1551  OrderName = '".addslashes(self::ORDER_EDIT_NAME)."'");
1552 
1553  # use that folder
1554  $EditOrder = new MetadataFieldOrder($OldId);
1555  }
1556 
1557  # otherwise, just create a new order
1558  else
1559  {
1560  $EditOrder = MetadataFieldOrder::Create(
1561  $this,
1562  self::ORDER_EDIT_NAME,
1563  self::GetOrderForUpgrade($this, self::ORDER_EDIT_NAME));
1564  }
1565  }
1566 
1567  return $EditOrder;
1568  }
1569 
1574  protected function FieldCompareOrdersSet()
1575  {
1576  return $this->FieldCompareDisplayOrder && $this->FieldCompareEditOrder;
1577  }
1578 
1586  protected function CompareFieldOrder($FieldA, $FieldB)
1587  {
1588  if ($this->FieldCompareType == MetadataSchema::MDFORDER_ALPHABETICAL)
1589  {
1590  return ($FieldA->GetDisplayName() < $FieldB->GetDisplayName()) ? -1 : 1;
1591  }
1592 
1593  if ($this->FieldCompareType == MetadataSchema::MDFORDER_EDITING)
1594  {
1596  }
1597 
1598  else
1599  {
1601  }
1602 
1603  $PositionA = GetArrayValue($Order, $FieldA->Id(), 0);
1604  $PositionB = GetArrayValue($Order, $FieldB->Id(), 0);
1605 
1606  return $PositionA < $PositionB ? -1 : 1;
1607  }
1608 
1617  protected static function GetOrderForUpgrade(MetadataSchema $Schema, $Name)
1618  {
1619  # don't do an upgrade for non-default schemas
1620  if ($Schema->Id() !== self::SCHEMAID_DEFAULT)
1621  {
1622  return array();
1623  }
1624 
1625  # get the default display order
1626  if ($Name == self::ORDER_DISPLAY_NAME)
1627  {
1628  # try to get the order from the database and, failing that, use the
1629  # defaults in the class
1630  $Rows = self::GetRowsForUpgrade(self::MDFORDER_DISPLAY);
1631  return count($Rows) ? $Rows: self::$DefaultDisplayOrder;
1632  }
1633 
1634  # get the default edit order
1635  if ($Name == self::ORDER_EDIT_NAME)
1636  {
1637  # try to get the order from the database and, failing that, use the
1638  # defaults in the class
1639  $Rows = self::GetRowsForUpgrade(self::MDFORDER_EDITING);
1640  return count($Rows) ? $Rows: self::$DefaultEditOrder;
1641  }
1642 
1643  # otherwise make no assumptions about the order
1644  return array();
1645  }
1646 
1654  protected static function GetRowsForUpgrade($Type)
1655  {
1656  $Database = new Database();
1657 
1658  # temporarily suppress errors
1659  $Setting = Database::DisplayQueryErrors();
1661 
1662  # see if the old columns exist
1663  $Handle = $Database->Query("
1664  SELECT EditingOrderPosition
1665  FROM MetadataFields
1666  LIMIT 1");
1667 
1668  # the columns do not exist so an upgrade cannot be performed
1669  if ($Handle === FALSE)
1670  {
1671  return array();
1672  }
1673 
1674  # determine which column to use for ordering
1675  $Column = $Type == MetadataSchema::MDFORDER_EDITING
1676  ? "DisplayOrderPosition" : "EditingOrderPosition";
1677 
1678  # query for the fields in their proper order
1679  $Database->Query("
1680  SELECT FieldId
1681  FROM MetadataFields
1682  WHERE FieldId > 0
1683  ORDER BY ".$Column." ASC");
1684 
1685  # restore the earlier error setting
1686  Database::DisplayQueryErrors($Setting);
1687 
1688  # return the resulting field IDs
1689  return $Database->FetchColumn("FieldId");
1690  }
1691 
1696  protected static $DefaultDisplayOrder = array(
1697  0 => 42,
1698  1 => 41,
1699  2 => 43,
1700  3 => 44,
1701  4 => 46,
1702  5 => 45,
1703  6 => 40,
1704  7 => 39,
1705  8 => 34,
1706  9 => 33,
1707  10 => 37,
1708  11 => 36,
1709  12 => 38,
1710  13 => 35,
1711  14 => 47,
1712  15 => 48,
1713  16 => 57,
1714  17 => 56,
1715  18 => 58,
1716  19 => 59,
1717  20 => 61,
1718  21 => 60,
1719  22 => 55,
1720  23 => 54,
1721  24 => 50,
1722  25 => 49,
1723  26 => 51,
1724  27 => 52,
1725  28 => 53,
1726  29 => 32,
1727  30 => 31,
1728  31 => 1,
1729  32 => 2,
1730  33 => 4,
1731  34 => 20,
1732  35 => 21,
1733  36 => 19,
1734  37 => 3,
1735  38 => 27,
1736  39 => 11,
1737  41 => 23,
1738  42 => 26,
1739  43 => 25,
1740  44 => 24,
1741  45 => 9,
1742  46 => 8,
1743  47 => 7,
1744  48 => 6,
1745  49 => 22,
1746  50 => 10,
1747  51 => 28,
1748  52 => 5,
1749  53 => 12,
1750  54 => 62,
1751  55 => 13,
1752  56 => 14,
1753  57 => 16,
1754  58 => 17,
1755  59 => 30,
1756  60 => 29,
1757  61 => 18,
1758  62 => 63,
1759  63 => 64,
1760  64 => 65,
1761  65 => 66);
1762 
1767  protected static $DefaultEditOrder = array(
1768  0 => 42,
1769  1 => 41,
1770  2 => 43,
1771  3 => 44,
1772  4 => 46,
1773  5 => 45,
1774  6 => 40,
1775  7 => 39,
1776  8 => 34,
1777  9 => 33,
1778  10 => 37,
1779  11 => 36,
1780  12 => 38,
1781  13 => 35,
1782  14 => 47,
1783  15 => 48,
1784  16 => 57,
1785  17 => 56,
1786  18 => 58,
1787  19 => 59,
1788  20 => 61,
1789  21 => 60,
1790  22 => 55,
1791  23 => 54,
1792  24 => 50,
1793  25 => 49,
1794  26 => 51,
1795  27 => 52,
1796  28 => 53,
1797  29 => 32,
1798  30 => 31,
1799  31 => 1,
1800  32 => 2,
1801  33 => 4,
1802  34 => 20,
1803  36 => 21,
1804  37 => 19,
1805  38 => 3,
1806  39 => 27,
1807  40 => 11,
1808  41 => 23,
1809  42 => 26,
1810  43 => 25,
1811  44 => 24,
1812  45 => 9,
1813  46 => 8,
1814  47 => 30,
1815  48 => 7,
1816  49 => 6,
1817  50 => 29,
1818  51 => 22,
1819  52 => 10,
1820  53 => 28,
1821  54 => 5,
1822  55 => 12,
1823  56 => 62,
1824  57 => 13,
1825  58 => 18,
1826  59 => 14,
1827  60 => 16,
1828  61 => 17,
1829  62 => 63,
1830  63 => 64,
1831  64 => 65,
1832  65 => 66);
1833 
1834  # ---- PRIVATE INTERFACE -------------------------------------------------
1835 
1836  private $Id;
1837  private $Name;
1838  private $ResourceName;
1839  private $AuthoringPrivileges;
1840  private $EditingPrivileges;
1841  private $ViewingPrivileges;
1842  private $ViewPage;
1843  private $FieldCompareType;
1844  private $CachingOn;
1845  private $NewFields = array();
1846  private $ErrorMsgs = array();
1847  private static $FieldMappings;
1849 
1853  protected $FieldCompareDisplayOrder = array();
1854 
1858  protected $FieldCompareEditOrder = array();
1859 
1867  private function ConvertXmlToPrivilegeSet($Xml)
1868  {
1869  # clear any existing errors
1870  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
1871  { unset($this->ErrorMsgs[__METHOD__]); }
1872 
1873  # create new privilege set
1874  $PrivSet = new PrivilegeSet();
1875 
1876  # for each XML child
1877  foreach ($Xml as $Tag => $Value)
1878  {
1879  # take action based on element name
1880  switch ($Tag)
1881  {
1882  case "PrivilegeSet":
1883  # convert child data to new set
1884  $NewSet = $this->ConvertXmlToPrivilegeSet($Value);
1885 
1886  # add new set to our privilege set
1887  $PrivSet->AddSet($NewSet);
1888  break;
1889 
1890  case "AddCondition":
1891  # start with default values for optional parameters
1892  unset($ConditionField);
1893  $ConditionValue = NULL;
1894  $ConditionOperator = "==";
1895 
1896  # pull out parameters
1897  foreach ($Value as $ParamName => $ParamValue)
1898  {
1899  $ParamValue = trim($ParamValue);
1900  switch ($ParamName)
1901  {
1902  case "Field":
1903  $ConditionField = $this->GetFieldByName(
1904  (string)$ParamValue, TRUE);
1905  if ($ConditionField === NULL)
1906  {
1907  # record error about unknown field
1908  $this->ErrorMsgs[__METHOD__][] =
1909  "Unknown metadata field name found"
1910  ." in AddCondition (".$ParamValue.").";
1911 
1912  # bail out
1913  return NULL;
1914  }
1915  break;
1916 
1917  case "Value":
1918  $ConditionValue = ($ParamValue == "NULL")
1919  ? NULL : (string)$ParamValue;
1920  break;
1921 
1922  case "Operator":
1923  $ConditionOperator = (string)$ParamValue;
1924  break;
1925 
1926  default:
1927  # record error about unknown parameter name
1928  $this->ErrorMsgs[__METHOD__][] =
1929  "Unknown tag found in AddCondition ("
1930  .$ParamName.").";
1931 
1932  # bail out
1933  return NULL;
1934  break;
1935  }
1936  }
1937 
1938  # if no field value
1939  if (!isset($ConditionField))
1940  {
1941  # record error about no field value
1942  $this->ErrorMsgs[__METHOD__][] =
1943  "No metadata field specified in AddCondition.";
1944 
1945  # bail out
1946  return NULL;
1947  }
1948 
1949  # add conditional to privilege set
1950  $PrivSet->AddCondition($ConditionField,
1951  $ConditionValue, $ConditionOperator);
1952  break;
1953 
1954  default:
1955  # strip any excess whitespace off of value
1956  $Value = trim($Value);
1957 
1958  # if child looks like valid method name
1959  if (method_exists("PrivilegeSet", $Tag))
1960  {
1961  # convert constants if needed
1962  if (defined($Value)) { $Value = constant($Value); }
1963 
1964  # convert booleans if needed
1965  if (strtoupper($Value) == "TRUE") { $Value = TRUE; }
1966  elseif (strtoupper($Value) == "FALSE") { $Value = FALSE; }
1967 
1968  # set value using child data
1969  $PrivSet->$Tag((string)$Value);
1970  }
1971  else
1972  {
1973  # record error about bad tag
1974  $this->ErrorMsgs[__METHOD__][] =
1975  "Unknown tag encountered (".$Tag.").";
1976 
1977  # bail out
1978  return NULL;
1979  }
1980  break;
1981  }
1982  }
1983 
1984  # return new privilege set to caller
1985  return $PrivSet;
1986  }
1987 }
const MDFSTAT_ILLEGALLABEL
const ORDER_DISPLAY_NAME
GetHighestItemId($IgnoreSqlCondition=FALSE)
Retrieve highest item ID in use.
static $FieldTypeDBEnums
const RESOURCENAME_DEFAULT
static $FieldTypeDBAllowedEnums
GetFieldIdByName($FieldName, $IgnoreCase=FALSE)
Retrieve metadata field ID by name.
GetHighestFieldId()
Get highest field ID currently in use.
$FieldCompareEditOrder
The cache for metadata field edit ordering.
GetViewPageIdParameter()
Get the resource ID GET parameter for the view page for the schema.
GetAllowedFieldTypes()
Retrieve array of field types that user can create.
static GetOrderForUpgrade(MetadataSchema $Schema, $Name)
Get the metadata field order for the default metadata schema.
ViewingPrivileges(PrivilegeSet $NewValue=NULL)
Get/set privileges that allowing viewing resources with this schema.
Metadata schema (in effect a Factory class for MetadataField).
ErrorMessages($Method=NULL)
Get error messages (if any) from recent calls.
ResourceName($NewValue=NULL)
Get/set name of resources using this schema.
static $FieldTypePHPEnums
Class to build metadata field ordering functionality on top of the foldering functionality.
const MDFORDER_ALPHABETICAL
static Create($SchemaId, $FieldType, $FieldName, $Optional=NULL, $DefaultValue=NULL)
Create a new metadata field.
static NormalizeOwnedFields()
Disable owned fields that have an owner that is unavailable and re-enable fields if an owner has retu...
SQL database abstraction object with smart query caching.
UserCanAuthor($User)
Determine if the given user can author resources using this schema.
EditingPrivileges(PrivilegeSet $NewValue=NULL)
Get/set privileges that allowing editing resources with this schema.
GetFieldByName($FieldName, $IgnoreCase=FALSE)
Retrieve metadata field by name.
GetFieldIdByLabel($FieldLabel, $IgnoreCase=FALSE)
Retrieve metadata field ID by label.
GetFieldsAsOptionList($OptionListName, $FieldTypes=NULL, $SelectedFieldId=NULL, $IncludeNullOption=TRUE, $AddEntries=NULL, $AllowMultiple=FALSE)
Retrieve fields of specified type as HTML option list with field names as labels and field IDs as val...
static SchemaExistsWithId($SchemaId)
Check with schema exists with specified ID.
static FieldToStdNameMapping($FieldId)
Get mapping of field ID to standard field name.
const MDFSTAT_FIELDDOESNOTEXIST
FieldExists($FieldName)
Check whether field with specified name exists.
CompareFieldOrder($FieldA, $FieldB)
Field sorting callback.
GetFieldIdByMappedName($MappedName)
Get field ID by standard field name.
Set of privileges used to access resource information or other parts of the system.
GetFieldNames($FieldTypes=NULL, $OrderType=NULL, $IncludeDisabledFields=FALSE, $IncludeTempFields=FALSE)
Retrieve field names.
static $DefaultEditOrder
The default editing order for metadata fields.
AddFieldFromXml($Xml)
Add new metadata field based on supplied XML.
CacheData($NewValue)
Enable/disable caching of metadata field info.
static SetOwnerListRetrievalFunction($Callback)
Allow external dependencies, i.e., the current list of owners that are available, to be injected...
Name($NewValue=NULL)
Get/set name of schema.
ViewPage($NewValue=NULL)
Get/set name of page to go to for viewing resources using this schema.
const MDFTYPE_CONTROLLEDNAME
GetOwnedFields()
Get fields that have an owner associated with them.
PathMatchesViewPage($Path)
Determine if a path matches the view page path for the schema.
PHP
Definition: OAIClient.php:39
const MDFSTAT_DUPLICATEDBCOLUMN
GetEditOrder()
Get the editing order for the schema.
static $DefaultDisplayOrder
The default display order for metadata fields.
static $OwnerListRetrievalFunction
const MDFSTAT_DUPLICATELABEL
static Create(MetadataSchema $Schema, $Name, array $FieldOrder=array())
Create a new metadata field order, optionally specifying the order of the fields. ...
NewFields()
Get new fields recently added (if any) via XML file.
AddField($FieldName, $FieldType, $Optional=TRUE, $DefaultValue=NULL)
Add new metadata field.
GetFields($FieldTypes=NULL, $OrderType=NULL, $IncludeDisabledFields=FALSE, $IncludeTempFields=FALSE)
Retrieve array of fields.
GetDisplayOrder()
Get the display order for the schema.
FieldCompareOrdersSet()
Determine whether the field comparison ordering caches are set.
static Create($Name, PrivilegeSet $AuthorPrivs=NULL, PrivilegeSet $EditPrivs=NULL, PrivilegeSet $ViewPrivs=NULL, $ViewPage="", $ResourceName=NULL)
Create new metadata schema.
Object representing a locally-defined type of metadata field.
static GetRowsForUpgrade($Type)
Get rows for upgrading purposes.
AuthoringPrivileges(PrivilegeSet $NewValue=NULL)
Get/set privileges that allowing authoring resources with this schema.
__construct($SchemaId=self::SCHEMAID_DEFAULT)
Object constructor, used to load an existing schema.
DropField($FieldId)
Delete metadata field and all associated data.
RemoveQualifierAssociations($QualifierIdOrObject)
Remove all metadata field associations for a given qualifier.
UpdateFieldCompareOrders()
Update the field comparison ordering cache that is used for sorting fields.
static GetOrderForSchema(MetadataSchema $Schema, $Name)
Get a metadata field order with a specific name for a given metadata schema.
const MDFSTAT_ILLEGALNAME
GetField($FieldId)
Retrieve metadata field by ID.
GetFieldByMappedName($MappedName)
Get field by standard field name.
Id()
Get schema ID.
static GetConstantName($Value, $Prefix=NULL)
Get name (string) for constant.
AddFieldsFromXmlFile($FileName, $TestRun=FALSE)
Add new metadata fields from XML file.
Common factory class for item manipulation.
Definition: ItemFactory.php:17
const MDFSTAT_DUPLICATENAME
$FieldCompareDisplayOrder
The cache for metadata field display ordering.
NameIsInUse($Name, $IgnoreCase=FALSE)
Check whether item name is currently in use.
static DisplayQueryErrors($NewValue=NULL)
Get/set whether Query() errors will be displayed.
static StdNameToFieldMapping($MappedName, $FieldId=NULL)
Get/set mapping of standard field name to specific field.
GetFieldTypes()
Retrieve array of field types.
ItemFactory($ItemClassName, $ItemTableName, $ItemIdFieldName, $ItemNameFieldName=NULL, $OrderOpsAllowed=FALSE, $SqlCondition=NULL)
Class constructor.
Definition: ItemFactory.php:36
static GetAllSchemas()
Get all existing metadata schemas.
GetFieldByLabel($FieldLabel, $IgnoreCase=FALSE)
Retrieve metadata field by label.
QualifierIsInUse($QualifierIdOrObject)
Check whether qualifier is in use by any metadata field (in any schema).