RepositoryUtils.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. namespace Gedmo\Tree;
  3. use Doctrine\Common\Persistence\Mapping\ClassMetadata;
  4. use Doctrine\Common\Persistence\ObjectManager;
  5. class RepositoryUtils implements RepositoryUtilsInterface
  6. {
  7. protected $meta;
  8. protected $listener;
  9. protected $om;
  10. protected $repo;
  11. public function __construct(ObjectManager $om, ClassMetadata $meta, $listener, $repo)
  12. {
  13. $this->om = $om;
  14. $this->meta = $meta;
  15. $this->listener = $listener;
  16. $this->repo = $repo;
  17. }
  18. public function getClassMetadata()
  19. {
  20. return $this->meta;
  21. }
  22. /**
  23. * {@inheritDoc}
  24. */
  25. public function childrenHierarchy($node = null, $direct = false, array $options = array())
  26. {
  27. $meta = $this->getClassMetadata();
  28. $config = $this->listener->getConfiguration($this->om, $meta->name);
  29. if ($node !== null) {
  30. if ($node instanceof $meta->name) {
  31. $wrapperClass = $this->om instanceof \Doctrine\ORM\EntityManager ?
  32. '\Gedmo\Tool\Wrapper\EntityWrapper' :
  33. '\Gedmo\Tool\Wrapper\MongoDocumentWrapper';
  34. $wrapped = new $wrapperClass($node, $this->om);
  35. if (!$wrapped->hasValidIdentifier()) {
  36. throw new InvalidArgumentException("Node is not managed by UnitOfWork");
  37. }
  38. }
  39. }
  40. // Gets the array of $node results. It must be ordered by depth
  41. $nodes = $this->repo->getNodesHierarchy($node, $direct, $config, $options);
  42. return $this->buildTree($nodes, $options);
  43. }
  44. /**
  45. * {@inheritDoc}
  46. */
  47. public function buildTree(array $nodes, array $options = array())
  48. {
  49. $meta = $this->getClassMetadata();
  50. $nestedTree = $this->repo->buildTreeArray($nodes);
  51. $default = array(
  52. 'decorate' => false,
  53. 'rootOpen' => '<ul>',
  54. 'rootClose' => '</ul>',
  55. 'childOpen' => '<li>',
  56. 'childClose' => '</li>',
  57. 'nodeDecorator' => function ($node) use ($meta) {
  58. // override and change it, guessing which field to use
  59. if ($meta->hasField('title')) {
  60. $field = 'title';
  61. } elseif ($meta->hasField('name')) {
  62. $field = 'name';
  63. } else {
  64. throw new InvalidArgumentException("Cannot find any representation field");
  65. }
  66. return $node[$field];
  67. }
  68. );
  69. $options = array_merge($default, $options);
  70. // If you don't want any html output it will return the nested array
  71. if (!$options['decorate']) {
  72. return $nestedTree;
  73. } elseif (!count($nestedTree)) {
  74. return '';
  75. }
  76. $build = function($tree) use (&$build, &$options) {
  77. $output = is_string($options['rootOpen']) ? $options['rootOpen'] : $options['rootOpen']($tree);
  78. foreach ($tree as $node) {
  79. $output .= is_string($options['childOpen']) ? $options['childOpen'] : $options['childOpen']($node);
  80. $output .= $options['nodeDecorator']($node);
  81. if (count($node['__children']) > 0) {
  82. $output .= $build($node['__children']);
  83. }
  84. $output .= $options['childClose'];
  85. }
  86. return $output . $options['rootClose'];
  87. };
  88. return $build($nestedTree);
  89. }
  90. /**
  91. * {@inheritDoc}
  92. */
  93. public function buildTreeArray(array $nodes)
  94. {
  95. $meta = $this->getClassMetadata();
  96. $config = $this->listener->getConfiguration($this->om, $meta->name);
  97. $nestedTree = array();
  98. $l = 0;
  99. if (count($nodes) > 0) {
  100. // Node Stack. Used to help building the hierarchy
  101. $stack = array();
  102. foreach ($nodes as $child) {
  103. $item = $child;
  104. $item['__children'] = array();
  105. // Number of stack items
  106. $l = count($stack);
  107. // Check if we're dealing with different levels
  108. while($l > 0 && $stack[$l - 1][$config['level']] >= $item[$config['level']]) {
  109. array_pop($stack);
  110. $l--;
  111. }
  112. // Stack is empty (we are inspecting the root)
  113. if ($l == 0) {
  114. // Assigning the root child
  115. $i = count($nestedTree);
  116. $nestedTree[$i] = $item;
  117. $stack[] = &$nestedTree[$i];
  118. } else {
  119. // Add child to parent
  120. $i = count($stack[$l - 1]['__children']);
  121. $stack[$l - 1]['__children'][$i] = $item;
  122. $stack[] = &$stack[$l - 1]['__children'][$i];
  123. }
  124. }
  125. }
  126. return $nestedTree;
  127. }
  128. }