Skip to content

Commit dc04599

Browse files
author
Robin Cawser
committed
Makes use of callbacks on Generators to define things like characters or prefixes
1 parent 2ffdb20 commit dc04599

7 files changed

Lines changed: 124 additions & 44 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### Composer ###
22
composer.phar
3+
composer.lock
34
vendor/
45
bin/
56

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace spec\Vivait\StringGeneratorBundle\EventListener;
4+
5+
use Doctrine\Common\Annotations\Reader;
6+
use PhpSpec\ObjectBehavior;
7+
use Prophecy\Argument;
8+
use Vivait\StringGeneratorBundle\Annotation\GeneratorAnnotation;
9+
use Vivait\StringGeneratorBundle\Generator\StringGenerator;
10+
use Vivait\StringGeneratorBundle\Registry\Registry;
11+
12+
class GeneratorListenerSpec extends ObjectBehavior
13+
{
14+
function it_is_initializable()
15+
{
16+
$this->shouldHaveType('Vivait\StringGeneratorBundle\EventListener\GeneratorListener');
17+
}
18+
19+
function let(Reader $reader, Registry $registry)
20+
{
21+
$this->beConstructedWith($reader, $registry);
22+
}
23+
24+
function it_performs_callbacks_on_the_generator(StringGenerator $generator, Entity $mockEntity)
25+
{
26+
$annotation = new GeneratorAnnotation([]);
27+
$annotation->callbacks = ['setChars' => 'abcdef'];
28+
$this->shouldNotThrow('\InvalidArgumentException')->duringPerformCallbacks($generator, $annotation, $mockEntity);
29+
30+
$annotation->callbacks = ['noMethod' => 'something'];
31+
$this->shouldThrow('\InvalidArgumentException')->duringPerformCallbacks($generator, $annotation, $mockEntity);
32+
}
33+
34+
function it_can_get_callback_values_from_annotated_object(StringGenerator $generator, Entity $mockEntity)
35+
{
36+
$annotation = new GeneratorAnnotation([]);
37+
$annotation->callbacks = ['setPrefix' => 'getPrefix'];
38+
39+
$mockEntity->getPrefix()->willReturn('VIVA_');
40+
$generator->setPrefix('VIVA_')->shouldBeCalled();
41+
$this->performCallbacks($generator, $annotation, $mockEntity);
42+
}
43+
}
44+
45+
class Entity
46+
{
47+
public function getPrefix()
48+
{
49+
50+
}
51+
}
52+

src/Vivait/StringGeneratorBundle/Annotation/GeneratorAnnotation.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,12 @@
1212
*/
1313
class GeneratorAnnotation extends Annotation
1414
{
15+
public $callbacks = [];
1516
/**
1617
* @var
1718
*/
1819
public $generator;
1920

20-
/**
21-
* @var string
22-
*/
23-
public $prefix;
24-
2521
/**
2622
* @var int
2723
*/
@@ -31,14 +27,4 @@ class GeneratorAnnotation extends Annotation
3127
* @var boolean
3228
*/
3329
public $unique = true;
34-
35-
/**
36-
* @var string
37-
*/
38-
public $separator = "-";
39-
40-
/**
41-
* @var string
42-
*/
43-
public $prefix_callback;
4430
}

src/Vivait/StringGeneratorBundle/DependencyInjection/Configuration.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ public function getConfigTreeBuilder()
1919
{
2020
$treeBuilder = new TreeBuilder();
2121
$rootNode = $treeBuilder->root('vivait_string_generator');
22+
2223
$rootNode
23-
->fixXmlConfig('notifier')
24+
->fixXmlConfig('generator')
2425
->children()
2526
->arrayNode('generators')
2627
->useAttributeAsKey('class')
27-
->prototype('scalar')
28-
->cannotBeEmpty()
28+
->prototype('scalar')->end()
2929
->end()
30-
->end()
31-
;
30+
->end();
31+
32+
3233

3334
return $treeBuilder;
3435
}

src/Vivait/StringGeneratorBundle/EventListener/GeneratorListener.php

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,56 +41,83 @@ public function prePersist(LifecycleEventArgs $args)
4141
$meta = $em->getClassMetadata(get_class($entity));
4242
$this->repo = $em->getRepository($meta->getName());
4343

44-
$obj = new \ReflectionObject($entity);
44+
$object = new \ReflectionObject($entity);
4545

