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  ."'".$DB->EscapeString($ViewPage)."',"
178  ."'".$DB->EscapeString($AuthorPrivs->Data())."',"
179  ."'".$DB->EscapeString($EditPrivs->Data())."',"
180  ."'".$DB->EscapeString($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  # create display and edit orders
200 
201  # return the new schema
202  return $Schema;
203  }
204 
209  public function Delete()
210  {
211  # delete fields associated with schema
212  $Fields = $this->GetFields(NULL, NULL, TRUE, TRUE);
213  foreach ($Fields as $FieldId => $Field)
214  {
215  $this->DropField($FieldId);
216  }
217 
218  # delete metadata field orders associated with schema
219  foreach (MetadataFieldOrder::GetOrdersForSchema($this) as $Order)
220  {
221  $Order->Delete();
222  }
223 
224  # remove schema info from database
225  $this->DB->Query("DELETE FROM MetadataSchemas WHERE SchemaId = "
226  .intval($this->Id));
227  }
228 
234  static function SchemaExistsWithId($SchemaId)
235  {
236  $DB = new Database();
237  $DB->Query("SELECT * FROM MetadataSchemas"
238  ." WHERE SchemaId = ".intval($SchemaId));
239  return ($DB->NumRowsSelected() > 0) ? TRUE : FALSE;
240  }
241 
247  function Id()
248  {
249  # return value to caller
250  return intval($this->Id);
251  }
252 
258  function Name($NewValue = NULL)
259  {
260  # set new name if one supplied
261  if ($NewValue !== NULL)
262  {
263  $this->DB->Query("UPDATE MetadataSchemas"
264  ." SET Name = '".addslashes($NewValue)."'"
265  ." WHERE SchemaId = '".intval($this->Id)."'");
266  $this->Name = $NewValue;
267  }
268 
269  # get the name if it hasn't been cached yet
270  if (!isset($this->Name))
271  {
272  $this->Name = $this->DB->Query("SELECT * FROM MetadataSchemas"
273  ." WHERE SchemaId = '".intval($this->Id)."'", "Name");
274  }
275 
276  # return current value to caller
277  return $this->Name;
278  }
279 
285  function ResourceName($NewValue = NULL)
286  {
287  # set new resource name if one supplied
288  if ($NewValue !== NULL)
289  {
290  $this->DB->Query("
291  UPDATE MetadataSchemas
292  SET ResourceName = '".addslashes($NewValue)."'
293  WHERE SchemaId = '".intval($this->Id)."'");
294  $this->ResourceName = $NewValue;
295  }
296 
297  # get the name if it hasn't been cached yet
298  if (!isset($this->ResourceName))
299  {
300  $this->ResourceName = $this->DB->Query("
301  SELECT * FROM MetadataSchemas
302  WHERE SchemaId = '".intval($this->Id)."'",
303  "ResourceName");
304 
305  # use the default resource name if one isn't set
306  if (!strlen(trim($this->ResourceName)))
307  {
308  $this->ResourceName = self::RESOURCENAME_DEFAULT;
309  }
310  }
311 
312  # return current value to caller
313  return $this->ResourceName;
314  }
315 
321  function ViewPage($NewValue = NULL)
322  {
323  # set new viewing page if one supplied
324  if ($NewValue !== NULL)
325  {
326  $this->DB->Query("UPDATE MetadataSchemas"
327  ." SET ViewPage = '".addslashes($NewValue)."'"
328  ." WHERE SchemaId = '".intval($this->Id)."'");
329  $this->ViewPage = $NewValue;
330  }
331 
332  # get the view page if it hasn't been cached yet
333  if (!isset($this->ViewPage))
334  {
335  $this->ViewPage = $this->DB->Query("SELECT * FROM MetadataSchemas"
336  ." WHERE SchemaId = '".intval($this->Id)."'", "ViewPage");
337  }
338 
339  # return current value to caller
340  return $this->ViewPage;
341  }
342 
348  function AuthoringPrivileges(PrivilegeSet $NewValue = NULL)
349  {
350  # if new privileges supplied
351  if ($NewValue !== NULL)
352  {
353  # store new privileges in database
354  $this->DB->Query("UPDATE MetadataSchemas"
355  ." SET AuthoringPrivileges = '"
356  .$this->DB->EscapeString($NewValue->Data())."'"
357  ." WHERE SchemaId = ".intval($this->Id));
358  $this->AuthoringPrivileges = $NewValue;
359  }
360 
361  # return current value to caller
362  return $this->AuthoringPrivileges;
363  }
364 
370  function EditingPrivileges(PrivilegeSet $NewValue = NULL)
371  {
372  # if new privileges supplied
373  if ($NewValue !== NULL)
374  {
375  # store new privileges in database
376  $this->DB->Query("UPDATE MetadataSchemas"
377  ." SET EditingPrivileges = '"
378  .$this->DB->EscapeString($NewValue->Data())."'"
379  ." WHERE SchemaId = ".intval($this->Id));
380  $this->EditingPrivileges = $NewValue;
381  }
382 
383  # return current value to caller
384  return $this->EditingPrivileges;
385  }
386 
392  function ViewingPrivileges(PrivilegeSet $NewValue = NULL)
393  {
394  # if new privileges supplied
395  if ($NewValue !== NULL)
396  {
397  # store new privileges in database
398  $this->DB->Query("UPDATE MetadataSchemas"
399  ." SET ViewingPrivileges = '"
400  .$this->DB->EscapeString($NewValue->Data())."'"
401  ." WHERE SchemaId = ".intval($this->Id));
402  $this->ViewingPrivileges = $NewValue;
403  }
404 
405  # return current value to caller
406  return $this->ViewingPrivileges;
407  }
408 
416  function UserCanAuthor($User)
417  {
418  # get authoring privilege set for schema
419  $AuthorPrivs = $this->AuthoringPrivileges();
420 
421  # user can author if privileges are greater than resource set
422  $CanAuthor = $AuthorPrivs->MeetsRequirements($User);
423 
424  # allow plugins to modify result of permission check
425  $SignalResult = $GLOBALS["AF"]->SignalEvent(
426  "EVENT_RESOURCE_AUTHOR_PERMISSION_CHECK", array(
427  "Schema" => $this,
428  "User" => $User,
429  "CanAuthor" => $CanAuthor));
430  $CanAuthor = $SignalResult["CanAuthor"];
431 
432  # report back to caller whether user can author field
433  return $CanAuthor;
434  }
435 
443  function UserCanEdit($User)
444  {
445  # get editing privilege set for schema
446  $EditPrivs = $this->EditingPrivileges();
447 
448  # user can edit if privileges are greater than resource set
449  $CanEdit = $EditPrivs->MeetsRequirements($User);
450 
451  # allow plugins to modify result of permission check
452  $SignalResult = $GLOBALS["AF"]->SignalEvent(
453  "EVENT_RESOURCE_EDIT_PERMISSION_CHECK", array(
454  "Schema" => $this,
455  "User" => $User,
456  "CanEdit" => $CanEdit));
457  $CanEdit = $SignalResult["CanEdit"];
458 
459  # report back to caller whether user can edit field
460  return $CanEdit;
461  }
462 
470  function UserCanView($User)
471  {
472  # get viewing privilege set for schema
473  $ViewPrivs = $this->ViewingPrivileges();
474 
475  # user can view if privileges are greater than resource set
476  $CanView = $ViewPrivs->MeetsRequirements($User);
477 
478  # allow plugins to modify result of permission check
479  $SignalResult = $GLOBALS["AF"]->SignalEvent(
480  "EVENT_RESOURCE_VIEW_PERMISSION_CHECK", array(
481  "Schema" => $this,
482  "User" => $User,
483  "CanView" => $CanView));
484  $CanView = $SignalResult["CanView"];
485 
486  # report back to caller whether user can view field
487  return $CanView;
488  }
489 
496  {
497  # get the query/GET parameters for the view page
498  $Query = parse_url($this->ViewPage(), PHP_URL_QUERY);
499 
500  # the URL couldn't be parsed
501  if (!is_string($Query))
502  {
503  return NULL;
504  }
505 
506  # parse the GET parameters out of the query string
507  $GetVars = ParseQueryString($Query);
508 
509  # search for the ID parameter
510  $Result = array_search("\$ID", $GetVars);
511 
512  return $Result !== FALSE ? $Result : NULL;
513  }
514 
527  function PathMatchesViewPage($Path)
528  {
529  # get the query/GET parameters for the view page
530  $Query = parse_url($this->ViewPage(), PHP_URL_QUERY);
531 
532  # can't perform matching if the URL couldn't be parsed
533  if (!is_string($Query))
534  {
535  return FALSE;
536  }
537 
538  # parse the GET parameters out of the query string
539  $GetVars = ParseQueryString($Query);
540 
541  # now, get the query/GET parameters from the path given
542  $PathQuery = parse_url($Path, PHP_URL_QUERY);
543 
544  # can't perform matching if the URL couldn't be parsed
545  if (!is_string($PathQuery))
546  {
547  return FALSE;
548  }
549 
550  # parse the GET parameters out of the path's query string
551  $PathGetVars = ParseQueryString($PathQuery);
552 
553  # make sure the given path GET parameters contain at least the GET
554  # parameters from the view page and that all non-variable parameters are
555  # equal. the path GET parameters may contain more, which is okay
556  foreach ($GetVars as $GetVarName => $GetVarValue)
557  {
558  # there's a required parameter that is not included in the path GET
559  # parameters
560  if (!array_key_exists($GetVarName, $PathGetVars))
561  {
562  return FALSE;
563  }
564 
565  # require the path's value to be equal to the view page's value if
566  # the view page's value is not a variable,
567  if ($PathGetVars[$GetVarName] != $GetVarValue
568  && (!strlen($GetVarValue) || $GetVarValue{0} != "$"))
569  {
570  return FALSE;
571  }
572  }
573 
574  # the path matches the view page path
575  return TRUE;
576  }
577 
582  function CacheData($NewValue)
583  {
584  $this->CachingOn = $NewValue;
585  }
586 
596  function AddField($FieldName, $FieldType, $Optional = TRUE, $DefaultValue = NULL)
597  {
598  # clear any existing error messages
599  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
600  { unset($this->ErrorMsgs[__METHOD__]); }
601 
602  # create new field
603  try
604  {
605  $Field = MetadataField::Create($this->Id(), $FieldType,
606  $FieldName, $Optional, $DefaultValue);
607  }
608  catch (Exception $Exception)
609  {
610  $this->ErrorMsgs[__METHOD__][] = $Exception->getMessage();
611  $Field = NULL;
612  }
613 
614  # return new field to caller
615  return $Field;
616  }
617 
630  function AddFieldsFromXmlFile($FileName, $TestRun = FALSE)
631  {
632  # clear loading status
633  $this->NewFields = array();
634  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
635  { unset($this->ErrorMsgs[__METHOD__]); }
636 
637  # check that file exists and is readable
638  if (!file_exists($FileName))
639  {
640  $this->ErrorMsgs[__METHOD__][] = "Could not find XML file '"
641  .$FileName."'.";
642  return FALSE;
643  }
644  elseif (!is_readable($FileName))
645  {
646  $this->ErrorMsgs[__METHOD__][] = "Could not read from XML file '"
647  .$FileName."'.";
648  return FALSE;
649  }
650 
651  # load XML from file
652  libxml_use_internal_errors(TRUE);
653  $XmlData = simplexml_load_file($FileName);
654  $Errors = libxml_get_errors();
655  libxml_use_internal_errors(FALSE);
656 
657  # if XML load failed
658  if ($XmlData === FALSE)
659  {
660  # retrieve XML error messages
661  foreach ($Errors as $Err)
662  {
663  $ErrType = ($Err->level == LIBXML_ERR_WARNING) ? "Warning"
664  : (($Err->level == LIBXML_ERR_WARNING) ? "Error"
665  : "Fatal Error");
666  $this->ErrorMsgs[__METHOD__][] = "XML ".$ErrType.": ".$Err->message
667  ." (".$Err->file.":".$Err->line.",".$Err->column.")";
668  }
669  }
670  # else if no metadata fields found record error message
671  elseif (!count($XmlData->MetadataField))
672  {
673  $this->ErrorMsgs[__METHOD__][] = "No metadata fields found.";
674  }
675  # else process metadata fields
676  else
677  {
678  # for each metadata field entry found
679  $FieldsAdded = 0;
680  $FieldIndex = 0;
681  foreach ($XmlData->MetadataField as $FieldXml)
682  {
683  $FieldIndex++;
684 
685  # pull out field type if present
686  if (isset($FieldXml->Type))
687  {
688  $FieldType = "MetadataSchema::".$FieldXml->Type;
689  if (!defined($FieldType))
690  {
691  $FieldType = "MetadataSchema::MDFTYPE_"
692  .strtoupper(preg_replace("/\\s+/", "",
693  $FieldXml->Type));
694  }
695  }
696 
697  # if required values are missing
698  if (!isset($FieldXml->Name) || !isset($FieldXml->Type)
699  || !defined($FieldType))
700  {
701  # add error message about required value missing
702  if (!isset($FieldXml->Name))
703  {
704  $this->ErrorMsgs[__METHOD__][] =
705  "Field name not found (MetadataField #"
706  .$FieldIndex.").";
707  }
708  else
709  {
710  $this->ErrorMsgs[__METHOD__][] =
711  "Valid type not found for field '"
712  .$FieldXml->Name."' (MetadataField #"
713  .$FieldIndex.").";
714  }
715  }
716  # else if there is not already a field with this name
717  elseif (!$this->NameIsInUse(trim($FieldXml->Name)))
718  {
719  # create new field
720  $Field = $this->AddField($FieldXml->Name, constant($FieldType));
721 
722  # if field creation failed
723  if ($Field === NULL)
724  {
725  # add any error message to our error list
726  $ErrorMsgs = $this->ErrorMessages("AddField");
727  foreach ($ErrorMsgs as $Msg)
728  {
729  $this->ErrorMsgs[__METHOD__][] =
730  $Msg." (AddField)";
731  }
732  }
733  else
734  {
735  # add field to list of created fields
736  $this->NewFields[$Field->Id()] = $Field;
737 
738  # for other field attributes
739  foreach ($FieldXml as $MethodName => $Value)
740  {
741  # if tags look valid and have not already been set
742  if (method_exists($Field, $MethodName)
743  && ($MethodName != "Name")
744  && ($MethodName != "Type"))
745  {
746  # if tag indicates privilege set
747  if (preg_match("/^[a-z]+Privileges\$/i",
748  $MethodName))
749  {
750  # save element for later processing
751  $PrivilegesToSet[$Field->Id()][$MethodName] = $Value;
752  }
753  else
754  {
755  # condense down any extraneous whitespace
756  $Value = preg_replace("/\s+/", " ", trim($Value));
757 
758  # set value for field
759  $Field->$MethodName($Value);
760  }
761  }
762  }
763 
764  # save the temp ID so that any privileges to set can be
765  # mapped to the actual ID when the field is made
766  # permanent
767  $TempId = $Field->Id();
768 
769  # make new field permanent
770  $Field->IsTempItem(FALSE);
771 
772  # map privileges to set to the permanent field ID
773  if (isset($PrivilegesToSet) &&
774  isset($PrivilegesToSet[$TempId]) )
775  {
776  # copy the privileges over
777  $PrivilegesToSet[$Field->Id()] =
778  $PrivilegesToSet[$TempId];
779 
780  # remove the values for the temp ID
781  unset($PrivilegesToSet[$TempId]);
782  }
783  }
784  }
785  }
786 
787  # if we have privileges to set
788  if (isset($PrivilegesToSet))
789  {
790  # for each field with privileges
791  foreach ($PrivilegesToSet as $FieldId => $Privileges)
792  {
793  # load the field for which to set the privileges
794  $Field = new MetadataField($FieldId);
795 
796  # for each set of privileges for field
797  foreach ($Privileges as $MethodName => $Value)
798  {
799  # convert privilege value
800  $Value = $this->ConvertXmlToPrivilegeSet($Value);
801 
802  # if conversion failed
803  if ($Value === NULL)
804  {
805  # add resulting error messages to our list
806  $ErrorMsgs = $this->ErrorMessages(
807  "ConvertXmlToPrivilegeSet");
808  foreach ($ErrorMsgs as $Msg)
809  {
810  $this->ErrorMsgs[__METHOD__][] =
811  $Msg." (ConvertXmlToPrivilegeSet)";
812  }
813  }
814  else
815  {
816  # set value for field
817  $Field->$MethodName($Value);
818  }
819  }
820  }
821  }
822 
823  # if errors were found during creation
824  if (array_key_exists(__METHOD__, $this->ErrorMsgs) || $TestRun)
825  {
826  # remove any fields that were created
827  foreach ($this->NewFields as $Field)
828  {
829  $Field->Drop();
830  }
831  $this->NewFields = array();
832  }
833  }
834 
835  # report success or failure based on whether errors were recorded
836  return (array_key_exists(__METHOD__, $this->ErrorMsgs)) ? FALSE : TRUE;
837  }
838 
844  function NewFields()
845  {
846  return $this->NewFields;
847  }
848 
858  function ErrorMessages($Method = NULL)
859  {
860  if ($Method === NULL)
861  {
862  return $this->ErrorMsgs;
863  }
864  else
865  {
866  if (!method_exists($this, $Method))
867  {
868  throw new Exception("Error messages requested for non-existent"
869  ." method (".$Method.").");
870  }
871  return array_key_exists(__CLASS__."::".$Method, $this->ErrorMsgs)
872  ? $this->ErrorMsgs[__CLASS__."::".$Method] : array();
873  }
874  }
875 
885  function AddFieldFromXml($Xml)
886  {
887  # assume field addition will fail
888  $Field = self::MDFSTAT_ERROR;
889 
890  # add XML prefixes if needed
891  $Xml = trim($Xml);
892  if (!preg_match("/^<\?xml/i", $Xml))
893  {
894  if (!preg_match("/^<document>/i", $Xml))
895  {
896  $Xml = "<document>".$Xml."</document>";
897  }
898  $Xml = "<?xml version='1.0'?".">".$Xml;
899  }
900 
901  # parse XML
902  $XmlData = simplexml_load_string($Xml);
903 
904  # if required values are present
905  if (is_object($XmlData)
906  && isset($XmlData->Name)
907  && isset($XmlData->Type)
908  && constant("MetadataSchema::".$XmlData->Type))
909  {
910  # create the metadata field
911  $Field = $this->AddField(
912  $XmlData->Name,
913  constant("MetadataSchema::".$XmlData->Type));
914 
915  # if field creation succeeded
916  if ($Field != NULL)
917  {
918  # for other field attributes
919  foreach ($XmlData as $MethodName => $Value)
920  {
921  # if they look valid and have not already been set
922  if (method_exists($Field, $MethodName)
923  && ($MethodName != "Name")
924  && ($MethodName != "Type"))
925  {
926  # if tag indicates privilege set
927  if (preg_match("/^[a-z]+Privileges\$/i",
928  $MethodName))
929  {
930  # save element for later processing
931  $PrivilegesToSet[$MethodName] = $Value;
932  }
933  else
934  {
935  # condense down any extraneous whitespace
936  $Value = preg_replace("/\s+/", " ", trim($Value));
937 
938  # set value for field
939  $Field->$MethodName($Value);
940  }
941  }
942  }
943 
944  # make new field permanent
945  $Field->IsTempItem(FALSE);
946 
947  # if we have privileges to set
948  if (isset($PrivilegesToSet))
949  {
950  # for each set of privileges for field
951  foreach ($PrivilegesToSet as $MethodName => $Value)
952  {
953  # convert privilege value
954  $Value = $this->ConvertXmlToPrivilegeSet($Value);
955 
956  # if conversion failed
957  if ($Value === NULL)
958  {
959  # add resulting error messages to our list
960  $ErrorMsgs = $this->ErrorMessages(
961  "ConvertXmlToPrivilegeSet");
962  foreach ($ErrorMsgs as $Msg)
963  {
964  $this->ErrorMsgs[__METHOD__][] =
965  $Msg." (ConvertXmlToPrivilegeSet)";
966  }
967  }
968  else
969  {
970  # set value for field
971  $Field->$MethodName($Value);
972  }
973  }
974  }
975  }
976  }
977 
978  # return new field (if any) to caller
979  return $Field;
980  }
981 
987  function DropField($FieldId)
988  {
989  $Field = $this->GetField($FieldId);
990  if ($Field !== NULL)
991  {
992  global $AF;
993  $AF->SignalEvent("EVENT_PRE_FIELD_DELETE",
994  array("FieldId" => $FieldId) );
995 
996  $Field->Drop();
997  return TRUE;
998  }
999  else
1000  {
1001  return FALSE;
1002  }
1003  }
1004 
1010  function GetField($FieldId)
1011  {
1012  static $Fields;
1013 
1014  # if caching is off or field is not already loaded
1015  if (($this->CachingOn != TRUE) || !isset($Fields[$FieldId]))
1016  {
1017  # retrieve field
1018  try
1019  {
1020  $Fields[$FieldId] = new MetadataField($FieldId);
1021  }
1022  catch (Exception $Exception)
1023  {
1024  $Fields[$FieldId] = NULL;
1025  }
1026  }
1027 
1028  # return field to caller
1029  return $Fields[$FieldId];
1030  }
1031 
1038  function GetFieldByName($FieldName, $IgnoreCase = FALSE)
1039  {
1040  $FieldId = $this->GetFieldIdByName($FieldName, $IgnoreCase);
1041  return ($FieldId === NULL) ? NULL : $this->GetField($FieldId);
1042  }
1043 
1050  function GetFieldByLabel($FieldLabel, $IgnoreCase = FALSE)
1051  {
1052  $FieldId = $this->GetFieldIdByLabel($FieldLabel, $IgnoreCase);
1053  return ($FieldId === NULL) ? NULL : $this->GetField($FieldId);
1054  }
1055 
1063  function GetFieldIdByName($FieldName, $IgnoreCase = FALSE)
1064  {
1065  static $FieldIdsByName;
1066 
1067  # if caching is off or field ID is already loaded
1068  if (($this->CachingOn != TRUE) || !isset($FieldIdsByName[$this->Id][$FieldName]))
1069  {
1070  # retrieve field ID from DB
1071  $Condition = $IgnoreCase
1072  ? "WHERE LOWER(FieldName) = '".addslashes(strtolower($FieldName))."'"
1073  : "WHERE FieldName = '".addslashes($FieldName)."'";
1074  $Condition .= " AND SchemaId = ".intval($this->Id);
1075  $FieldIdsByName[$this->Id][$FieldName] = $this->DB->Query(
1076  "SELECT FieldId FROM MetadataFields ".$Condition, "FieldId");
1077  }
1078 
1079  return $FieldIdsByName[$this->Id][$FieldName];
1080  }
1081 
1089  function GetFieldIdByLabel($FieldLabel, $IgnoreCase = FALSE)
1090  {
1091  static $FieldIdsByLabel;
1092 
1093  # if caching is off or field ID is already loaded
1094  if (($this->CachingOn != TRUE) || !isset($FieldIdsByLabel[$FieldLabel]))
1095  {
1096  # retrieve field ID from DB
1097  $Condition = $IgnoreCase
1098  ? "WHERE LOWER(Label) = '".addslashes(strtolower($FieldLabel))."'"
1099  : "WHERE Label = '".addslashes($FieldLabel)."'";
1100  $Condition .= " AND SchemaId = ".intval($this->Id);
1101  $FieldIdsByLabel[$FieldLabel] = $this->DB->Query(
1102  "SELECT FieldId FROM MetadataFields ".$Condition, "FieldId");
1103  }
1104 
1105  return $FieldIdsByLabel[$FieldLabel];
1106  }
1107 
1113  function FieldExists($FieldName)
1114  {
1115  return $this->NameIsInUse($FieldName);
1116  }
1117 
1131  function GetFields($FieldTypes = NULL, $OrderType = NULL,
1132  $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1133  {
1134  # create empty array to pass back
1135  $Fields = array();
1136 
1137  # for each field type in database
1138  $this->DB->Query("SELECT FieldId, FieldType FROM MetadataFields"
1139  ." WHERE SchemaId = ".intval($this->Id)
1140  .(!$IncludeDisabledFields ? " AND Enabled != 0" : "")
1141  .(!$IncludeTempFields ? " AND FieldId >= 0" : ""));
1142  while ($Record = $this->DB->FetchRow())
1143  {
1144  # if field type is known
1145  if (array_key_exists($Record["FieldType"], MetadataField::$FieldTypePHPEnums))
1146  {
1147  # if no specific type requested or if field is of requested type
1148  if (($FieldTypes == NULL)
1149  || (MetadataField::$FieldTypePHPEnums[$Record["FieldType"]]
1150  & $FieldTypes))
1151  {
1152  # create field object and add to array to be passed back
1153  $Fields[$Record["FieldId"]] = $this->GetField($Record["FieldId"]);
1154  }
1155  }
1156  }
1157 
1158  # if field sorting requested
1159  if ($OrderType !== NULL)
1160  {
1161  # update field comparison ordering if not set yet
1162  if (!$this->FieldCompareOrdersSet())
1163  {
1164  $this->UpdateFieldCompareOrders();
1165  }
1166 
1167  $this->FieldCompareType = $OrderType;
1168 
1169  # sort field array by requested order type
1170  uasort($Fields, array($this, "CompareFieldOrder"));
1171  }
1172 
1173  # return array of field objects to caller
1174  return $Fields;
1175  }
1176 
1191  function GetFieldNames($FieldTypes = NULL, $OrderType = NULL,
1192  $IncludeDisabledFields = FALSE, $IncludeTempFields = FALSE)
1193  {
1194  $Fields = $this->GetFields($FieldTypes, $OrderType,
1195  $IncludeDisabledFields, $IncludeTempFields);
1196 
1197  $FieldNames = array();
1198  foreach($Fields as $Field)
1199  {
1200  $FieldNames[$Field->Id()] = $Field->Name();
1201  }
1202 
1203  return $FieldNames;
1204  }
1205 
1223  function GetFieldsAsOptionList($OptionListName, $FieldTypes = NULL,
1224  $SelectedFieldId = NULL, $IncludeNullOption = TRUE,
1225  $AddEntries = NULL, $AllowMultiple = FALSE)
1226  {
1227  # retrieve requested fields
1228  $FieldNames = $this->GetFieldNames($FieldTypes);
1229 
1230  # transform field names to labels
1231  foreach ($FieldNames as $FieldId => $FieldName)
1232  {
1233  $FieldNames[$FieldId] = $this->GetField($FieldId)->GetDisplayName();
1234  }
1235 
1236  # begin HTML option list
1237  $Html = "<select id=\"".$OptionListName."\" name=\"".$OptionListName."\"";
1238 
1239  # if multiple selections should be allowed
1240  if ($AllowMultiple)
1241  {
1242  $Html .= " multiple=\"multiple\"";
1243  }
1244 
1245  $Html .= ">\n";
1246 
1247  if ($IncludeNullOption)
1248  {
1249  $Html .= "<option value=\"\">--</option>\n";
1250  }
1251 
1252  # make checking for IDs simpler
1253  if (!is_array($SelectedFieldId))
1254  {
1255  $SelectedFieldId = array($SelectedFieldId);
1256  }
1257 
1258  # for each metadata field
1259  foreach ($FieldNames as $Id => $Name)
1260  {
1261  # add entry for field to option list
1262  $Html .= "<option value=\"".$Id."\"";
1263  if (in_array($Id, $SelectedFieldId)) { $Html .= " selected"; }
1264  $Html .= ">".htmlspecialchars($Name)."</option>\n";
1265  }
1266 
1267  # if additional entries were requested
1268  if ($AddEntries)
1269  {
1270  foreach ($AddEntries as $Value => $Label)
1271  {
1272  $Html .= "<option value=\"".$Value."\"";
1273  if (in_array($Value, $SelectedFieldId))
1274  {
1275  $Html .= " selected";
1276  }
1277  $Html .= ">".htmlspecialchars($Label)."</option>\n";
1278  }
1279  }
1280 
1281  # end HTML option list
1282  $Html .= "</select>\n";
1283 
1284  # return constructed HTML to caller
1285  return $Html;
1286  }
1287 
1293  function GetFieldTypes()
1294  {
1296  }
1297 
1304  {
1306  }
1307 
1312  function RemoveQualifierAssociations($QualifierIdOrObject)
1313  {
1314  # sanitize qualifier ID or grab it from object
1315  $QualifierIdOrObject = is_object($QualifierIdOrObject)
1316  ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1317 
1318  # delete intersection records from database
1319  $this->DB->Query("DELETE FROM FieldQualifierInts"
1320  ." WHERE QualifierId = ".$QualifierIdOrObject);
1321  }
1322 
1328  function QualifierIsInUse($QualifierIdOrObject)
1329  {
1330  # sanitize qualifier ID or grab it from object
1331  $QualifierIdOrObject = is_object($QualifierIdOrObject)
1332  ? $QualifierIdOrObject->Id() : intval($QualifierIdOrObject);
1333 
1334  # determine whether any fields use qualifier as default
1335  $DefaultCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
1336  ." FROM MetadataFields"
1337  ." WHERE DefaultQualifier = ".$QualifierIdOrObject,
1338  "RecordCount");
1339 
1340  # determine whether any fields are associated with qualifier
1341  $AssociationCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount"
1342  ." FROM FieldQualifierInts"
1343  ." WHERE QualifierId = ".$QualifierIdOrObject,
1344  "RecordCount");
1345 
1346  # report whether qualifier is in use based on defaults and associations
1347  return (($DefaultCount + $AssociationCount) > 0) ? TRUE : FALSE;
1348  }
1349 
1355  {
1356  return $this->GetHighestItemId();
1357  }
1358 
1366  static function StdNameToFieldMapping($MappedName, $FieldId = NULL)
1367  {
1368  if ($FieldId !== NULL)
1369  {
1370  self::$FieldMappings[$MappedName] = $FieldId;
1371  }
1372  return isset(self::$FieldMappings[$MappedName])
1373  ? self::$FieldMappings[$MappedName] : NULL;
1374  }
1375 
1382  static function FieldToStdNameMapping($FieldId)
1383  {
1384  if ($FieldId != -1)
1385  {
1386  foreach (self::$FieldMappings as $MappedName => $MappedFieldId)
1387  {
1388  if ($MappedFieldId == $FieldId)
1389  {
1390  return $MappedName;
1391  }
1392  }
1393  }
1394  return NULL;
1395  }
1396 
1404  function GetFieldByMappedName($MappedName)
1405  {
1406  return (self::StdNameToFieldMapping($MappedName) == NULL) ? NULL
1407  : $this->GetField($this->StdNameToFieldMapping($MappedName));
1408  }
1409 
1417  function GetFieldIdByMappedName($MappedName)
1418  {
1419  return self::StdNameToFieldMapping($MappedName);
1420  }
1421 
1426  function GetOwnedFields()
1427  {
1428  $Fields = array();
1429 
1430  $this->DB->Query("SELECT * FROM MetadataFields"
1431  ." WHERE Owner IS NOT NULL AND LENGTH(Owner) > 0"
1432  ." AND SchemaId = ".intval($this->Id));
1433 
1434  while (FALSE !== ($Row = $this->DB->FetchRow()))
1435  {
1436  $FieldId = $Row["FieldId"];
1437  $Fields[$FieldId] = $this->GetField($FieldId);
1438  }
1439 
1440  return $Fields;
1441  }
1442 
1458  static function GetCanonicalFieldIdentifier($Field)
1459  {
1460  # if field object was passed in
1461  if ($Field instanceof MetadataField)
1462  {
1463  # return identifier from field to caller
1464  return $Field->Id();
1465  }
1466  # else if field ID was passed in
1467  elseif (is_numeric($Field))
1468  {
1469  # return supplied field ID to caller
1470  return (int)$Field;
1471  }
1472  # else if field name was passed in
1473  elseif (is_string($Field))
1474  {
1475  # retrieve field names if not already loaded
1476  static $FieldNames;
1477  static $FieldSchemaIds;
1478  if (!isset($FieldNames))
1479  {
1480  $DB = new Database();
1481  $DB->Query("SELECT FieldId, FieldName, SchemaId"
1482  ." FROM MetadataFields");
1483  while ($Row = $DB->FetchRow())
1484  {
1485  $FieldNames[$Row["FieldId"]] = $Row["FieldName"];
1486  $FieldSchemaIds[$Row["FieldId"]] = $Row["SchemaId"];
1487  }
1488  }
1489 
1490  # look for field with specified name
1491  $Ids = array_keys($FieldNames, $Field);
1492 
1493  # if one matching field was found
1494  $FieldsFound = count($Ids);
1495  if ($FieldsFound == 1)
1496  {
1497  # return ID for matching field
1498  return (int)$Ids[0];
1499  }
1500  # else if multiple matching fields were found
1501  elseif ($FieldsFound > 1)
1502  {
1503  # return ID of field with the lowest schema ID
1504  $LowestSchemaId = PHP_INT_MAX;
1505  foreach ($Ids as $Id)
1506  {
1507  if ($FieldSchemaIds[$Id] < $LowestSchemaId)
1508  {
1509  $FieldId = $Id;
1510  $LowestSchemaId = $FieldSchemaIds[$Id];
1511  }
1512  }
1513  return $FieldId;
1514  }
1515  # else error out because no matching field found
1516  else
1517  {
1518  throw new Exception("No metadata field found with the"
1519  ." name \"".$Field."\".");
1520  }
1521  }
1522  # else error out because we were given an illegal field argument
1523  else
1524  {
1525  throw new InvalidArgumentException(
1526  "Illegal field argument supplied.");
1527  }
1528  }
1529 
1544  static function GetPrintableFieldName($Field)
1545  {
1546  # retrieve field ID
1547  $Id = self::GetCanonicalFieldIdentifier($Field);
1548 
1549  # retrieve field labels and names if not already loaded
1550  static $FieldLabels;
1551  static $FieldNames;
1552  if (!isset($FieldNames))
1553  {
1554  $DB = new Database();
1555  $DB->Query("SELECT FieldId, FieldName, Label FROM MetadataFields");
1556  while ($Row = $DB->FetchRow())
1557  {
1558  $FieldNames[$Row["FieldId"]] = $Row["FieldName"];
1559  $FieldLabels[$Row["FieldId"]] = $Row["Label"];
1560  }
1561  }
1562 
1563  # return field label if available otherwise return field name
1564  return isset($FieldLabels[$Id]) ? $FieldLabels[$Id] : $FieldNames[$Id];
1565  }
1566 
1572  static function GetAllSchemas()
1573  {
1574  $Database = new Database();
1575  $Schemas = array();
1576 
1577  # fetch the IDs all of the metadata schemas
1578  $Database->Query("SELECT * FROM MetadataSchemas");
1579  $SchemaIds = $Database->FetchColumn("SchemaId");
1580 
1581  # construct objects from the IDs
1582  foreach ($SchemaIds as $SchemaId)
1583  {
1584  $Schemas[$SchemaId] = new MetadataSchema($SchemaId);
1585  }
1586 
1587  return $Schemas;
1588  }
1589 
1595  static function SetOwnerListRetrievalFunction($Callback)
1596  {
1597  if (is_callable($Callback))
1598  {
1599  self::$OwnerListRetrievalFunction = $Callback;
1600  }
1601  }
1602 
1608  static function NormalizeOwnedFields()
1609  {
1610  # if an owner list retrieval function and default schema exists
1611  if (self::$OwnerListRetrievalFunction
1612  && self::SchemaExistsWithId(self::SCHEMAID_DEFAULT))
1613  {
1614  # retrieve the list of owners that currently exist
1615  $OwnerList = call_user_func(self::$OwnerListRetrievalFunction);
1616 
1617  # an array is expected
1618  if (is_array($OwnerList))
1619  {
1620  $Schema = new MetadataSchema(self::SCHEMAID_DEFAULT);
1621 
1622  # get each metadata field that is owned by a plugin
1623  $OwnedFields = $Schema->GetOwnedFields();
1624 
1625  # loop through each owned field
1626  foreach ($OwnedFields as $OwnedField)
1627  {
1628  # the owner of the current field
1629  $Owner = $OwnedField->Owner();
1630 
1631  # if the owner of the field is in the list of owners that
1632  # currently exist, i.e., available plugins
1633  if (in_array($Owner, $OwnerList))
1634  {
1635  # enable the field and reset its "enable on owner return"
1636  # flag if the "enable on owner return" flag is currently
1637  # set to true. in other words, re-enable the field since
1638  # the owner has returned to the list of existing owners
1639  if ($OwnedField->EnableOnOwnerReturn())
1640  {
1641  $OwnedField->Enabled(TRUE);
1642  $OwnedField->EnableOnOwnerReturn(FALSE);
1643  }
1644  }
1645 
1646  # if the owner of the field is *not* in the list of owners
1647  # that currently exist, i.e., available plugins
1648  else
1649  {
1650  # first, see if the field is currently enabled since it
1651  # will determine whether the field is re-enabled when
1652  # the owner becomes available again
1653  $Enabled = $OwnedField->Enabled();
1654 
1655  # if the field is enabled, set its "enable on owner
1656  # return" flag to true and disable the field. nothing
1657  # needs to be done if the field is already disabled
1658  if ($Enabled)
1659  {
1660  $OwnedField->EnableOnOwnerReturn($Enabled);
1661  $OwnedField->Enabled(FALSE);
1662  }
1663  }
1664  }
1665  }
1666  }
1667  }
1668 
1673  protected function UpdateFieldCompareOrders()
1674  {
1675  $Index = 0;
1676 
1677  foreach ($this->GetDisplayOrder()->GetFields() as $Field)
1678  {
1679  $this->FieldCompareDisplayOrder[$Field->Id()] = $Index++;
1680  }
1681 
1682  $Index = 0;
1683 
1684  foreach ($this->GetEditOrder()->GetFields() as $Field)
1685  {
1686  $this->FieldCompareEditOrder[$Field->Id()] = $Index++;
1687  }
1688  }
1689 
1694  function GetDisplayOrder()
1695  {
1696  return MetadataFieldOrder::GetOrderForSchema($this, self::ORDER_DISPLAY_NAME);
1697  }
1698 
1703  function GetEditOrder()
1704  {
1705  return MetadataFieldOrder::GetOrderForSchema($this, self::ORDER_EDIT_NAME);
1706  }
1707 
1712  protected function FieldCompareOrdersSet()
1713  {
1714  return $this->FieldCompareDisplayOrder && $this->FieldCompareEditOrder;
1715  }
1716 
1724  protected function CompareFieldOrder($FieldA, $FieldB)
1725  {
1726  if ($this->FieldCompareType == MetadataSchema::MDFORDER_ALPHABETICAL)
1727  {
1728  return ($FieldA->GetDisplayName() < $FieldB->GetDisplayName()) ? -1 : 1;
1729  }
1730 
1731  if ($this->FieldCompareType == MetadataSchema::MDFORDER_EDITING)
1732  {
1734  }
1735 
1736  else
1737  {
1739  }
1740 
1741  $PositionA = GetArrayValue($Order, $FieldA->Id(), 0);
1742  $PositionB = GetArrayValue($Order, $FieldB->Id(), 0);
1743 
1744  return $PositionA < $PositionB ? -1 : 1;
1745  }
1746 
1747 
1748  # ---- PRIVATE INTERFACE -------------------------------------------------
1749 
1750  private $Id;
1751  private $Name;
1752  private $ResourceName;
1753  private $AuthoringPrivileges;
1754  private $EditingPrivileges;
1755  private $ViewingPrivileges;
1756  private $ViewPage;
1757  private $FieldCompareType;
1758  private $CachingOn;
1759  private $NewFields = array();
1760  private $ErrorMsgs = array();
1761  private static $FieldMappings;
1763 
1767  protected $FieldCompareDisplayOrder = array();
1768 
1772  protected $FieldCompareEditOrder = array();
1773 
1781  private function ConvertXmlToPrivilegeSet($Xml)
1782  {
1783  # clear any existing errors
1784  if (array_key_exists(__METHOD__, $this->ErrorMsgs))
1785  { unset($this->ErrorMsgs[__METHOD__]); }
1786 
1787  # create new privilege set
1788  $PrivSet = new PrivilegeSet();
1789 
1790  # for each XML child
1791  foreach ($Xml as $Tag => $Value)
1792  {
1793  # take action based on element name
1794  switch ($Tag)
1795  {
1796  case "PrivilegeSet":
1797  # convert child data to new set
1798  $NewSet = $this->ConvertXmlToPrivilegeSet($Value);
1799 
1800  # add new set to our privilege set
1801  $PrivSet->AddSet($NewSet);
1802  break;
1803 
1804  case "AddCondition":
1805  # start with default values for optional parameters
1806  unset($ConditionField);
1807  $ConditionValue = NULL;
1808  $ConditionOperator = "==";
1809 
1810  # pull out parameters
1811  foreach ($Value as $ParamName => $ParamValue)
1812  {
1813  $ParamValue = trim($ParamValue);
1814  switch ($ParamName)
1815  {
1816  case "Field":
1817  $ConditionField = $this->GetFieldByName(
1818  (string)$ParamValue, TRUE);
1819  if ($ConditionField === NULL)
1820  {
1821  # record error about unknown field
1822  $this->ErrorMsgs[__METHOD__][] =
1823  "Unknown metadata field name found"
1824  ." in AddCondition (".$ParamValue.").";
1825 
1826  # bail out
1827  return NULL;
1828  }
1829  break;
1830 
1831  case "Value":
1832  $ConditionValue = ($ParamValue == "NULL")
1833  ? NULL : (string)$ParamValue;
1834  break;
1835 
1836  case "Operator":
1837  $ConditionOperator = (string)$ParamValue;
1838  break;
1839 
1840  default:
1841  # record error about unknown parameter name
1842  $this->ErrorMsgs[__METHOD__][] =
1843  "Unknown tag found in AddCondition ("
1844  .$ParamName.").";
1845 
1846  # bail out
1847  return NULL;
1848  break;
1849  }
1850  }
1851 
1852  # if no field value
1853  if (!isset($ConditionField))
1854  {
1855  # record error about no field value
1856  $this->ErrorMsgs[__METHOD__][] =
1857  "No metadata field specified in AddCondition.";
1858 
1859  # bail out
1860  return NULL;
1861  }
1862 
1863  # add conditional to privilege set
1864  $PrivSet->AddCondition($ConditionField,
1865  $ConditionValue, $ConditionOperator);
1866  break;
1867 
1868  default:
1869  # strip any excess whitespace off of value
1870  $Value = trim($Value);
1871 
1872  # if child looks like valid method name
1873  if (method_exists("PrivilegeSet", $Tag))
1874  {
1875  # convert constants if needed
1876  if (defined($Value)) { $Value = constant($Value); }
1877 
1878  # convert booleans if needed
1879  if (strtoupper($Value) == "TRUE") { $Value = TRUE; }
1880  elseif (strtoupper($Value) == "FALSE") { $Value = FALSE; }
1881 
1882  # set value using child data
1883  $PrivSet->$Tag((string)$Value);
1884  }
1885  else
1886  {
1887  # record error about bad tag
1888  $this->ErrorMsgs[__METHOD__][] =
1889  "Unknown tag encountered (".$Tag.").";
1890 
1891  # bail out
1892  return NULL;
1893  }
1894  break;
1895  }
1896  }
1897 
1898  # return new privilege set to caller
1899  return $PrivSet;
1900  }
1901 }
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.
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
UserCanView($User)
Determine if the given user can view resources using this schema.
const MDFORDER_ALPHABETICAL
UserCanEdit($User)
Determine if the given user can edit resources using this schema.
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.
static GetPrintableFieldName($Field)
Retrieve label for field.
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.
Delete()
Destroy metadata schema.
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
static GetCanonicalFieldIdentifier($Field)
Retrieve canonical identifier for field.
GetOwnedFields()
Get fields that have an owner associated with them.
PathMatchesViewPage($Path)
Determine if a path matches the view page path for the schema.
const MDFSTAT_DUPLICATEDBCOLUMN
GetEditOrder()
Get the editing order for the schema.
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.
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
static GetOrdersForSchema(MetadataSchema $Schema)
Get all of the orders associated with a schema.
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 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).