Welcome to Abdul Malik Ikhsan's Blog

Testing “expects($this->any())” with Prophecy with Spying

Posted in Tutorial PHP by samsonasik on September 27, 2015

Testing method call from Collaborator that may be 0 or any other count with phpunit Framework test case can be done with expects($this->any()) from mock object. If we are using Prophecy for mocking tools, it can be done with spying.
However, the spying itself need checks whenever method is called or not. We need findProphecyMethodCalls() call againsts ObjectProphecy for that.

For example, we have a class with collaborator like the following:

namespace App;

class Awesome
{
    private $awesomeDependency;

    public function __construct(AwesomeDependency $awesomeDependency)
    {
        $this->awesomeDependency = $awesomeDependency;
    }

    public function process($data)
    {
        $rand = rand(1, 2);
        if ($rand === 1) {
            return $this->awesomeDependency->process($data);
        }
        return $data;
    }
}

The rand() usage is just a sample, in real app, we may have a heavy logic and it may fall to not call the collaborator.

The tests can be done like this:

namespace AppTest;

use App\Awesome;
use App\AwesomeDependency;
use PHPUnit_Framework_TestCase;
use Prophecy\Argument;
use Prophecy\Argument\ArgumentsWildcard;

class AwesomeTest extends PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        $this->awesomeDependency = $this->prophesize(AwesomeDependency::class);
        $this->awesome     = new Awesome($this->awesomeDependency->reveal());
    }

    public function testProcess()
    {
        $data = [
            'foo' => 'abcdef',
        ];

        // make \Prophecy\MethodProphecy instance
        $methodProphecy = $this->awesomeDependency
                               ->process(Argument::exact($data));
        
        // call method from actual instance
        $this->awesome->process($data);

        $calls = $this->awesomeDependency->findProphecyMethodCalls(
            'process',
            new ArgumentsWildcard([$data])
        );
        $count = count($calls);
        
        // assert how many times it called 
        $methodProphecy->shouldBeCalledTimes($count);
        if ($count) {
            // echoing just to prove
            echo 'Method from collaborator has been called';
            $methodProphecy->shouldHaveBeenCalled();
        } else {
            // echoing just to prove
            echo 'Method from collaborator has not been called';
            $methodProphecy->shouldNotHaveBeenCalled();
        }
    }
}

Of course, it may be can’t be called ‘expecting’ before for something has done, it may be can be called as ‘recording’ what already happen, but by this usage, we can prove if it actually called in actual code.

ZendExpressive: On Callable $next, and middleware_pipeline

Posted in Tutorial PHP, Zend Framework by samsonasik on September 20, 2015

In ZendExpressive, middleware_pipeline is a config that can be used to seed pre- and/or post-routing middleware. There are two keys inside it: pre_routing and post_routing.
Each of them has different purpose, pre_routing means the middleware registered under it will always be pipe()‘d before routing middleware, and for post_routing, they will be pipe()‘d afterwards.

If we create middlewares on them, we may need a call $next that on 3rd parameter in __invoke() method in its middlewares or middlewares that uses them as “next” middlewares. The code may be like this:

public function __invoke($request, $response, $next = null)
{
    // do something with request or response here
    return $next($request, $response);
}

$next will bring current $request and $response which may be modified before filled.

Ok, Let’s say we need an authorization middleware that pipe()‘d early, that means, we need a pre_routing:

class AuthorizationAction {

    public function __invoke($request, $response, $next = null)
    {
        // here, for example: check path and session exists
        // and handle with return response early or
        // continue to routing middleware
        return $next($request, $response);
    }

}

We can do something like this:

class AuthorizationAction {
  public function __construct($session) 
  { /** **/ }
    
  public function __invoke($request, $response, $next = null)
  {
    $path         = $request->getUri()->getPath();
    $sesionExists = $this->session->offsetExists('storage');

    // redirect to login page
    // when path = '/admin' and  
    // doesn't has session 
    if ($path === '/admin' && ! $sesionExists) {
        return new RedirectResponse('/auth');
    }

    if ($path === '/admin' && $sesionExists) {
        // check if session storage value !== 'admin'
        // then return early with status = 403
        $storageValue = $this->session->offsetGet('storage');
        if ($storageValue !== 'admin') {
            $response = $response->withStatus(403);
            $response->write('Forbidden');

            return $response;
        }
    }

    // if everything ok, continue
    return $next($request, $response);
  }
}

