Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Annotation\SlugHandler;
use Gedmo\Mapping\Annotation\SlugHandlerOption;
use Gedmo\Mapping\Driver\AbstractAnnotationDriver;
use Gedmo\Exception\InvalidMappingException;
/**
* This is an annotation mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from Annotations specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Annotation extends AbstractAnnotationDriver
{
/**
* Annotation to identify field as one which holds the slug
* together with slug options
*/
const SLUG = 'Gedmo\\Mapping\\Annotation\\Slug';
/**
* SlugHandler extension annotation
*/
const HANDLER = 'Gedmo\\Mapping\\Annotation\\SlugHandler';
/**
* SlugHandler option annotation
*/
const HANDLER_OPTION = 'Gedmo\\Mapping\\Annotation\\SlugHandlerOption';
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
protected $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$class = $this->getMetaReflectionClass($meta);
// property annotations
foreach ($class->getProperties() as $property) {
if ($meta->isMappedSuperclass && !$property->isPrivate() ||
$meta->isInheritedField($property->name) ||
isset($meta->associationMappings[$property->name]['inherited'])
) {
continue;
}
$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);
}
}
}
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}");
}
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);
}
}
// 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 (!$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}");
}
}
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 = array();
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;
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Driver\Xml as BaseXml;
use Gedmo\Exception\InvalidMappingException;
/**
* This is a xml mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from xml specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @author Miha Vrhovnik <miha.vrhovnik@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Xml extends BaseXml
{
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
private $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
/**
* @var \SimpleXmlElement $xml
*/
$xml = $this->_getMapping($meta->name);
if (isset($xml->field)) {
foreach ($xml->field as $mapping) {
$field = $this->_getAttribute($mapping, 'name');
$this->buildFieldConfiguration($meta, $field, $mapping, $config);
}
}
if (isset($xml->{'attribute-overrides'})) {
foreach ($xml->{'attribute-overrides'}->{'attribute-override'} as $mapping) {
$field = $this->_getAttribute($mapping, 'name');
$this->buildFieldConfiguration($meta, $field, $mapping->field, $config);
}
}
}
private function buildFieldConfiguration($meta, $field, \SimpleXMLElement $mapping, array &$config)
{
/**
* @var \SimpleXmlElement $mapping
*/
$mapping = $mapping->children(self::GEDMO_NAMESPACE_URI);
if (isset($mapping->slug)) {
/**
* @var \SimpleXmlElement $slug
*/
$slug = $mapping->slug;
if (!$this->isValidField($meta, $field)) {
throw new InvalidMappingException("Cannot use field - [{$field}] for slug storage, type is not valid and must be 'string' in class - {$meta->name}");
}
$fields = array_map('trim', explode(',', (string) $this->_getAttribute($slug, 'fields')));
foreach ($fields as $slugField) {
if (!$meta->hasField($slugField)) {
throw new InvalidMappingException("Unable to find slug [{$slugField}] as mapped property 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}");
}
}
$handlers = array();
if (isset($slug->handler)) {
foreach ($slug->handler as $handler) {
$class = (string) $this->_getAttribute($handler, 'class');
$handlers[$class] = array();
foreach ($handler->{'handler-option'} as $option) {
$handlers[$class][(string) $this->_getAttribute($option, 'name')]
= (string) $this->_getAttribute($option, 'value')
;
}
$class::validate($handlers[$class], $meta);
}
}
// set all options
$config['slugs'][$field] = array(
'fields' => $fields,
'slug' => $field,
'style' => $this->_isAttributeSet($slug, 'style') ?
$this->_getAttribute($slug, 'style') : 'default',
'updatable' => $this->_isAttributeSet($slug, 'updatable') ?
$this->_getBooleanAttribute($slug, 'updatable') : true,
'dateFormat' => $this->_isAttributeSet($slug, 'dateFormat') ?
$this->_getAttribute($slug, 'dateFormat') : 'Y-m-d-H:i',
'unique' => $this->_isAttributeSet($slug, 'unique') ?
$this->_getBooleanAttribute($slug, 'unique') : true,
'unique_base' => $this->_isAttributeSet($slug, 'unique-base') ?
$this->_getAttribute($slug, 'unique-base') : null,
'separator' => $this->_isAttributeSet($slug, 'separator') ?
$this->_getAttribute($slug, 'separator') : '-',
'prefix' => $this->_isAttributeSet($slug, 'prefix') ?
$this->_getAttribute($slug, 'prefix') : '',
'suffix' => $this->_isAttributeSet($slug, 'suffix') ?
$this->_getAttribute($slug, 'suffix') : '',
'handlers' => $handlers,
);
if (!$meta->isMappedSuperclass && $meta->isIdentifier($field) && !$config['slugs'][$field]['unique']) {
throw new InvalidMappingException("Identifier field - [{$field}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
$ubase = $config['slugs'][$field]['unique_base'];
if ($config['slugs'][$field]['unique'] === false && $ubase) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($ubase && !$meta->hasField($ubase) && !$meta->hasAssociation($ubase)) {
throw new InvalidMappingException("Unable to find [{$ubase}] as mapped property in entity - {$meta->name}");
}
}
}
/**
* Checks if $field type is valid as Sluggable field
*
* @param object $meta
* @param string $field
*
* @return boolean
*/
protected function isValidField($meta, $field)
{
$mapping = $meta->getFieldMapping($field);
return $mapping && in_array($mapping['type'], $this->validTypes);
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace Gedmo\Sluggable\Mapping\Driver;
use Gedmo\Mapping\Driver\File;
use Gedmo\Mapping\Driver;
use Gedmo\Exception\InvalidMappingException;
/**
* This is a yaml mapping driver for Sluggable
* behavioral extension. Used for extraction of extended
* metadata from yaml specifically for Sluggable
* extension.
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class Yaml extends File implements Driver
{
/**
* File extension
* @var string
*/
protected $_extension = '.dcm.yml';
/**
* List of types which are valid for slug and sluggable fields
*
* @var array
*/
private $validTypes = array(
'string',
'text',
'integer',
'int',
'datetime',
'citext',
);
/**
* {@inheritDoc}
*/
public function readExtendedMetadata($meta, array &$config)
{
$mapping = $this->_getMapping($meta->name);
if (isset($mapping['fields'])) {
foreach ($mapping['fields'] as $field => $fieldMapping) {
$this->buildFieldConfiguration($field, $fieldMapping, $meta, $config);
}
}
if (isset($mapping['attributeOverride'])) {
foreach ($mapping['attributeOverride'] as $field => $overrideMapping) {
$this->buildFieldConfiguration($field, $overrideMapping, $meta, $config);
}
}
}
/**
* {@inheritDoc}
*/
protected function _loadMappingFile($file)
{
return \Symfony\Component\Yaml\Yaml::parse(file_get_contents($file));
}
/**
* Checks if $field type is valid as Sluggable field
*
* @param object $meta
* @param string $field
*
* @return boolean
*/
protected function isValidField($meta, $field)
{
$mapping = $meta->getFieldMapping($field);
return $mapping && in_array($mapping['type'], $this->validTypes);
}
private function buildFieldConfiguration($field, array $fieldMapping, $meta, array &$config)
{
if (isset($fieldMapping['gedmo'])) {
if (isset($fieldMapping['gedmo']['slug'])) {
$slug = $fieldMapping['gedmo']['slug'];
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}");
}
// process slug handlers
$handlers = array();
if (isset($slug['handlers'])) {
foreach ($slug['handlers'] as $handlerClass => $options) {
if (!strlen($handlerClass)) {
throw new InvalidMappingException("SlugHandler class: {$handlerClass} should be a valid class name in entity - {$meta->name}");
}
$handlers[$handlerClass] = $options;
$handlerClass::validate($handlers[$handlerClass], $meta);
}
}
// 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 (!$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}");
}
}
$config['slugs'][$field]['fields'] = $slug['fields'];
$config['slugs'][$field]['handlers'] = $handlers;
$config['slugs'][$field]['slug'] = $field;
$config['slugs'][$field]['style'] = isset($slug['style']) ?
(string) $slug['style'] : 'default';
$config['slugs'][$field]['dateFormat'] = isset($slug['dateFormat']) ?
(string) $slug['dateFormat'] : 'Y-m-d-H:i';
$config['slugs'][$field]['updatable'] = isset($slug['updatable']) ?
(bool) $slug['updatable'] : true;
$config['slugs'][$field]['unique'] = isset($slug['unique']) ?
(bool) $slug['unique'] : true;
$config['slugs'][$field]['unique_base'] = isset($slug['unique_base']) ?
$slug['unique_base'] : null;
$config['slugs'][$field]['separator'] = isset($slug['separator']) ?
(string) $slug['separator'] : '-';
$config['slugs'][$field]['prefix'] = isset($slug['prefix']) ?
(string) $slug['prefix'] : '';
$config['slugs'][$field]['suffix'] = isset($slug['suffix']) ?
(string) $slug['suffix'] : '';
if (!$meta->isMappedSuperclass && $meta->isIdentifier($field) && !$config['slugs'][$field]['unique']) {
throw new InvalidMappingException("Identifier field - [{$field}] slug must be unique in order to maintain primary key in class - {$meta->name}");
}
$ubase = $config['slugs'][$field]['unique_base'];
if ($config['slugs'][$field]['unique'] === false && $ubase) {
throw new InvalidMappingException("Slug annotation [unique_base] can not be set if unique is unset or 'false'");
}
if ($ubase && !$meta->hasField($ubase) && !$meta->hasAssociation($ubase)) {
throw new InvalidMappingException("Unable to find [{$ubase}] as mapped property in entity - {$meta->name}");
}
}
}
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace Gedmo\Sluggable\Mapping\Event\Adapter;
use Gedmo\Mapping\Event\Adapter\ODM as BaseAdapterODM;
use Doctrine\ODM\MongoDB\Cursor;
use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
use Gedmo\Tool\Wrapper\AbstractWrapper;
/**
* Doctrine event adapter for ODM adapted
* for sluggable behavior
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
final class ODM extends BaseAdapterODM implements SluggableAdapter
{
/**
* {@inheritDoc}
*/
public function getSimilarSlugs($object, $meta, array $config, $slug)
{
$dm = $this->getObjectManager();
$wrapped = AbstractWrapper::wrap($object, $dm);
$qb = $dm->createQueryBuilder($config['useObjectClass']);
if (($identifier = $wrapped->getIdentifier()) && !$meta->isIdentifier($config['slug'])) {
$qb->field($meta->identifier)->notEqual($identifier);
}
$qb->field($config['slug'])->equals(new \MongoRegex('/^'.preg_quote($slug, '/').'/'));
// use the unique_base to restrict the uniqueness check
if ($config['unique'] && isset($config['unique_base'])) {
if (is_object($ubase = $wrapped->getPropertyValue($config['unique_base']))) {
$qb->field($config['unique_base'].'.$id')->equals(new \MongoId($ubase->getId()));
} elseif ($ubase) {
$qb->where('/^'.preg_quote($ubase, '/').'/.test(this.'.$config['unique_base'].')');
} else {
$qb->field($config['unique_base'])->equals(null);
}
}
$q = $qb->getQuery();
$q->setHydrate(false);
$result = $q->execute();
if ($result instanceof Cursor) {
$result = $result->toArray();
}
return $result;
}
/**
* This query can cause some data integrity failures since it does not
* execute automatically
*
* {@inheritDoc}
*/
public function replaceRelative($object, array $config, $target, $replacement)
{
$dm = $this->getObjectManager();
$meta = $dm->getClassMetadata($config['useObjectClass']);
$q = $dm
->createQueryBuilder($config['useObjectClass'])
->where("function() {
return this.{$config['slug']}.indexOf('{$target}') === 0;
}")
->getQuery()
;
$q->setHydrate(false);
$result = $q->execute();
if ($result instanceof Cursor) {
$result = $result->toArray();
foreach ($result as $targetObject) {
$slug = preg_replace("@^{$target}@smi", $replacement.$config['pathSeparator'], $targetObject[$config['slug']]);
$dm
->createQueryBuilder()
->update($config['useObjectClass'])
->field($config['slug'])->set($slug)
->field($meta->identifier)->equals($targetObject['_id'])
->getQuery()
->execute()
;
}
}
}
/**
* This query can cause some data integrity failures since it does not
* execute atomically
*
* {@inheritDoc}
*/
public function replaceInverseRelative($object, array $config, $target, $replacement)
{
$dm = $this->getObjectManager();
$wrapped = AbstractWrapper::wrap($object, $dm);
$meta = $dm->getClassMetadata($config['useObjectClass']);
$q = $dm
->createQueryBuilder($config['useObjectClass'])
->field($config['mappedBy'].'.'.$meta->identifier)->equals($wrapped->getIdentifier())
->getQuery()
;
$q->setHydrate(false);
$result = $q->execute();
if ($result instanceof Cursor) {
$result = $result->toArray();
foreach ($result as $targetObject) {
$slug = preg_replace("@^{$replacement}@smi", $target, $targetObject[$config['slug']]);
$dm
->createQueryBuilder()
->update($config['useObjectClass'])
->field($config['slug'])->set($slug)
->field($meta->identifier)->equals($targetObject['_id'])
->getQuery()
->execute()
;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace Gedmo\Sluggable\Mapping\Event\Adapter;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Gedmo\Mapping\Event\Adapter\ORM as BaseAdapterORM;
use Doctrine\ORM\Query;
use Gedmo\Sluggable\Mapping\Event\SluggableAdapter;
use Gedmo\Tool\Wrapper\AbstractWrapper;
/**
* Doctrine event adapter for ORM adapted
* for sluggable behavior
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class ORM extends BaseAdapterORM implements SluggableAdapter
{
/**
* {@inheritDoc}
*/
public function getSimilarSlugs($object, $meta, array $config, $slug)
{
$em = $this->getObjectManager();
$wrapped = AbstractWrapper::wrap($object, $em);
$qb = $em->createQueryBuilder();
$qb->select('rec.'.$config['slug'])
->from($config['useObjectClass'], 'rec')
->where($qb->expr()->like(
'rec.'.$config['slug'],
':slug')
)
;
$qb->setParameter('slug',$slug.'%');
// use the unique_base to restrict the uniqueness check
if ($config['unique'] && isset($config['unique_base'])) {
$ubase = $wrapped->getPropertyValue($config['unique_base']);
if (array_key_exists($config['unique_base'], $wrapped->getMetadata()->getAssociationMappings())) {
$mapping = $wrapped->getMetadata()->getAssociationMapping($config['unique_base']);
} else {
$mapping = false;
}
if (($ubase || $ubase === 0) && !$mapping) {
$qb->andWhere('rec.'.$config['unique_base'].' = :unique_base');
$qb->setParameter(':unique_base', $ubase);
} elseif ($ubase && $mapping && in_array($mapping['type'], array(ClassMetadataInfo::ONE_TO_ONE, ClassMetadataInfo::MANY_TO_ONE))) {
$mappedAlias = 'mapped_'.$config['unique_base'];
$wrappedUbase = AbstractWrapper::wrap($ubase, $em);
$qb->innerJoin('rec.'.$config['unique_base'], $mappedAlias);
foreach (array_keys($mapping['targetToSourceKeyColumns']) as $i => $mappedKey) {
$mappedProp = $wrappedUbase->getMetadata()->fieldNames[$mappedKey];
$qb->andWhere($qb->expr()->eq($mappedAlias.'.'.$mappedProp, ':assoc'.$i));
$qb->setParameter(':assoc'.$i, $wrappedUbase->getPropertyValue($mappedProp));
}
} else {
$qb->andWhere($qb->expr()->isNull('rec.'.$config['unique_base']));
}
}
// include identifiers
foreach ((array) $wrapped->getIdentifier(false) as $id => $value) {
if (!$meta->isIdentifier($config['slug'])) {
$namedId = str_replace('.', '_', $id);
$qb->andWhere($qb->expr()->neq('rec.'.$id, ':'.$namedId));
$qb->setParameter($namedId, $value, $meta->getTypeOfField($namedId));
}
}
$q = $qb->getQuery();
$q->setHydrationMode(Query::HYDRATE_ARRAY);
return $q->execute();
}
/**
* {@inheritDoc}
*/
public function replaceRelative($object, array $config, $target, $replacement)
{
$em = $this->getObjectManager();
$qb = $em->createQueryBuilder();
$qb->update($config['useObjectClass'], 'rec')
->set('rec.'.$config['slug'], $qb->expr()->concat(
$qb->expr()->literal($replacement),
$qb->expr()->substring('rec.'.$config['slug'], mb_strlen($target))
))
->where($qb->expr()->like(
'rec.'.$config['slug'],
$qb->expr()->literal($target.'%'))
)
;
// update in memory
$q = $qb->getQuery();
return $q->execute();
}
/**
* {@inheritDoc}
*/
public function replaceInverseRelative($object, array $config, $target, $replacement)
{
$em = $this->getObjectManager();
$qb = $em->createQueryBuilder();
$qb->update($config['useObjectClass'], 'rec')
->set('rec.'.$config['slug'], $qb->expr()->concat(
$qb->expr()->literal($target),
$qb->expr()->substring('rec.'.$config['slug'], mb_strlen($replacement)+1)
))
->where($qb->expr()->like('rec.'.$config['slug'], $qb->expr()->literal($replacement . '%')))
;
$q = $qb->getQuery();
return $q->execute();
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Gedmo\Sluggable\Mapping\Event;
use Gedmo\Mapping\Event\AdapterInterface;
/**
* Doctrine event adapter interface
* for Sluggable behavior
*
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
interface SluggableAdapter extends AdapterInterface
{
/**
* Loads the similar slugs
*
* @param object $object
* @param object $meta
* @param array $config
* @param string $slug
*
* @return array
*/
public function getSimilarSlugs($object, $meta, array $config, $slug);
/**
* Replace part of slug to all objects
* matching $target pattern
*
* @param object $object
* @param array $config
* @param string $target
* @param string $replacement
*
* @return integer
*/
public function replaceRelative($object, array $config, $target, $replacement);
/**
* Replace part of slug to all objects
* matching $target pattern and having $object
* related
*
* @param object $object
* @param array $config
* @param string $target
* @param string $replacement
*
* @return integer
*/
public function replaceInverseRelative($object, array $config, $target, $replacement);
}