Skip to content

Commit

Permalink
Merge pull request #1781 from dgafka/v2.4.x
Browse files Browse the repository at this point in the history
Possibility to use sluggable with embedded entites
  • Loading branch information
l3pp4rd authored Apr 23, 2017
2 parents 1a5f953 + f2b09fb commit 58038d5
Showing 1 changed file with 98 additions and 67 deletions.
165 changes: 98 additions & 67 deletions lib/Gedmo/Sluggable/Mapping/Driver/Annotation.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,81 +62,112 @@ public function readExtendedMetadata($meta, array &$config)
) {
continue;
}
// slug property
if ($slug = $this->reader->getPropertyAnnotation($property, self::SLUG)) {
$field = $property->getName();
if (!$meta->hasField($field)) {
throw new InvalidMappingException("Unable to find slug [{$field}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Cannot use field - [{$field}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
$config = $this->retrieveSlug($meta, $config, $property, '');
}

// Embedded entity
if (property_exists($meta, 'embeddedClasses') && $meta->embeddedClasses) {
foreach ($meta->embeddedClasses as $propertyName => $embeddedClassInfo) {
$embeddedClass = new \ReflectionClass($embeddedClassInfo['class']);
foreach ($embeddedClass->getProperties() as $embeddedProperty) {
$config = $this->retrieveSlug($meta, $config, $embeddedProperty, $propertyName);
}
// process slug handlers
$handlers = array();
if (is_array($slug->handlers) && $slug->handlers) {
foreach ($slug->handlers as $handler) {
if (!$handler instanceof SlugHandler) {
throw new InvalidMappingException("SlugHandler: {$handler} should be instance of SlugHandler annotation in entity - {$meta->name}");
}
if (!strlen($handler->class)) {
throw new InvalidMappingException("SlugHandler class: {$handler->class} should be a valid class name in entity - {$meta->name}");
}
$class = $handler->class;
$handlers[$class] = array();
foreach ((array) $handler->options as $option) {
if (!$option instanceof SlugHandlerOption) {
throw new InvalidMappingException("SlugHandlerOption: {$option} should be instance of SlugHandlerOption annotation in entity - {$meta->name}");
}
if (!strlen($option->name)) {
throw new InvalidMappingException("SlugHandlerOption name: {$option->name} should be valid name in entity - {$meta->name}");
}
$handlers[$class][$option->name] = $option->value;
}
$class::validate($handlers[$class], $meta);
}
}

return $config;
}

/**
* @param $meta
* @param array $config
* @param $property
* @param $fieldNamePrefix
* @return array
*/
private function retrieveSlug($meta, array &$config, $property, $fieldNamePrefix)
{
$fieldName = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $property->getName()) : $property->getName();
// slug property
if ($slug = $this->reader->getPropertyAnnotation($property, self::SLUG)) {
if (!$meta->hasField($fieldName)) {
throw new InvalidMappingException("Unable to find slug [{$fieldName}] as mapped property in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $fieldName)) {
throw new InvalidMappingException("Cannot use field - [{$fieldName}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
// process slug handlers
$handlers = array();
if (is_array($slug->handlers) && $slug->handlers) {
foreach ($slug->handlers as $handler) {
if (!$handler instanceof SlugHandler) {
throw new InvalidMappingException("SlugHandler: {$handler} should be instance of SlugHandler annotation in entity - {$meta->name}");
}
}
// process slug fields
if (empty($slug->fields) || !is_array($slug->fields)) {
throw new InvalidMappingException("Slug must contain at least one field for slug generation in class - {$meta->name}");
}
foreach ($slug->fields as $slugField) {
if (!$meta->hasField($slugField)) {
throw new InvalidMappingException("Unable to find slug [{$slugField}] as mapped property in entity - {$meta->name}");
if (!strlen($handler->class)) {
throw new InvalidMappingException("SlugHandler class: {$handler->class} should be a valid class name in entity - {$meta->name}");
}
if (!$this->isValidField($meta, $slugField)) {
throw new InvalidMappingException("Cannot use field - [{$slugField}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
$class = $handler->class;
$handlers[$class] = array();
foreach ((array)$handler->options as $option) {
if (!$option instanceof SlugHandlerOption) {
throw new InvalidMappingException("SlugHandlerOption: {$option} should be instance of SlugHandlerOption annotation in entity - {$meta->name}");
}
if (!strlen($option->name)) {
throw new InvalidMappingException("SlugHandlerOption name: {$option->name} should be valid name in entity - {$meta->name}");
}
$handlers[$class][$option->name] = $option->value;
}
$class::validate($handlers[$class], $meta);
}
if (!is_bool($slug->updatable)) {
throw new InvalidMappingException("Slug annotation [updatable], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!is_bool($slug->unique)) {
throw new InvalidMappingException("Slug annotation [unique], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!empty($meta->identifier) && $meta->isIdentifier($field) && !(bool) $slug->unique) {
throw new InvalidMappingException("Identifier field - [{$field}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
if ($slug->unique === false && $slug->unique_base) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
// process slug fields
if (empty($slug->fields) || !is_array($slug->fields)) {
throw new InvalidMappingException("Slug must contain at least one field for slug generation in class - {$meta->name}");
}
foreach ($slug->fields as $slugField) {
$slugFieldWithPrefix = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $slugField) : $slugField;
if (!$meta->hasField($slugFieldWithPrefix)) {
throw new InvalidMappingException("Unable to find slug [{$slugFieldWithPrefix}] as mapped property in entity - {$meta->name}");
}
if ($slug->unique_base && !$meta->hasField($slug->unique_base) && !$meta->hasAssociation($slug->unique_base)) {
throw new InvalidMappingException("Unable to find [{$slug->unique_base}] as mapped property in entity - {$meta->name}");
if (!$this->isValidField($meta, $slugFieldWithPrefix)) {
throw new InvalidMappingException("Cannot use field - [{$slugFieldWithPrefix}] for slug storage, type is not valid and must be 'string' or 'text' in class - {$meta->name}");
}
// set all options
$config['slugs'][$field] = array(
'fields' => $slug->fields,
'slug' => $field,
'style' => $slug->style,
'dateFormat' => $slug->dateFormat,
'updatable' => $slug->updatable,
'unique' => $slug->unique,
'unique_base' => $slug->unique_base,
'separator' => $slug->separator,
'prefix' => $slug->prefix,
'suffix' => $slug->suffix,
'handlers' => $handlers,
);
}
if (!is_bool($slug->updatable)) {
throw new InvalidMappingException("Slug annotation [updatable], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!is_bool($slug->unique)) {
throw new InvalidMappingException("Slug annotation [unique], type is not valid and must be 'boolean' in class - {$meta->name}");
}
if (!empty($meta->identifier) && $meta->isIdentifier($fieldName) && !(bool)$slug->unique) {
throw new InvalidMappingException("Identifier field - [{$fieldName}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
if ($slug->unique === false && $slug->unique_base) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($slug->unique_base && !$meta->hasField($slug->unique_base) && !$meta->hasAssociation($slug->unique_base)) {
throw new InvalidMappingException("Unable to find [{$slug->unique_base}] as mapped property in entity - {$meta->name}");
}
$sluggableFields = [];
foreach ($slug->fields as $field) {
$sluggableFields[] = $fieldNamePrefix ? ($fieldNamePrefix . '.' . $field) : $field;
}

// set all options
$config['slugs'][$fieldName] = array(
'fields' => $sluggableFields,
'slug' => $fieldName,
'style' => $slug->style,
'dateFormat' => $slug->dateFormat,
'updatable' => $slug->updatable,
'unique' => $slug->unique,
'unique_base' => $slug->unique_base,
'separator' => $slug->separator,
'prefix' => $slug->prefix,
'suffix' => $slug->suffix,
'handlers' => $handlers,
);
}
return $config;
}
}

0 comments on commit 58038d5

Please sign in to comment.