We then can register in our 'middleware_pipeline' config:

'middleware_pipeline' => [
    'pre_routing' => [
        [
            'middleware' => 'App\Action\AuthorizationAction',
        ],
    ],
    'post_routing' => [
        // ...
    ],
],

For example, we have routed middleware:

'routes' => [
    [
        'name' => 'funny',
        'path' => '/funny',
        'middleware' => App\Action\FunnyPageAction::class,
        'allowed_methods' => ['GET'],
    ],
    [
        'name' => 'admin',
        'path' => '/admin',
        'middleware' => App\Action\AdminPageAction::class,
        'allowed_methods' => ['GET'],
    ],
],

The AuthorizationAction middleware above will be pipe()‘d before middleware that registered in routes when specified middleware with its route match called.

So, how about post_routing ? We can call middleware registered in it, only if desired, that means, only if $next called in middleware that uses that. For example, we have a SugarAction middleware that change response header that will be placed in post_routing:

class SugarAction {

  public function __construct(RouterInterface $router)
  { $this->router = $router;}

  public function __invoke($request, $response, $next = null)
  {
     if (! $this->router->match($request)->isFailure()) {
         $response = $response->withHeader('X-Powered-By', 'JAVA');
     }
     return $next($request, $response);
  }
}

For note: As post_routing, because if the route is not match, the middleware above will be fall called, and withHeader() actually create new Response instance, we need to check whenever route match is not failure.

We then can register in our ‘middleware_pipeline’ config:

'middleware_pipeline' => [
    'pre_routing' => [
        [
            'middleware' => 'App\Action\AuthorizationAction',
        ],
    ],
    'post_routing' => [
        [
            'middleware' => 'App\Action\SugarAction',
        ],
    ],
],

and we have a /funny that uses that, so we can call $next:

class FunnyAction { 
  public function __invoke($request, $response, $next = null) {
    $response =  $response->write(
        $this->template->render('app::funny-page')
    );
    return $next($request, $response);
  }
}

If we check the header ( for example with Firebug or RestClient), and we can see the header ‘X-Powered-By’ changed. If we have a “not funny page”, and don’t want to modify header, then we can just not use $next.

Using Router match Check and Diactoros’s RedirectResponse in Zend\Expressive

Posted in Tutorial PHP, Zend Framework by samsonasik on September 17, 2015

If we use Zend\Expressive middleware, and want to handle redirection using Diactoros’s RedirectResponse, we may need to check whenever the Uri that we want to redirect is a valid and match against registered Router, if not valid, then back to home/other handling. Zend\Expressive gives us a choice to use ZF2 Router, Aura Router, or FastRoute. They have a way to check Uri is on registered Router, and they return different value when not valid (null for ZF2 Router, false for Aura Router, and FastRoute check with Dispatcher FOUND and NOT_FOUND constants). Zend\Expressive facilitating it by provide Router ‘adapter’ for each of them, and they have match method that return RouteResult instance as Value Object. They RouteResult has a $success property that will be setted as false when not match, and true when matched via following functions:

namespace Zend\Expressive\Router;

class RouteResult
{
    // (new self())->success = true;
    public static function fromRouteMatch($name, $middleware, array $params){}
    // (new self())->success = false;
    public static function fromRouteFailure($methods = null){} 
}

We have another methods to check $success property that have setted:

namespace Zend\Expressive\Router;

class RouteResult
{
    // return $this->success
    public static function isSuccess(){}
    // return (! $this->success);
    public static function isFailure(){} 
}

We can use one of the methods above to check $success property value.

Ok, let’s create an example! For example, we have a SamplePageAction as middleware:

namespace App\Action;

use Zend\Diactoros\Response\RedirectResponse;

