Skip to content

Commit

Permalink
Add autowiring
Browse files Browse the repository at this point in the history
  • Loading branch information
roukmoute committed Nov 1, 2016
1 parent 9ade3f7 commit 4691045
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 10 deletions.
57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ roukmoute_hashids:

# if set, will use only characters of alphabet string
alphabet: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"

# if set to true, guess automatically hashid
autowire: false
```

## Usage
Expand All @@ -73,7 +76,7 @@ $this->get('hashids')->encodeWithCustomHashLength($minHashLength, 1, 2, 3);
```

Hashids Converter
===============
=================

Converter Name: `hashids.converter`

Expand Down Expand Up @@ -107,5 +110,57 @@ public function getAction(User $user, Status $status)
}
```

Defining Hashid Automatically (Autowiring)
==========================================

Autowiring allows to guess hashid with minimal configuration.
It automatically resolves the variable in route.
The ParamConverter component will be able to automatically guess
the hashid when configuration has autowire to true.

```
roukmoute_hashids:
autowire: true
```

The autowiring subsystem will detect the hashid.

Base on the example above:

```php
/**
* @Route("/users/{hashid}")
* @ParamConverter("user", class="RoukmouteBundle\Entity\User", options={"id" = "hashid"})
*/
public function getAction(User $user)
{
}
```

Now you can do simply that:

```php
/**
* @Route("/users/{hashid}")
*/
public function getAction(User $user)
{
}
```

Or can directly use `id` now !

```php
/**
* @Route("/users/{id}")
*/
public function getAction(User $user)
{
}
```

As you can see, the autowiring feature reduces the amount of
configuration required to define a hashid.

[1]: https://github.com/ivanakimov/hashids.php
[2]: http://hashids.org/php/
1 change: 1 addition & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
>
<argument type="service" id="hashids"/>
<argument type="service" id="doctrine"/>
<argument>%hashids.autowire%</argument>
<tag name="request.param_converter" priority="1" converter="hashids.converter" />
</service>
</services>
Expand Down
10 changes: 7 additions & 3 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@ public function getConfigTreeBuilder()
->children()
->scalarNode('salt')
->defaultValue('')
->info('if set, the hashids will differ from everyone else\'s')
->info('if set, the hashids will differ from everyone else\'s.')
->end()
->integerNode('min_hash_length')
->info('if set, will generate minimum length for the id')
->info('if set, will generate minimum length for the id.')
->defaultValue(0)
->min(0)
->end()
->scalarNode('alphabet')
->info('if set, will use only characters of alphabet string')
->info('if set, will use only characters of alphabet string.')
->defaultValue('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890')
->end()
->booleanNode('autowire')
->info('if true, will try to detect the hashids when Doctrine was unable to guess Entity.')
->defaultFalse()
->end()
->end();

return $treeBuilder;
Expand Down
1 change: 1 addition & 0 deletions src/DependencyInjection/RoukmouteHashidsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('hashids.salt', $config['salt']);
$container->setParameter('hashids.min_hash_length', $config['min_hash_length']);
$container->setParameter('hashids.alphabet', $config['alphabet']);
$container->setParameter('hashids.autowire', $config['autowire']);
}
}
80 changes: 74 additions & 6 deletions src/ParamConverter/HashidsParamConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,24 @@
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\DoctrineParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class HashidsParamConverter extends DoctrineParamConverter implements ParamConverterInterface
{
/**
* @var Hashids
*/
protected $hashids;
/**
* @var bool
*/
private $autowire;

public function __construct(Hashids $hashids, ManagerRegistry $registry)
public function __construct(Hashids $hashids, ManagerRegistry $registry, $autowire)
{
parent::__construct($registry);
$this->hashids = $hashids;
$this->autowire = $autowire;
}

/**
Expand All @@ -26,32 +35,91 @@ public function __construct(Hashids $hashids, ManagerRegistry $registry)
*/
public function apply(Request $request, ParamConverter $configuration)
{
$options = $configuration->getOptions();
$exception = null;

if ($this->autowire) {
try {
return parent::apply($request, $configuration);
} catch (\Exception $exception) {
$name = $configuration->getName();
$options = $this->getOptions($configuration);

if ($exception instanceof NotFoundHttpException) {
$hashid = $this->getIdentifier($request, $options, $name);
} else {
$hashid = $this->getHashIdentifier($request, $options, $name);
}
}
} else {
$options = $configuration->getOptions();

if (!isset($options['id']) || mb_strtolower(mb_substr($options['id'], -6)) !== 'hashid') {
return false;
}

if (!isset($options['id']) || mb_strtolower(mb_substr($options['id'], -6)) !== 'hashid') {
return false;
$hashid = $request->attributes->get($options['id']);
}

$hashid = $request->attributes->get($options['id']);
return $this->decodeHashid($request, $configuration, $hashid, $exception);
}

/**
* @param Request $request
* @param ParamConverter $configuration
* @param $hashid
* @param \Exception|null $exception
*
* @return bool
* @throws \Exception
*/
private function decodeHashid(Request $request, ParamConverter $configuration, $hashid, \Exception $exception = null)
{
$options = $configuration->getOptions();
$decodeHashids = $this->hashids->decode($hashid);

if (!is_array($decodeHashids)
|| !isset($decodeHashids[0])
|| false === ($id = $decodeHashids[0])
|| false === is_int($id)
) {
if ($exception) {
throw $exception;
}
throw new \LogicException('Unable to guess hashid from the request information.');
}

$request->attributes->set('id', $id);
unset($options['id']);

$configuration->setOptions($options);
$configuration->setIsOptional(true);

parent::apply($request, $configuration);

$name = $configuration->getName();

if (!$request->attributes->get($name)) {
throw new \LogicException(sprintf('%s "%s" not found.', ucfirst($name), $hashid));
}

return true;
}

/**
* @param Request $request
* @param $options
* @param $name
*
* @return array|bool|mixed
*/
private function getHashIdentifier(Request $request, $options, $name)
{
$id = $this->getIdentifier($request, $options, $name);

if (!$id && $request->attributes->has('hashid')) {
return $request->attributes->get('hashid');
}

return $id;
}
}

0 comments on commit 4691045

Please sign in to comment.