Thursday, February 11, 2016

Access static methods/properties from Twig

Classic stuff we need while using Twig : access static properties or call static methods of any class.


Reflection Extension

Downloadable from my Github repository

namespace SiteBundle\Twig\Extension;

class Reflection extends \Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            new \Twig_SimpleFunction('call_static', [$this, 'callStaticMethod']),
            new \Twig_SimpleFunction('get_static', [$this, 'getStaticProperty']),
        );
    }

    public function callStaticMethod($class, $method, array $args = [])
    {
        $refl = new \reflectionClass($class);

        // Check that method is static AND public
        if ($refl->hasMethod($method) && $refl->getMethod($method)->isStatic() && $refl->getMethod($method)->isPublic()) {
            return call_user_func_array($class.'::'.$method, $args);
        }

        throw new \RuntimeException(sprintf('Invalid static method call for class %s and method %s', $class, $method));
    }

    public function getStaticProperty($class, $property)
    {
        $refl = new \reflectionClass($class);

        // Check that property is static AND public
        if ($refl->hasProperty($property) && $refl->getProperty($property)->isStatic() && $refl->getProperty($property)->isPublic()) {
            return $refl->getProperty($property)->getValue();
        }

        throw new \RuntimeException(sprintf('Invalid static property get for class %s and property %s', $class, $property));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'reflection';
    }
}

Twig extension definition

services:
    site.twig.reflection_extension:
        class: SiteBundle\Twig\Extension\Reflection
        tags:
            - { name: twig.extension }

Friday, January 30, 2015

TwigFiddle

A short post to promote a new tool developed by my friend Alain Tiemblo : TwigFiddle. You can now test your templates, macros, and share your Twig code examples with this tool.

This is really useful when you post or answer a question about a Twig issue on Stackoverflow (or any other dev forum).

So test it and make feedback if you discover an issue or just have any suggestion...

twigfiddle.com



About Alain Tiemblo :

profile for Alain Tiemblo at Stack Overflow, Q&A for professional and enthusiast programmers

Friday, October 10, 2014

Redirection after registration

Symfony Security bundle provides everything to deal with redirections after login. The most used is based on referer as many pages may require an authentication, and this way you just redirect to the pages that asked for identification. But what happens when user has no account, he needs to register and create its account. Here is a proper way to achieve redirection after registration, dealing with multiple firewalls sharing a common context

This solution implies that all your firewalls are named like {name}_area.

 
class RegistrationController
{

    protected function getFirewallCallingForAuthentication()
    {
        $session = $this->get('session');

        $firewall = null;

        $securityKeys = array_filter(array_keys($session->all()), function ($key) {
            return preg_match('/^_security\.[\w]+_area\.target_path$/', $key);
        });
        $securityKey = empty($securityKeys) ? null : end($securityKeys);

        if ($securityKey) {
            $matches = [];
            $match = preg_match('/^_security\.([\w]+_area)\.target_path$/', $securityKey, $matches);

            if (isset($matches[1])) {
                $firewall = $matches[1];
            }
        }

        return $firewall;
    }

    // ...

    public function registrationAction()
    {

        // Get firewall name
        $firewallCallingForAuth = $this->getFirewallCallingForAuthentication();

        // ... prepare form ...

        $form->handleRequest($request);

        if ($form->isValid()) {

            // ... process registration, account creation, flash message, etc ...

            // Programmatically log user
            $token = new UsernamePasswordToken($user, null, $firewallCallingForAuth, $user->getRoles());
            $this->get('security.context')->setToken($token);

            // Redirects to the last _security.{firewall}.target_path found in session
            //  (last attempt of visiting a page protected by firewall requiring authentication)
            if (isset($firewallCallingForAuth)) {
                $redirectUrl = $session->get('_security.' . $firewallCallingForAuth . '.target_path');
                return $this->redirect($redirectUrl);
            } else {
                return $this->redirect($this->generateUrl('route_to_account_index'));
            }
        }

        // ... return Response

    }
}