class SamplePageAction
{
    public function __invoke($request, $response, $next = null)
    {
        return new RedirectResponse('/a-sample-uri');
    }
}

We need to ‘validate’ if ‘/a-sample-uri’ is a valid uri for our Zend\Expressive application. We can do:

  1. Inject the middleware with Zend\Expressive\Router\RouterInterface
    class SamplePageAction
    {
        private $router;
    
        public function __construct(RouterInterface $router)
        {
            $this->router = $router;
        }
    
        public function __invoke($request, $response, $next = null)
        { /** **/ }
    }
    

  2. Make factory for it

    namespace App\Action;
    
    use Interop\Container\ContainerInterface;
    use Zend\Expressive\Router\RouterInterface;
    
    class SamplePageActionFactory
    {
        public function __invoke(ContainerInterface $container)
        {
            $router   = $container->get(RouterInterface::class);
            return new SamplePageAction($router);
        }
    }
    

  3. If we are using Zend\ServiceManager as the Container, we can register inside our config at ‘factories’

    use App\Action\SamplePageAction;
    use App\Action\SamplePageActionFactory;
    
    //...
            'factories' => [
                SamplePageAction::class => SamplePageActionFactory::class,
            ]
    // ...
    

    if we use other container, we can follow the docs.

  4. Now, we can use it to check and handle route match the request uri

    class SamplePageAction
    {
        public function __construct(RouterInterface $router){ /** **/ }
        public function __invoke($request, $response, $next = null)
        {
            $uri         =  '/a-sample-uri';
    
            // save current path as variable
            $currentPath = $request->getUri()->getPath();
            // set request with Uri
            $request     = $request->withUri(new Uri($uri));
    
            // check match
            $match = $this->router->match($request);
            // check failure and if request uri path is not same with current
            // path to avoid infinite redirection 
            if (! $match->isFailure() 
                && $currentPath !== $request->getUri()->getPath()
            ) {   
                return new RedirectResponse($uri);
            }
    
            // redirect to uri with router name = home 
            // when router is not match  
            return new RedirectResponse($this->router->generateUri('home'));
        }
    }
    

    In real world app, the redirect check usually come from a variable, for example, a Query param(for ex: ‘redirect’ query param). For that case, we can do check like this:

    class SamplePageAction
    {
        public function __construct(RouterInterface $router){ /** **/ }
        public function __invoke($request, $response, $next = null)
        {
            // get arrays of Query params
            $queryParams = $request->getQueryParams();
            
            // check if 'redirect' Query param is set
            // and not equals than ''
            if (isset($queryParams['redirect']) 
                && trim($queryParams['redirect']) !== ''
            ) {  
                // save current path as variable
                $currentPath = $request->getUri()->getPath();
                // set request with Uri
                $request = $request->withUri(new Uri($queryParams['redirect']));
                 
                 // check match
                 $match = $this->router->match($request);
                 // check failure and if request uri path is not same with
                 // current path to avoid infinite redirection 
                 if (! $match->isFailure() 
                     && $currentPath !== $request->getUri()->getPath()
                 ) {
                     return new RedirectResponse($queryParams['redirect']);
                 }
            }
    
            return new RedirectResponse($this->router->generateUri('home'));
        }
    }
    

Update: There is a package for that that I created, go grab it here: https://github.com/samsonasik/ExpressiveRedirectHandler 😉

Practical GIT (4) : Rebasing Conflicted “task” branch against primary branch

Posted in GIT by samsonasik on September 16, 2015

git-logoWhen we work on our “task” branch that based on our primary branch, We may have overlapped commits when our team have update the primary branch.
Many people just use “merge” the primary branch into their “task” branch, but it will make extra commit that contains actually same changes, that may a project history not clean, and make hard to review (for example: in case we use merge or pull request). What we need to do is rebase instead. Actually, the merge should only happen when you need to apply your “task” branch into your primary branch.

Rebase will synchronize the commits and put our changes in top of commits. Let’s see what the process step by step. For example, you work with git flow, you’re now on “feature/xzy” against develop.

