RelativeSlugHandler.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. namespace Gedmo\Sluggable\Handler;
  3. use Doctrine\Common\Persistence\ObjectManager;
  4. use Doctrine\Common\Persistence\Mapping\ClassMetadata;
  5. use Gedmo\Sluggable\SluggableListener;
  6. use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
  7. use Gedmo\Tool\Wrapper\AbstractWrapper;
  8. use Gedmo\Exception\InvalidMappingException;
  9. class RelativeSlugHandler implements SlugHandlerInterface
  10. {
  11. /**
  12. * @var Doctrine\Common\Persistence\ObjectManager
  13. */
  14. private $om;
  15. /**
  16. * @var Gedmo\Sluggable\SluggableListener
  17. */
  18. private $sluggable;
  19. /**
  20. * Options for relative slug handler
  21. *
  22. * @var array
  23. */
  24. private $options;
  25. private $originalTransliterator;
  26. private $parts = array();
  27. private $isInsert = false;
  28. /**
  29. * {@inheritDoc}
  30. */
  31. public function __construct(ObjectManager $om, SluggableListener $sluggable, array $options)
  32. {
  33. $this->om = $om;
  34. $this->sluggable = $sluggable;
  35. $default = array(
  36. 'recursive' => true,
  37. 'separator' => '/'
  38. );
  39. $this->options = array_merge($default, $options);
  40. }
  41. /**
  42. * {@inheritDoc}
  43. */
  44. public function postSlugBuild(SluggableAdapter $ea, array &$config, $object, &$slug)
  45. {
  46. $this->originalTransliterator = $this->sluggable->getTransliterator();
  47. $this->sluggable->setTransliterator(array($this, 'transliterate'));
  48. $this->parts = array();
  49. $this->isInsert = $this->om->getUnitOfWork()->isScheduledForInsert($object);
  50. $wrapped = AbstractWrapper::wrapp($object, $this->om);
  51. if ($this->isInsert) {
  52. do {
  53. $relation = $wrapped->getPropertyValue($this->options['relation']);
  54. if ($relation) {
  55. $wrappedRelation = AbstractWrapper::wrapp($relation, $this->om);
  56. array_unshift($this->parts, $wrappedRelation->getPropertyValue($this->options['targetField']));
  57. $wrapped = $wrappedRelation;
  58. }
  59. } while ($this->options['recursive'] && $relation);
  60. } else {
  61. $this->parts = explode($this->options['separator'], $wrapped->getPropertyValue($config['slug']));
  62. }
  63. }
  64. /**
  65. * {@inheritDoc}
  66. */
  67. public static function validate(array $options, ClassMetadata $meta)
  68. {
  69. if (!$meta->isSingleValuedAssociation($options['relation'])) {
  70. throw new InvalidMappingException("Unable to find slug relation through field - [{$options['relation']}] in class - {$meta->name}");
  71. }
  72. /*if (!$meta->isSingleValuedAssociation($options['relation'])) {
  73. throw new InvalidMappingException("Unable to find slug relation through field - [{$options['relation']}] in class - {$meta->name}");
  74. }*/
  75. }
  76. /**
  77. * {@inheritDoc}
  78. */
  79. public function onSlugCompletion(SluggableAdapter $ea, array &$config, $object, &$slug)
  80. {
  81. if (!$this->isInsert) {
  82. $wrapped = AbstractWrapper::wrapp($object, $this->om);
  83. $extConfig = $this->sluggable->getConfiguration($this->om, $wrapped->getMetadata()->name);
  84. $config['useObjectClass'] = $extConfig['useObjectClass'];
  85. $ea->replaceRelative(
  86. $object,
  87. $config,
  88. $wrapped->getPropertyValue($config['slug']).$this->options['separator'],
  89. $slug
  90. );
  91. }
  92. }
  93. public function transliterate($text, $separator, $object)
  94. {
  95. if ($this->isInsert) {
  96. foreach ($this->parts as &$part) {
  97. $part = call_user_func_array(
  98. $this->originalTransliterator,
  99. array($part, $separator, $object)
  100. );
  101. }
  102. } else {
  103. array_pop($this->parts);
  104. }
  105. $this->parts[] = call_user_func_array(
  106. $this->originalTransliterator,
  107. array($text, $separator, $object)
  108. );
  109. $this->sluggable->setTransliterator($this->originalTransliterator);
  110. return implode($this->options['separator'], $this->parts);
  111. }
  112. }