CerFieldChainHandler.inc 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. /**
  3. * @file
  4. * Contains the CerFieldChainHandler object.
  5. */
  6. /**
  7. * @class
  8. * Wraps around every CerFieldHandler object in a chain. In any given chain, there
  9. * could be many entities that need to be processed -- think about multi-value field
  10. * collections embedded within other multi-value field collections, and you quickly
  11. * see how extensive the recursion can be. CER needs to be able to handle crazy
  12. * scenarios like that and still perform add/delete operations transparently. That's
  13. * what this guy does.
  14. */
  15. class CerFieldChainHandler {
  16. /**
  17. * @var CerFieldChain
  18. */
  19. protected $chain;
  20. /**
  21. * @var EntityDrupalWrapper
  22. */
  23. protected $entity;
  24. /**
  25. * @var array or RecursiveIteratorIterator
  26. */
  27. protected $handlers;
  28. public function __construct(CerFieldChain $chain, EntityDrupalWrapper $entity) {
  29. $this->chain = $chain;
  30. $this->entity = $entity;
  31. $chain->__wakeup();
  32. $chain->seek($entity->cer->depth->value());
  33. $field = $chain->current();
  34. // If the field has a child, there could be extensive recusion here. So we'll need
  35. // to iterate over the entire chain recursively -- luckily, SPL provides the
  36. // RecursiveIteratorIterator class for this purpose. But if there are no children,
  37. // we don't need to recurse; the only handler we'll need to load is the current
  38. // field's, for the current entity.
  39. if ($field->child()) {
  40. $this->handlers = new RecursiveIteratorIterator(new CerEndPointIterator($field, $entity));
  41. }
  42. else {
  43. // Wrap the handler in an array, just to normalize things internally.
  44. $this->handlers = array( $field->getHandler($entity) );
  45. }
  46. }
  47. /**
  48. * Returns the IDs of every entity referenced in this chain. If there are no references,
  49. * an empty array is returned.
  50. *
  51. * @return array
  52. */
  53. public function getIDs() {
  54. $IDs = array();
  55. foreach ($this->handlers as $handler) {
  56. $IDs = array_merge($handler->getIDs(), $IDs);
  57. }
  58. return array_unique($IDs);
  59. }
  60. /**
  61. * Adds a reference to the given entity.
  62. */
  63. public function add(EntityDrupalWrapper $entity) {
  64. $owner = $this->entity;
  65. foreach ($this->chain as $field) {
  66. // If the current field implements CerEntityContainerInterface, we can
  67. // create an entity on-the-fly to receive the reference, if there isn't
  68. // one already.
  69. if ($field instanceof CerEntityContainerInterface) {
  70. $items = $field->getHandler($owner);
  71. // If there is are items which could receive the reference, seek to the
  72. // last one. Otherwise, create one.
  73. if (sizeof($items) == 0) {
  74. $owner = $field->createInnerEntity($owner);
  75. }
  76. else {
  77. $items->seek(-1);
  78. $owner = $items->current();
  79. }
  80. }
  81. }
  82. $field->getHandler($owner)->add($entity);
  83. }
  84. public function delete(EntityDrupalWrapper $entity) {
  85. foreach ($this->handlers as $handler) {
  86. $handler->delete($entity);
  87. }
  88. }
  89. }