diff --git a/doc/tokenizer.md b/doc/tokenizer.md new file mode 100644 index 0000000000..d2eb6f8fde --- /dev/null +++ b/doc/tokenizer.md @@ -0,0 +1,609 @@ +# Tokenizer behavior extension for Doctrine 2 + +**Tokenizer** behavior will automate the update of token field +on your Entities or Documents. It works through annotations and can update +fields on creation, update, property subset update, or even on specific property value change. + +Features: + +- Automatic predefined token field update on creation, update, property subset update, and even on record property changes +- ORM and ODM support using same listener +- Specific annotations for properties, and no interface required +- Can react to specific property or relation changes to specific value +- Can be nested with other behaviors +- Annotation, Yaml and Xml mapping support for extensions + +[blog_reference]: http://gediminasm.org/article/tokenizer-behavior-extension-for-doctrine-2 "Tokenizer extension for Doctrine 2 helps automate update of token" +[blog_test]: http://gediminasm.org/test "Test extensions on this blog" + +**Note:** + +- You can [test live][blog_test] on this blog +- Public [Timestampable repository](http://github.com/l3pp4rd/DoctrineExtensions "Tokenizer extension on Github") is available on github + +**Portability:** + +- **Tokenizer** is now available as [Bundle](http://github.com/stof/StofDoctrineExtensionsBundle) +ported to **Symfony2** by **Christophe Coevoet**, together with all other extensions + +This article will cover the basic installation and functionality of **Tokenizer** behavior + +Content: + +- [Including](#including-extension) the extension +- Entity [example](#entity-mapping) +- Document [example](#document-mapping) +- [Yaml](#yaml-mapping) mapping example +- [Xml](#xml-mapping) mapping example +- Advanced usage [examples](#advanced-examples) +- Using [Traits](#traits) + + + +## Setup and autoloading + +Read the [documentation](http://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/annotations.md#em-setup) +or check the [example code](http://github.com/l3pp4rd/DoctrineExtensions/tree/master/example) +on how to setup and use the extensions in most optimized way. + + + +## Tokenizer Entity example: + +### Tokenizer annotations: +- **@Gedmo\Mapping\Annotation\Tokenizer** this annotation tells that this column is Tokenizer +by default it updates this column on update. If column is not date, datetime or time +type it will trigger an exception. + +Available configuration options: + +- **on** - is main option and can be **create, update, change** this tells when it +should be updated +- **field** - only valid if **on="change"** is specified, tracks property or a list of properties for changes +- **value** - only valid if **on="change"** is specified and the tracked field is a single field (not an array), if the tracked field has this **value** + +**Note:** that Tokenizer interface is not necessary, except in cases where +you need to identify entity as being Token. The metadata is loaded only once then +cache is activated + +``` php +id; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getTitle() + { + return $this->title; + } + + public function setBody($body) + { + $this->body = $body; + } + + public function getBody() + { + return $this->body; + } + + public function getToken() + { + return $this->token; + } +} +``` + + + +## Tokenizer Document example: + +``` php +id; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getTitle() + { + return $this->title; + } + + public function setBody($body) + { + $this->body = $body; + } + + public function getBody() + { + return $this->body; + } + + public function getToken() + { + return $this->token; + } + +} +``` + +Now on update and creation these annotated fields will be automatically updated + + + +## Yaml mapping example: + +Yaml mapped Article: **/mapping/yaml/Entity.Article.dcm.yml** + +``` +--- +Entity\Article: + type: entity + table: articles + id: + id: + type: integer + generator: + strategy: AUTO + fields: + title: + type: string + length: 64 + token: + type: date + gedmo: + tokenizer: + on: create +``` + + + +## Xml mapping example + +``` xml + + + + + + + + + + + + + + + + + + +``` + + + +## Advanced examples: + +### Using dependency of property changes + +Add another entity which would represent Article Type: + +``` php +id; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getTitle() + { + return $this->title; + } +} +``` + +Now update the Article Entity to reflect published date on Type change: + +``` php +type = $type; + } + + public function getId() + { + return $this->id; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getTitle() + { + return $this->title; + } + + public function getCreated() + { + return $this->created; + } + + public function getUpdated() + { + return $this->updated; + } + + public function getPublished() + { + return $this->published; + } +} +``` + +Yaml mapped Article: **/mapping/yaml/Entity.Article.dcm.yml** + +``` +--- +Entity\Article: + type: entity + table: articles + id: + id: + type: integer + generator: + strategy: AUTO + fields: + title: + type: string + length: 64 + created: + type: date + gedmo: + timestampable: + on: create + updated: + type: datetime + gedmo: + timestampable: + on: update + published: + type: datetime + gedmo: + timestampable: + on: change + field: type.title + value: Published + manyToOne: + type: + targetEntity: Entity\Type + inversedBy: articles +``` + +Now few operations to get it all done: + +``` php +setTitle('My Article'); + +$em->persist($article); +$em->flush(); +// article: $created, $updated were set + +$type = new Type; +$type->setTitle('Published'); + +$article = $em->getRepository('Entity\Article')->findByTitle('My Article'); +$article->setType($type); + +$em->persist($article); +$em->persist($type); +$em->flush(); +// article: $published, $updated were set + +$article->getPublished()->format('Y-m-d'); // the date article type changed to published +``` + +Easy like that, any suggestions on improvements are very welcome + +### Creating a UTC DateTime type that stores your datetimes in UTC + +First, we define our custom data type (note the type name is datetime and the type extends DateTimeType which simply overrides the default Doctrine type): + +``` php +setTimeZone(self::$utc); + + return $value->format($platform->getDateTimeFormatString()); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + if (is_null(self::$utc)) { + self::$utc = new \DateTimeZone('UTC'); + } + + $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value, self::$utc); + + if (!$val) { + throw ConversionException::conversionFailed($value, $this->getName()); + } + + return $val; + } +} +``` + +Now in Symfony2, we register and override the **datetime** type. **WARNING:** this will override the **datetime** type for all your entities and for all entities in external bundles or extensions, so if you have some entities that require the standard **datetime** type from Doctrine, you must modify the above type and use a different name (such as **utcdatetime**). Additionally, you'll need to modify **Timestampable** so that it includes **utcdatetime** as a valid type. + +``` +doctrine: + dbal: + types: + datetime: Acme\DoctrineExtensions\DBAL\Types\UTCDateTimeType +``` + +And our Entity properties look as expected: + +``` php + + +## Traits + +You can use timestampable traits for quick **createdAt** **updatedAt** timestamp definitions +when using annotation mapping. + +**Note:** this feature is only available since php **5.4.0**. And you are not required +to use the Traits provided by extensions. + +``` php + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +final class Tokenizer extends Annotation +{ + /** @var string */ + public $on = 'update'; + /** @var string|array */ + public $field; + /** @var mixed */ + public $value; +} + diff --git a/lib/Gedmo/Tokenizer/Mapping/Driver/Annotation.php b/lib/Gedmo/Tokenizer/Mapping/Driver/Annotation.php new file mode 100644 index 0000000000..e740b430e7 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Driver/Annotation.php @@ -0,0 +1,77 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +class Annotation extends AbstractAnnotationDriver +{ + /** + * Annotation field is Tokenizer + */ + const TOKENIZER = 'Gedmo\\Mapping\\Annotation\\Tokenizer'; + + /** + * List of types which are valid for timestamp + * + * @var array + */ + protected $validTypes = array( + 'string', + ); + + /** + * {@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; + } + if ($tokenizer = $this->reader->getPropertyAnnotation($property, self::TOKENIZER)) { + $field = $property->getName(); + if (!$meta->hasField($field)) { + throw new InvalidMappingException("Unable to find timestampable [{$field}] as mapped property in entity - {$meta->name}"); + } + if (!$this->isValidField($meta, $field)) { + throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'date', 'datetime' or 'time' in class - {$meta->name}"); + } + if (!in_array($tokenizer->on, array('update', 'create', 'change'))) { + throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->name}"); + } + if ($tokenizer->on == 'change') { + if (!isset($tokenizer->field)) { + throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->name}"); + } + if (is_array($tokenizer->field) && isset($tokenizer->value)) { + throw new InvalidMappingException("Timestampable extension does not support multiple value changeset detection yet."); + } + $field = array( + 'field' => $field, + 'trackedField' => $tokenizer->field, + 'value' => $tokenizer->value, + ); + } + // properties are unique and mapper checks that, no risk here + $config[$tokenizer->on][] = $field; + } + } + } +} diff --git a/lib/Gedmo/Tokenizer/Mapping/Driver/Xml.php b/lib/Gedmo/Tokenizer/Mapping/Driver/Xml.php new file mode 100644 index 0000000000..1b459eafe5 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Driver/Xml.php @@ -0,0 +1,93 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +class Xml extends BaseXml +{ + + /** + * List of types which are valid for timestamp + * + * @var array + */ + private $validTypes = array( + 'string', + ); + + /** + * {@inheritDoc} + */ + public function readExtendedMetadata($meta, array &$config) + { + /** + * @var \SimpleXmlElement $mapping + */ + $mapping = $this->_getMapping($meta->name); + + if (isset($mapping->field)) { + /** + * @var \SimpleXmlElement $fieldMapping + */ + foreach ($mapping->field as $fieldMapping) { + $fieldMappingDoctrine = $fieldMapping; + $fieldMapping = $fieldMapping->children(self::GEDMO_NAMESPACE_URI); + if (isset($fieldMapping->timestampable)) { + /** + * @var \SimpleXmlElement $data + */ + $data = $fieldMapping->timestampable; + + $field = $this->_getAttribute($fieldMappingDoctrine, 'name'); + if (!$this->isValidField($meta, $field)) { + throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'date', 'datetime' or 'time' in class - {$meta->name}"); + } + if (!$this->_isAttributeSet($data, 'on') || !in_array($this->_getAttribute($data, 'on'), array('update', 'create', 'change'))) { + throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->name}"); + } + + if ($this->_getAttribute($data, 'on') == 'change') { + if (!$this->_isAttributeSet($data, 'field')) { + throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->name}"); + } + $trackedFieldAttribute = $this->_getAttribute($data, 'field'); + $valueAttribute = $this->_isAttributeSet($data, 'value') ? $this->_getAttribute($data, 'value' ) : null; + if (is_array($trackedFieldAttribute) && null !== $valueAttribute) { + throw new InvalidMappingException("Timestampable extension does not support multiple value changeset detection yet."); + } + $field = array( + 'field' => $field, + 'trackedField' => $trackedFieldAttribute, + 'value' => $valueAttribute, + ); + } + $config[$this->_getAttribute($data, 'on')][] = $field; + } + } + } + } + + /** + * Checks if $field type is valid + * + * @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); + } +} diff --git a/lib/Gedmo/Tokenizer/Mapping/Driver/Yaml.php b/lib/Gedmo/Tokenizer/Mapping/Driver/Yaml.php new file mode 100644 index 0000000000..a16a7a1890 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Driver/Yaml.php @@ -0,0 +1,94 @@ + + * @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 timestamp + * + * @var array + */ + private $validTypes = array( + 'string', + ); + + /** + * {@inheritDoc} + */ + public function readExtendedMetadata($meta, array &$config) + { + $mapping = $this->_getMapping($meta->name); + + if (isset($mapping['fields'])) { + foreach ($mapping['fields'] as $field => $fieldMapping) { + if (isset($fieldMapping['gedmo']['timestampable'])) { + $mappingProperty = $fieldMapping['gedmo']['timestampable']; + if (!$this->isValidField($meta, $field)) { + throw new InvalidMappingException("Field - [{$field}] type is not valid and must be 'date', 'datetime' or 'time' in class - {$meta->name}"); + } + if (!isset($mappingProperty['on']) || !in_array($mappingProperty['on'], array('update', 'create', 'change'))) { + throw new InvalidMappingException("Field - [{$field}] trigger 'on' is not one of [update, create, change] in class - {$meta->name}"); + } + + if ($mappingProperty['on'] == 'change') { + if (!isset($mappingProperty['field'])) { + throw new InvalidMappingException("Missing parameters on property - {$field}, field must be set on [change] trigger in class - {$meta->name}"); + } + $trackedFieldAttribute = $mappingProperty['field']; + $valueAttribute = isset($mappingProperty['value']) ? $mappingProperty['value'] : null; + if (is_array($trackedFieldAttribute) && null !== $valueAttribute) { + throw new InvalidMappingException("Timestampable extension does not support multiple value changeset detection yet."); + } + $field = array( + 'field' => $field, + 'trackedField' => $trackedFieldAttribute, + 'value' => $valueAttribute, + ); + } + $config[$mappingProperty['on']][] = $field; + } + } + } + } + + /** + * {@inheritDoc} + */ + protected function _loadMappingFile($file) + { + return \Symfony\Component\Yaml\Yaml::parse($file); + } + + /** + * Checks if $field type is valid + * + * @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); + } +} diff --git a/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ODM.php b/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ODM.php new file mode 100644 index 0000000000..65a02ae502 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ODM.php @@ -0,0 +1,31 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +final class ODM extends BaseAdapterODM implements TokenizerAdapter +{ + /** + * {@inheritDoc} + */ + public function getDateValue($meta, $field) + { + $mapping = $meta->getFieldMapping($field); + if (isset($mapping['type']) && $mapping['type'] === 'string') { + $date = new \DateTime(); + $token =base_convert(sha1(uniqid(mt_rand(1, 999) . $date->format('Y-m-d H:i:s'), true)), 16, 36); + + return $token; + } + return null; + } +} \ No newline at end of file diff --git a/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ORM.php b/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ORM.php new file mode 100644 index 0000000000..042b9b4505 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Event/Adapter/ORM.php @@ -0,0 +1,31 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +final class ORM extends BaseAdapterORM implements TokenizerAdapter +{ + /** + * {@inheritDoc} + */ + public function getDateValue($meta, $field) + { + $mapping = $meta->getFieldMapping($field); + if (isset($mapping['type']) && $mapping['type'] === 'string') { + $date = new \DateTime(); + $token =base_convert(sha1(uniqid(mt_rand(1, 999) . $date->format('Y-m-d H:i:s'), true)), 16, 36); + + return $token; + } + return null; + } +} \ No newline at end of file diff --git a/lib/Gedmo/Tokenizer/Mapping/Event/TokenizerAdapter.php b/lib/Gedmo/Tokenizer/Mapping/Event/TokenizerAdapter.php new file mode 100644 index 0000000000..66aa112aaa --- /dev/null +++ b/lib/Gedmo/Tokenizer/Mapping/Event/TokenizerAdapter.php @@ -0,0 +1,24 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +interface TokenizerAdapter extends AdapterInterface +{ + /** + * Get the date value + * + * @param object $meta + * @param string $field + * @return mixed + */ + function getDateValue($meta, $field); +} \ No newline at end of file diff --git a/lib/Gedmo/Tokenizer/Tokenizer.php b/lib/Gedmo/Tokenizer/Tokenizer.php new file mode 100644 index 0000000000..ae10baad12 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Tokenizer.php @@ -0,0 +1,50 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +interface Tokenizer +{ + // Tokenizer expects annotations on properties + + /** + * @gedmo:Tokenizer(on="create") + * token which should be updated on insert only + */ + + /** + * @gedmo:Tokenizer(on="update") + * token which should be updated on update and insert + */ + + /** + * @gedmo:Tokenizer(on="change", field="field", value="value") + * token which should be updated on changed "property" + * value and become equal to given "value" + */ + + /** + * @gedmo:Tokenizer(on="change", field="field") + * token which should be updated on changed "property" + */ + + /** + * @gedmo:Tokenizer(on="change", fields={"field1", "field2"}) + * token which should be updated if at least one of the given fields changed + */ + + /** + * example + * + * @gedmo:Tokenizer(on="create") + * @Column(type="string") + * $token + */ +} \ No newline at end of file diff --git a/lib/Gedmo/Tokenizer/TokenizerListener.php b/lib/Gedmo/Tokenizer/TokenizerListener.php new file mode 100644 index 0000000000..34c440871a --- /dev/null +++ b/lib/Gedmo/Tokenizer/TokenizerListener.php @@ -0,0 +1,191 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +class TokenizerListener extends MappedEventSubscriber +{ + /** + * Specifies the list of events to listen + * + * @return array + */ + public function getSubscribedEvents() + { + return array( + 'prePersist', + 'onFlush', + 'loadClassMetadata' + ); + } + + /** + * Maps additional metadata for the Entity + * + * @param EventArgs $eventArgs + * @return void + */ + public function loadClassMetadata(EventArgs $eventArgs) + { + $ea = $this->getEventAdapter($eventArgs); + $this->loadMetadataForObjectClass($ea->getObjectManager(), $eventArgs->getClassMetadata()); + } + + /** + * Looks for Tokenizer objects being updated + * to update modification date + * + * @param EventArgs $args + * @throws \Gedmo\Exception\UnexpectedValueException + * @return void + */ + public function onFlush(EventArgs $args) + { + $ea = $this->getEventAdapter($args); + $om = $ea->getObjectManager(); + $uow = $om->getUnitOfWork(); + // check all scheduled updates + foreach ($ea->getScheduledObjectUpdates($uow) as $object) { + $meta = $om->getClassMetadata(get_class($object)); + if ($config = $this->getConfiguration($om, $meta->name)) { + $changeSet = $ea->getObjectChangeSet($uow, $object); + $needChanges = false; + + if (isset($config['update'])) { + foreach ($config['update'] as $field) { + if (!isset($changeSet[$field])) { // let manual values + $needChanges = true; + $this->updateField($object, $ea, $meta, $field); + + } + } + } + + if (isset($config['change'])) { + foreach ($config['change'] as $options) { + if (isset($changeSet[$options['field']])) { + continue; // value was set manually + } + + if (!is_array($options['trackedField'])) { + $singleField = true; + $trackedFields = array($options['trackedField']); + } else { + $singleField = false; + $trackedFields = $options['trackedField']; + } + + foreach ($trackedFields as $tracked) { + $trackedChild = null; + $parts = explode('.', $tracked); + if (isset($parts[1])) { + $tracked = $parts[0]; + $trackedChild = $parts[1]; + } + + if (isset($changeSet[$tracked])) { + $changes = $changeSet[$tracked]; + if (isset($trackedChild)) { + $changingObject = $changes[1]; + if (!is_object($changingObject)) { + throw new UnexpectedValueException( + "Field - [{$field}] is expected to be object in class - {$meta->name}" + ); + } + $objectMeta = $om->getClassMetadata(get_class($changingObject)); + $om->initializeObject($changingObject); + $value = $objectMeta->getReflectionProperty($trackedChild)->getValue($changingObject); + } else { + $value = $changes[1]; + } + + if (($singleField && in_array($value, (array)$options['value'])) || $options['value'] === null) { + $needChanges = true; + $this->updateField($object, $ea, $meta, $options['field']); + } + } + } + } + } + + if ($needChanges) { + $ea->recomputeSingleObjectChangeSet($uow, $meta, $object); + } + } + } + } + + /** + * Checks for persisted Timestampable objects + * to update creation and modification dates + * + * @param EventArgs $args + * @return void + */ + public function prePersist(EventArgs $args) + { + $ea = $this->getEventAdapter($args); + $om = $ea->getObjectManager(); + $object = $ea->getObject(); + + $meta = $om->getClassMetadata(get_class($object)); + + if ($config = $this->getConfiguration($om, $meta->getName())) { + + if (isset($config['update'])) { + foreach ($config['update'] as $field) { + if ($meta->getReflectionProperty($field)->getValue($object) === null) { // let manual values + $this->updateField($object, $ea, $meta, $field); + } + } + } + + if (isset($config['create'])) { + foreach ($config['create'] as $field) { + if ($meta->getReflectionProperty($field)->getValue($object) === null) { // let manual values + $this->updateField($object, $ea, $meta, $field); + } + } + } + } + } + + /** + * {@inheritDoc} + */ + protected function getNamespace() + { + return __NAMESPACE__; + } + + /** + * Updates a field + * + * @param $object + * @param $ea + * @param $meta + * @param $field + */ + protected function updateField($object, $ea, $meta, $field) + { + $property = $meta->getReflectionProperty($field); + $oldValue = $property->getValue($object); + $newValue = $ea->getDateValue($meta, $field); + $property->setValue($object, $newValue); + if ($object instanceof NotifyPropertyChanged) { + $uow = $ea->getObjectManager()->getUnitOfWork(); + $uow->propertyChanged($object, $field, $oldValue, $newValue); + } + } +} diff --git a/lib/Gedmo/Tokenizer/Traits/TokenizerDocument.php b/lib/Gedmo/Tokenizer/Traits/TokenizerDocument.php new file mode 100644 index 0000000000..56a3932aeb --- /dev/null +++ b/lib/Gedmo/Tokenizer/Traits/TokenizerDocument.php @@ -0,0 +1,42 @@ += 5.4 + * + * @author Ceif Khedhiri + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +trait TokenizerDocument +{ + /** + * @var \DateTime + * @Gedmo\Tokenizer(on="create") + * @ODM\String + */ + private $token; + + /** + * Sets token. + * + * @param $token + * @return $this + */ + public function setToken($token) + { + $this->token = $token; + + return $this; + } + + /** + * Returns token. + * + * @return token + */ + public function getToken() + { + return $this->token; + } +} diff --git a/lib/Gedmo/Tokenizer/Traits/TokenizerEntity.php b/lib/Gedmo/Tokenizer/Traits/TokenizerEntity.php new file mode 100644 index 0000000000..cdbd8acb12 --- /dev/null +++ b/lib/Gedmo/Tokenizer/Traits/TokenizerEntity.php @@ -0,0 +1,43 @@ += 5.4 + * + * @author Ceif Khedhiri + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +trait TokenizerEntity +{ + /** + * @var token + * @Gedmo\Tokenizer(on="create") + * @ORM\Column(type="string") + */ + protected $token; + + /** + * Sets token. + * + * @param $token + * @return $this + */ + public function setToken( $token) + { + $this->token = $token; + + return $this; + } + + /** + * Returns token. + * + * @return token + */ + public function getToken() + { + return $this->token; + } + +}