$ git flow feature start xzy
# can be replaced with 
# git checkout -b feature/xzy develop

And we are working on a big task. On the middle of the day, someone or some people on the team make a hotfix that make a commit to master and develop, that make your branch is outdate, and has some conflict.
What you can do to synchronize is by using rebase with steps:

1. Checkout primary branch (at this case: develop), pull latest

$ git checkout develop
$ git pull origin develop

2. Back to our feature branch and rebase

$ git checkout feature/xzy
$ git rebase develop

From now on, if we see conflict, and get error:

You are currently rebasing.
  (fix conflicts and then run "git rebase --continue")

We need to see the files that contains conflicts that may contains:

<<<<<<< HEAD

, and fix them. After that, we can close the editor. Don’t make a commit after fixing conflicts in the files!

3. Add resolved files and you can continue

$ git add .
$ git rebase --continue

4. Last, if we publish the “feature/xzy” branch into our origin/feature/xyz, we need to push –force because the commits has been rewritten:

$ git push --force origin feature/xzy

If everything ok, then we are now synchronized. That’s it 😉

Getting Closer with Penny – A PHP Framework

Posted in Tutorial PHP by samsonasik on September 8, 2015

“One penny is valueless but a lot of pennies build an empire.”. This is a tagline that we can see at the Penny repository. Gianluca Arbezzano, A PHP developer that created it focused on creating interoperability concept. It uses great PHP components in the Framework.

There are PHP components that used in Penny Framework:
* nikic/fast-route: handle routing
* php-di/php-di: act as service container
* zendframework/zend-diactoros: a PHP package implements psr-7
* zendframework/zend-eventmanager: handle application event
* doctrine/annotations:for annotation usage
* zendframework/zend-stdlib: used to manage configs.

Penny ships Skeleton Application to get started, we can follow the installation steps, and we can see the welcome page.

The Penny’s Skeleton page brings Plates to manage template, so you don’t need to worry about adding manually. The template configureable in the skeleton’s config:

// config/di.php
return [
    'template' => \DI\object(\League\Plates\Engine::class)->constructor('./app/view/'),
    'router' => /* */
];

And about the routing, it brings the basic FastRoute‘s config:

// config/di.php
return [
    'template' => /* */
    'router' => function () {
        return \FastRoute\simpleDispatcher(function (\FastRoute\RouteCollector $r) {
            $r->addRoute('GET', '/', ['ClassicApp\Controller\IndexController', 'index']);
        });
    },
];

In ClassicApp\Controller\IndexController::index, we have Stream object that write with rendered template:

// app/Controller/IndexController.php
    public function index($request, $response)
    {
        $response->getBody()->write($this->template->render('index', [
            'title' => 'Home Page',
        ]));
        return $response;
    }

The template property in the controller above injected via @Inject annotation:

// app/Controller/IndexController.php
class IndexController {
    /**
     * @Inject("di")
     */
    private $di;

    /**
     * @Inject("template")
     */
    private $template;
}

And you’re already ready to go. But, what if You don’t like the way it worked, You need __construct injection? There we go:

// app/Controller/IndexController.php
use League\Plates\Engine as PlatesEngine;

class IndexController
{
    public function __construct(PlatesEngine $template)
    {
        $this->template = $template;
    }
}

And we can re-configure the config/di.php:

// config/di.php
use ClassicApp\Controller\IndexController;

return [

    IndexController::class => \DI\object(IndexController::class)->constructor(\DI\get('template')),

    'template' => /* */
    'router' => /* */
];

You want another container instead of php-di ? You can! The GianArb\Penny\App allows passing $container in 2nd parameter, so you can use it in public/index.php:

// public/index.php
$app = new \GianArb\Penny\App(null, $yourChoiceContainer);

Penny use Zend\EventManager to manage application event, There are 3 events that may be triggered:
* ERROR_DISPATCH: when error happen ( route not found, method not allowed, etc)
* filename.function: runnable
* filename.function_error: runnable but exception found.

Interesting? Take a look more on the site! Curious about the code behind it? Consult the code ;).