46-
//Loop through each of entity's properties
47-
foreach ($obj->getProperties() as $property) {
48-
//Loop through the property's annotations
46+
foreach ($object->getProperties() as $property) {
4947
foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
5048

5149
if ($annotation instanceof GeneratorAnnotation) {
52-
if (method_exists($entity, $annotation->prefix_callback) && is_callable([$entity, $annotation->prefix_callback])) {
53-
$callback = $annotation->prefix_callback;
54-
$annotation->prefix = $entity->$callback();
55-
}
56-
57-
$id = $this->generateString(
58-
$property->name,
59-
$annotation
60-
);
61-
$meta->getReflectionProperty($property->name)->setValue($entity, $id);
50+
$string = $this->generateString($property->name, $annotation, $object);
51+
52+
$meta->getReflectionProperty($property->name)->setValue($entity, $string);
6253
}
6354
}
6455
}
6556
}
6657

6758
/**
6859
* @param $property
69-
* @param $annotation
60+
* @param GeneratorAnnotation $annotation
61+
* @param $object
7062
* @return string
7163
*/
72-
private function generateString($property, GeneratorAnnotation $annotation)
64+
private function generateString($property, GeneratorAnnotation $annotation, $object)
7365
{
66+
/** @var GeneratorInterface $generator */
7467
$generator = $this->registry->get($annotation->generator);
7568
$generator->setLength($annotation->length);
7669

77-
$str = $this->generator->generate();
78-
79-
if ($annotation->prefix) {
80-
$str = sprintf("%s%s%s", $annotation->prefix, $annotation->separator, $str);
70+
if(!empty($annotation->callbacks)){
71+
$this->performCallbacks($generator, $annotation, $object);
8172
}
8273

74+
$str = $generator->generate();
75+
8376
if (!$annotation->unique) {
8477
return $str;
8578
}
8679

8780

8881
if ($this->repo->findOneBy([$property => $str])) {
89-
return $this->generateString($property, $annotation);
82+
return $this->generateString($property, $annotation, $object);
9083
} else {
9184
return $str;
9285
}
9386

9487
}
9588

89+
/**
90+
* @param GeneratorInterface $generator
91+
* @param GeneratorAnnotation $annotation
92+
* @param $object
93+
*/
94+
public function performCallbacks(GeneratorInterface $generator, GeneratorAnnotation $annotation, $object)
95+
{
96+
foreach($annotation->callbacks as $callback => $value){
97+
if($this->isMethod($generator, $callback)){
98+
99+
if($this->isMethod($object, $value)){
100+
$value = $object->$value();
101+
}
102+
$generator->$callback($value);
103+
}
104+
else{
105+
throw new \InvalidArgumentException(sprintf(
106+
'Callback "%s" does not exist in class "%s"',
107+
$callback,
108+
get_class($generator))
109+
);
110+
}
111+
}
112+
}
113+
114+
/**
115+
* @param $class
116+
* @param $callback
117+
* @return bool
118+
*/
119+
private function isMethod($class, $callback)
120+
{
121+
return method_exists($class, $callback) && is_callable([$class, $callback]);
122+
}
96123
}

src/Vivait/StringGeneratorBundle/Generator/StringGenerator.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class StringGenerator implements GeneratorInterface
1616
* @var string
1717
*/
1818
private $chars = 'abcdefjhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345567890';
19+
private $prefix = '';
1920

2021
/**
2122
* @param string $chars
@@ -44,6 +45,11 @@ public function setLength($length)
4445
return $this;
4546
}
4647

48+
public function setPrefix($prefix)
49+
{
50+
$this->prefix = $prefix;
51+
}
52+
4753
/**
4854
* Creates a random string based on a length and alphabet
4955
*
@@ -58,6 +64,6 @@ public function generate()
5864
$str[] = $this->chars[$n];
5965
}
6066

61-
return implode($str);
67+
return $this->prefix . implode($str);
6268
}
6369
}

src/Vivait/StringGeneratorBundle/Resources/config/services.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ services:
22
vivait_generator.generator.listener:
33
class: Vivait\StringGeneratorBundle\EventListener\GeneratorListener
44
public: false
5-
arguments: ["@annotation_reader"]
5+
arguments: [@annotation_reader, @vivait_generator.registry]
66
tags:
77
- { name: doctrine.event_listener, event: prePersist }
88
vivait_generator.registry:
99
class: Vivait\StringGeneratorBundle\Registry\Registry
10-
arguments: [@service_container, []]
10+
arguments: [@service_container, []]
11+
12+
vivait_generator.generator.string:
13+
class: Vivait\StringGeneratorBundle\Generator\StringGenerator
14+
15+
vivait_generator.generator.secure_bytes:
16+
class: Vivait\StringGeneratorBundle\Generator\SecureBytesGenerator
17+
arguments: [@security.secure_random]

0 commit comments

Comments
 (0)