CWIS Developer Documentation
MetadataFieldOrder.php
Go to the documentation of this file.
1 <?PHP
2 
8 {
9 
13  const DISPLAY_FOLDER_NAME = "FieldDisplayFolder";
14 
18  const EDIT_FOLDER_NAME = "FieldEditFolder";
19 
24  public function GetItems()
25  {
26  $ItemIds = $this->GetItemIds();
27  $Items = array();
28 
29  foreach ($ItemIds as $Info)
30  {
31  $Items[] = new $Info["Type"]($Info["ID"]);
32  }
33 
34  return $Items;
35  }
36 
42  public function CreateGroup($Name)
43  {
44  $FolderFactory = new FolderFactory();
45 
46  # create the new group
47  $Folder = $FolderFactory->CreateMixedFolder($Name);
48  $Group = new MetadataFieldGroup($Folder->Id());
49 
50  # and add it to this ordering
51  $this->AppendItem($Group->Id(), "MetadataFieldGroup");
52 
53  return $Group;
54  }
55 
62  public function DeleteGroup(MetadataFieldGroup $Group)
63  {
64  if ($this->ContainsItem($Group->Id(), "MetadataFieldGroup"))
65  {
66  $this->MoveFieldsToOrder($Group);
67  $this->RemoveItem($Group->Id(), "MetadataFieldGroup");
68  }
69  }
70 
75  public function GetFields()
76  {
77  $Fields = array();
78 
79  foreach ($this->GetItems() as $Item)
80  {
81  # add fields to the list
82  if ($Item instanceof MetadataField)
83  {
84  $Fields[$Item->Id()] = $Item;
85  }
86 
87  # add fields of groups to the list
88  else if ($Item instanceof MetadataFieldGroup)
89  {
90  foreach ($Item->GetFields() as $Field)
91  {
92  $Fields[$Field->Id()] = $Field;
93  }
94  }
95  }
96 
97  return $Fields;
98  }
99 
104  public function GetGroups()
105  {
106  $ItemIds = $this->GetItemIds();
107  $GroupIds = array_filter($ItemIds, array($this, "GroupFilterCallback"));
108 
109  $Groups = array();
110 
111  # transform group info to group objects
112  foreach ($GroupIds as $GroupId)
113  {
114  try
115  {
116  $Groups[$GroupId["ID"]] = new $GroupId["Type"]($GroupId["ID"]);
117  } catch (Exception $Exception) {}
118  }
119 
120  return $Groups;
121  }
122 
132  public function MoveItemUp($Item, $Filter=NULL)
133  {
134  # make sure the item is a field or group
135  if (!$this->IsFieldOrGroup($Item))
136  {
137  throw new Exception("Item must be a field or group");
138  }
139 
140  # make sure the item is in the order
141  if (!$this->ItemInOrder($Item))
142  {
143  throw new Exception("Item must exist in the ordering");
144  }
145 
146  # make sure the filter is callable if set
147  if (!is_null($Filter) && !is_callable($Filter))
148  {
149  throw new Exception("Filter callback must be callable");
150  }
151 
152  $ItemType = $this->GetItemType($Item);
153  $Enclosure = $this->GetEnclosure($Item);
154  $EnclosureType = $this->GetItemType($Enclosure);
155  $Previous = $this->GetSiblingItem($Item, -1, $Filter);
156  $PreviousId = $this->GetItemId($Previous);
157  $PreviousType = $this->GetItemType($Previous);
158 
159  # determine if the item is at the top of the list
160  $ItemAtTop = is_null($Previous);
161 
162  # determine if a field needs to be moved into a group
163  $FieldToGroup = $ItemType == "MetadataField";
164  $FieldToGroup = $FieldToGroup && $EnclosureType == "MetadataFieldOrder";
165  $FieldToGroup = $FieldToGroup && $PreviousType == "MetadataFieldGroup";
166 
167  # determine if a field needs to be moved out of a group
168  $FieldToOrder = $ItemType == "MetadataField";
169  $FieldToOrder = $FieldToOrder && $EnclosureType == "MetadataFieldGroup";
170  $FieldToOrder = $FieldToOrder && $ItemAtTop;
171 
172  # move a field into a group if necessary
173  if ($FieldToGroup)
174  {
175  $this->MoveFieldToGroup($Previous, $Item, "append");
176  }
177 
178  # or move a field from a group to the order if necessary
179  else if ($FieldToOrder)
180  {
181  $this->MoveFieldToOrder($Enclosure, $Item, "before");
182  }
183 
184  # otherwise just move the item up if not at the top of the list
185  else if (!$ItemAtTop)
186  {
187  $this->MoveItemAfter($Item, $Previous);
188  }
189  }
190 
200  public function MoveItemDown($Item, $Filter=NULL)
201  {
202  # make sure the item is a field or group
203  if (!$this->IsFieldOrGroup($Item))
204  {
205  throw new Exception("Item must be a field or group");
206  }
207 
208  # make sure the item is in the order
209  if (!$this->ItemInOrder($Item))
210  {
211  throw new Exception("Item must exist in the ordering");
212  }
213 
214  # make sure the filter is callable if set
215  if (!is_null($Filter) && !is_callable($Filter))
216  {
217  throw new Exception("Filter callback must be callable");
218  }
219 
220  $ItemType = $this->GetItemType($Item);
221  $Enclosure = $this->GetEnclosure($Item);
222  $EnclosureType = $this->GetItemType($Enclosure);
223  $Next = $this->GetSiblingItem($Item, 1, $Filter);
224  $NextId = $this->GetItemId($Next);
225  $NextType = $this->GetItemType($Next);
226 
227  # determine if the item is at the bottom of the list
228  $ItemAtBottom = is_null($Next);
229 
230  # determine if a field needs to be moved into a group
231  $FieldToGroup = $ItemType == "MetadataField";
232  $FieldToGroup = $FieldToGroup && $EnclosureType == "MetadataFieldOrder";
233  $FieldToGroup = $FieldToGroup && $NextType == "MetadataFieldGroup";
234 
235  # determine if a field needs to be moved out of a group
236  $FieldToOrder = $ItemType == "MetadataField";
237  $FieldToOrder = $FieldToOrder && $EnclosureType == "MetadataFieldGroup";
238  $FieldToOrder = $FieldToOrder && $ItemAtBottom;
239 
240  # move a field into a group if necessary
241  if ($FieldToGroup)
242  {
243  $this->MoveFieldToGroup($Next, $Item, "prepend");
244  }
245 
246  # or move a field from a group to the order if necessary
247  else if ($FieldToOrder)
248  {
249  $this->MoveFieldToOrder($Enclosure, $Item, "after");
250  }
251 
252  # otherwise just move the item down if not at the bottom
253  else if (!$ItemAtBottom)
254  {
255  $this->MoveItemAfter($Next, $Item);
256  }
257  }
258 
265  public function MoveItemToTop($Item)
266  {
267  # make sure the item is either a field or group
268  if (!$this->IsFieldOrGroup($Item))
269  {
270  throw new Exception("Item must be a either field or group");
271  }
272 
273  # make sure the item is in the order
274  if (!$this->ItemInOrder($Item))
275  {
276  throw new Exception("Item must exist in the ordering");
277  }
278 
279  $OrderId = $this->GetItemId($this);
280  $OrderType = $this->GetItemType($this);
281  $ItemId = $this->GetItemId($Item);
282  $ItemType = $this->GetItemType($Item);
283  $ItemEnclosure = $this->GetEnclosure($Item);
284  $ItemEnclosureId = $this->GetItemId($ItemEnclosure);
285  $ItemEnclosureType = $this->GetItemType($ItemEnclosure);
286 
287  $SameEnclosureId = $OrderId == $ItemEnclosureId;
288  $SameEnclosureType = $OrderType == $ItemEnclosureType;
289 
290  # remove the item from its enclosure if necessary
291  if (!$SameEnclosureId || !$SameEnclosureType)
292  {
293  $ItemEnclosure->RemoveItem($ItemId, $ItemType);
294  }
295 
296  # move the item to the top of the order
297  $this->PrependItem($ItemId, $ItemType);
298  }
299 
305  public function MoveFieldToTopOfGroup(
306  MetadataFieldGroup $Group,
307  MetadataField $Field)
308  {
309  # make sure the items are in the order
310  if (!$this->ItemInOrder($Group) || !$this->ItemInOrder($Field))
311  {
312  throw new Exception("Item must exist in the ordering");
313  }
314 
315  $GroupId = $this->GetItemId($Group);
316  $GroupType = $this->GetItemType($Group);
317  $FieldId = $this->GetItemId($Field);
318  $FieldType = $this->GetItemType($Field);
319  $FieldEnclosure = $this->GetEnclosure($Field);
320  $FieldEnclosureId = $this->GetItemId($FieldEnclosure);
321  $FieldEnclosureType = $this->GetItemType($FieldEnclosure);
322 
323  $SameEnclosureId = $GroupId == $FieldEnclosureId;
324  $SameEnclosureType = $GroupType == $FieldEnclosureType;
325 
326  # remove the item from its enclosure if necessary
327  if (!$SameEnclosureId || !$SameEnclosureType)
328  {
329  $FieldEnclosure->RemoveItem($FieldId, $FieldType);
330  }
331 
332  # move the item to the top of the group
333  $Group->PrependItem($FieldId, $FieldType);
334  }
335 
345  public function MoveItemAfter($Target, $Item)
346  {
347  # make sure the items are either a field or group
348  if (!$this->IsFieldOrGroup($Target) || !$this->IsFieldOrGroup($Item))
349  {
350  throw new Exception("Items must be a either field or group");
351  }
352 
353  # make sure the items are in the order
354  if (!$this->ItemInOrder($Target) || !$this->ItemInOrder($Item))
355  {
356  throw new Exception("Items must exist in the ordering");
357  }
358 
359  $TargetId = $this->GetItemId($Target);
360  $TargetType = $this->GetItemType($Target);
361  $ItemId = $this->GetItemId($Item);
362  $ItemType = $this->GetItemType($Item);
363  $TargetEnclosure = $this->GetEnclosure($Target);
364  $TargetEnclosureId = $this->GetItemId($TargetEnclosure);
365  $TargetEnclosureType = $this->GetItemType($TargetEnclosure);
366  $ItemEnclosure = $this->GetEnclosure($Item);
367  $ItemEnclosureId = $this->GetItemId($ItemEnclosure);
368  $ItemEnclosureType = $this->GetItemType($ItemEnclosure);
369 
370  $TargetInGroup = $TargetEnclosure instanceof MetadataFieldGroup;
371  $ItemIsField = $Item instanceof MetadataField;
372 
373  # make sure only fields are placed in groups
374  if ($TargetInGroup && !$ItemIsField)
375  {
376  throw new Exception("Only fields can go into field groups");
377  }
378 
379  $SameEnclosureId = $TargetEnclosureId == $ItemEnclosureId;
380  $SameEnclosureType = $TargetEnclosureType == $ItemEnclosureType;
381 
382  # move a field into a group if necessary
383  if (!$SameEnclosureId || !$SameEnclosureType)
384  {
385  $ItemEnclosure->RemoveItem($ItemId, $ItemType);
386  }
387 
388  # move the item after the target
389  $TargetEnclosure->InsertItemAfter(
390  $TargetId,
391  $ItemId,
392  $TargetType,
393  $ItemType);
394  }
395 
401  public function ItemInOrder($Item)
402  {
403  # the item would have to be a field or group to be in the order
404  if (!$this->IsFieldOrGroup($Item))
405  {
406  return FALSE;
407  }
408 
409  $ItemId = $this->GetItemId($Item);
410  $ItemType = $this->GetItemType($Item);
411 
412  # if the item is in the order, i.e., not in a group
413  if ($this->ContainsItem($ItemId, $ItemType))
414  {
415  return TRUE;
416  }
417 
418  # the item is in one of the groups, so search each one for it
419  foreach ($this->GetGroups() as $Group)
420  {
421  if ($Group->ContainsItem($ItemId, $ItemType))
422  {
423  return TRUE;
424  }
425  }
426 
427  # the item was not found
428  return FALSE;
429  }
430 
437  public static function SetConfiguration(SystemConfiguration $SysConfig)
438  {
439  $DisplayFolderId = $SysConfig->FieldDisplayFolder();
440  $EditFolderId = $SysConfig->FieldEditFolder();
441 
442  # create the display folder and update the system configuration if
443  # necessary
444  if (!$DisplayFolderId)
445  {
446  $Order = self::CreateOrderingObject(
447  self::DISPLAY_FOLDER_NAME,
449  $DisplayFolderId = $Order->Id();
451  }
452 
453  # create the edit folder and update the system configuration if
454  # necessary
455  if (!$EditFolderId)
456  {
457  $Order = self::CreateOrderingObject(
458  self::EDIT_FOLDER_NAME,
460  $EditFolderId = $Order->Id();
461  $SysConfig->FieldEditFolder($EditFolderId);
462  }
463 
464  self::$DisplayFolderId = $DisplayFolderId;
465  self::$EditFolderId = $EditFolderId;
466  }
467 
473  public static function GetDisplayOrderObject()
474  {
475  self::CheckOrderingConfiguration();
476 
477  return new MetadataFieldOrder(self::$DisplayFolderId);
478  }
479 
485  public static function GetEditOrderObject()
486  {
487  self::CheckOrderingConfiguration();
488 
489  return new MetadataFieldOrder(self::$EditFolderId);
490  }
491 
496  public static function MendIssues()
497  {
498  try
499  {
500  $DisplayOrder = self::GetDisplayOrderObject();
501  $EditOrder = self::GetEditOrderObject();
502  $Schema = new MetadataSchema();
503  $Fields = $Schema->GetFields(NULL, NULL, TRUE);
504 
505  foreach ($Fields as $Field)
506  {
507  if (!$DisplayOrder->ItemInOrder($Field))
508  {
509  $DisplayOrder->AppendItem($Field->Id(), "MetadataField");
510  }
511 
512  if (!$EditOrder->ItemInOrder($Field))
513  {
514  $EditOrder->AppendItem($Field->Id(), "MetadataField");
515  }
516  }
517  } catch (Exception $Exception){}
518  }
519 
525  protected function IsFieldOrGroup($Item)
526  {
527  if ($Item instanceof MetadataField)
528  {
529  return TRUE;
530  }
531 
532  if ($Item instanceof MetadataFieldGroup)
533  {
534  return TRUE;
535  }
536 
537  return FALSE;
538  }
539 
545  protected function GetItemId($Item)
546  {
547  return is_object($Item) ? $Item->Id() : NULL;
548  }
549 
555  protected function GetItemType($Item)
556  {
557  return is_object($Item) ? get_class($Item) : NULL;
558  }
559 
566  protected function GroupFilterCallback($Item)
567  {
568  return $Item["Type"] == "MetadataFieldGroup";
569  }
570 
578  protected function GetEnclosure($Item)
579  {
580  $ItemId = $this->GetItemId($Item);
581  $ItemType = $this->GetItemType($Item);
582 
583  # the item is in the order, i.e., not in a group
584  if ($this->ContainsItem($ItemId, $ItemType))
585  {
586  return $this;
587  }
588 
589  # the item is in one of the groups, so search each one for it
590  foreach ($this->GetGroups() as $Group)
591  {
592  if ($Group->ContainsItem($ItemId, $ItemType))
593  {
594  return $Group;
595  }
596  }
597 
598  # the item was not found
599  return NULL;
600  }
601 
609  protected function GetSiblingItem($Item, $Offset, $Filter=NULL)
610  {
611  $Id = $this->GetItemId($Item);
612  $Type = $this->GetItemType($Item);
613  $Sibling = NULL;
614 
615  # the sibling is in the order, i.e., not in a group
616  if ($this->ContainsItem($Id, $Type))
617  {
618  return $this->FindSiblingItem($this, $Item, $Offset, $Filter);
619  }
620 
621  # otherwise search for it in the groups
622  foreach ($this->GetGroups() as $Group)
623  {
624  if ($Group->ContainsItem($Id, $Type))
625  {
626  try
627  {
628  $Sibling = $this->FindSiblingItem(
629  $Group,
630  $Item,
631  $Offset,
632  $Filter);
633 
634  if ($Sibling)
635  {
636  return $Sibling;
637  }
638  } catch (Exception $Exception) {}
639 
640  break;
641  }
642  }
643 
644  return NULL;
645  }
646 
656  protected function FindSiblingItem($Enclosure, $Item, $Offset, $Filter=NULL)
657  {
658  $ItemIds = $Enclosure->GetItemIds();
659 
660  # filter items if necessary
661  if (is_callable($Filter))
662  {
663  $ItemIds = array_filter($ItemIds, $Filter);
664 
665  # maintain continuous indices
666  ksort($ItemIds);
667  $ItemIds = array_values($ItemIds);
668  }
669 
670  $Id = $this->GetItemId($Item);
671  $Type = $this->GetItemType($Item);
672  $Index = array_search(array("ID" => $Id, "Type" => $Type), $ItemIds);
673 
674  if (!is_null($Index) && array_key_exists($Index+$Offset, $ItemIds))
675  {
676  $SiblingInfo = $ItemIds[$Index+$Offset];
677  return new $SiblingInfo["Type"]($SiblingInfo["ID"]);
678  }
679 
680  return NULL;
681  }
682 
691  protected function MoveFieldToGroup(
692  MetadataFieldGroup $Group,
693  MetadataField $Field,
694  $Placement)
695  {
696  # determine which action to use based on the placement value
697  $Action = $Placement == "prepend" ? "PrependItem" : "AppendItem";
698 
699  $GroupId = $this->GetItemId($Group);
700  $FieldId = $this->GetItemId($Field);
701 
702  $OrderHasGroup = $this->ContainsItem($GroupId, "MetadataFieldGroup");
703  $OrderHasField = $this->ContainsItem($FieldId, "MetadataField");
704 
705  # make sure the field and group are in the order before editing
706  if ($OrderHasGroup && $OrderHasField)
707  {
708  $this->RemoveItem($FieldId, "MetadataField");
709  $Group->$Action($FieldId, "MetadataField");
710  }
711  }
712 
721  protected function MoveFieldToOrder(
722  MetadataFieldGroup $Group,
723  MetadataField $Field,
724  $Placement)
725  {
726  # determine which action to use based on the placement value
727  $Action = $Placement == "before" ? "InsertItemBefore" : "InsertItemAfter";
728 
729  $GroupId = $this->GetItemId($Group);
730  $FieldId = $this->GetItemId($Field);
731 
732  $OrderHasGroup = $this->ContainsItem($GroupId, "MetadataFieldGroup");
733  $GroupHasField = $Group->ContainsItem($FieldId, "MetadataField");
734 
735  # make sure the field is in the group and the group is in the order
736  if ($OrderHasGroup && $GroupHasField)
737  {
738  $Group->RemoveItem($FieldId, "MetadataField");
739  $this->$Action(
740  $GroupId,
741  $FieldId,
742  "MetadataFieldGroup",
743  "MetadataField");
744  }
745  }
746 
753  protected function MoveFieldsToOrder(MetadataFieldGroup $Group)
754  {
755  $ItemIds = $Group->GetItemIds();
756  $PreviousItemId = $Group->Id();
757  $PreviousItemType = "MetadataFieldGroup";
758 
759  foreach ($ItemIds as $ItemInfo)
760  {
761  $ItemId = $ItemInfo["ID"];
762  $ItemType = $ItemInfo["Type"];
763 
764  $this->InsertItemAfter(
765  $PreviousItemId,
766  $ItemId,
767  $PreviousItemType,
768  $ItemType);
769 
770  $PreviousItemId = $ItemId;
771  $PreviousItemType = $ItemType;
772  }
773  }
774 
781  protected static function CheckOrderingConfiguration()
782  {
783  if (!self::$DisplayFolderId || !self::$EditFolderId)
784  {
785  throw new Exception("Metadata field ordering configuration not set");
786  }
787  }
788 
795  protected static function CreateOrderingObject($NewFolderName, $Type)
796  {
797  # create the folder
798  $FolderFactory = new FolderFactory();
799  $Folder = $FolderFactory->CreateMixedFolder($NewFolderName);
800 
801  # temporarily save and change the current setting
804 
805  # get the metadata fields that will be added
806  $Schema = new MetadataSchema();
807  $Fields = $Schema->GetFields(NULL, $Type, TRUE);
808 
809  # restore the old setting
811 
812  # add each field to the folder
813  foreach ($Fields as $Field)
814  {
815  $Folder->AppendItem($Field->Id(), "MetadataField");
816  }
817 
818  # wrap the folder in a MetadataFieldOrder object
819  return new MetadataFieldOrder($Folder->Id());
820  }
821 
825  protected static $DisplayFolderId;
826 
830  protected static $EditFolderId;
831 
832 }