Skip to content

Commit

Permalink
Merge pull request #1197 from pantheon-systems/change/di-sessions
Browse files Browse the repository at this point in the history
Make the session helper injectable
  • Loading branch information
Ronan Dowling committed Sep 14, 2016
2 parents da4f14b + 8db4a66 commit 7aeebf6
Show file tree
Hide file tree
Showing 6 changed files with 271 additions and 1 deletion.
9 changes: 9 additions & 0 deletions bin/terminus.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
use League\Container\Container;
use Pantheon\Terminus\Config;
use Pantheon\Terminus\Runner;
use Pantheon\Terminus\Session\Session;
use Pantheon\Terminus\Session\SessionAwareInterface;
use Pantheon\Terminus\Terminus;
use Robo\Robo;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Terminus\Caches\FileCache;

// Initializing the Terminus application
$config = new Config();
Expand All @@ -30,6 +33,12 @@
$output = new ConsoleOutput();
Robo::configureContainer($container, $config, $input, $output, $application);

$container->share('fileCache', FileCache::class);
$container->share('session', Session::class)
->withArgument('fileCache');
$container->inflector(SessionAwareInterface::class)
->invokeMethod('setSession', ['session']);

// Running Terminus
$runner = new Runner($container);
$status_code = $runner->run($input, $output);
Expand Down
5 changes: 4 additions & 1 deletion src/Commands/TerminusCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Pantheon\Terminus\Commands;

use Pantheon\Terminus\Config;
use Pantheon\Terminus\Session\SessionAwareInterface;
use Pantheon\Terminus\Session\SessionAwareTrait;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
Expand All @@ -12,11 +14,12 @@
use Robo\Common\IO;
use Terminus\Models\Auth;

abstract class TerminusCommand implements IOAwareInterface, LoggerAwareInterface, ConfigAwareInterface
abstract class TerminusCommand implements IOAwareInterface, LoggerAwareInterface, ConfigAwareInterface, SessionAwareInterface
{
use LoggerAwareTrait;
use ConfigAwareTrait;
use IO;
use SessionAwareTrait;

/**
* TerminusCommand constructor
Expand Down
104 changes: 104 additions & 0 deletions src/Session/Session.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace Pantheon\Terminus\Session;

use Terminus\Caches\FileCache;
use Terminus\Models\User;

class Session {
/**
* @var FileCache
*/
protected $cache;

/**
* @var object
*/
protected $data;

/**
* Instantiates object, sets session data
*/
public function __construct($fileCache) {
$this->cache = $fileCache;
$session = $this->cache->getData('session');
$this->data = $session;
if (empty($session)) {
$this->data = new \stdClass();
}
}

/**
* Removes the session from the cache
*
* @return void
*/
public function destroy() {
$this->cache->remove('session');
}

/**
* Returns given data property or default if DNE.
*
* @param string $key Name of property to return
* @param mixed $default Default return value in case property DNE
* @return mixed
*/
public function get($key, $default = false) {
if (isset($this->data) && isset($this->data->$key)) {
return $this->data->$key;
}
return $default;
}

/**
* Sets a keyed value to be part of the data property object
*
* TODO: This is never used and arguably shouldn't be (since it doesn't save
* data to the persistent session store)
* This should be removed in favor of setData which is designed to
* instantiate the entire session or changed to add persistent data.
*
* @param string $key Name of data property
* @param mixed $value Value of property to set
* @return Session
*/
public function set($key, $value = null) {
$this->data->$key = $value;
return $this;
}

/**
* Saves session data to cache
*
* TODO: The difference between set and setData is confusing. This should be
* refactored when Auth() is.
*
* @param array $data Session data to save
* @return bool
*/
public function setData($data) {
if (empty($data)) {
return false;
}
$this->cache->putData('session', $data);

foreach ($data as $k => $v) {
$this->set($k, $v);
}
return true;
}

/**
* Returns a user with the current session user id
* @return \Terminus\Models\User [user] $session user
*/
public function getUser() {
$user_uuid = $this->get('user_uuid');
// TODO: Remove this direct instantiation to make this more testable
$user = new User((object)array('id' => $user_uuid));
return $user;
}

}
25 changes: 25 additions & 0 deletions src/Session/SessionAwareInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Pantheon\Terminus\Session;


/**
* Interface SessionAwareInterface
* @package Pantheon\Terminus\Session
*
* Provides an interface for direct injection of the session helper.
*/
interface SessionAwareInterface {

/***
* @param Session $session
* @return void
*/
public function setSession(Session $session);

/**
* @return Session
*/
public function session();

}
38 changes: 38 additions & 0 deletions src/Session/SessionAwareTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Pantheon\Terminus\Session;


/**
* Provides the basic properties needed to fulfill the SessionAwareInterface.
*
* Class SessionAwareTrait
* @package Pantheon\Terminus\Session
*/
trait SessionAwareTrait {

/**
* @var Session
*/
protected $session;

/**
* @inheritdoc
*/
public function setSession(Session $session)
{
$this->session = $session;

return $this;
}

/**
* @inheritdoc
*/
public function session()
{
return $this->session;
}


}
91 changes: 91 additions & 0 deletions tests/new_unit_tests/Session/SessionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Pantheon\Terminus\UnitTests\Session;

use Pantheon\Terminus\Session\Session;
use Terminus\Caches\FileCache;

/**
* Testing class for Pantheon\Terminus\Session\Session
*/
class SessionTest extends \PHPUnit_Framework_TestCase {

protected $session;
protected $filecache;

protected function setUp() {
$this->filecache = $this->getMockBuilder(FileCache::class)
->disableOriginalConstructor()
->getMock();

$this->session = new Session($this->filecache);

}

/**
* Test getting and setting data
*/
public function testSetGet() {
$this->session->set('foo', 'bar');
$this->session->set('abc', 123);
$this->session->set('foo', 'baz');

$this->assertEquals('baz', $this->session->get('foo'));
$this->assertEquals(123, $this->session->get('abc'));
}


/**
* Test getting and setting data
*/
public function testSetData() {
$data = [
'foo' => 'bar',
'abc' => 123
];

$this->filecache->expects($this->once())
->method('putData')
->with('session', $data);

$this->session->setData($data);

foreach ($data as $key => $val) {
$this->assertEquals($val, $this->session->get($key));
}
}

/**
* Test getting and setting data
*/
public function testGetUser() {
$data = [
'foo' => 'bar',
'abc' => 123
];

$this->filecache->expects($this->once())
->method('getData')
->with('session')
->willReturn(['user_uuid' => '123']);

$this->session = new Session($this->filecache);

// @TODO: Test mocking of new user (will require some sort of mockable factory rather than
// the direct use of new User() in Session)
$user = $this->session->getUser();
$this->assertInstanceOf('Terminus\Models\User', $user);
}

/**
* Test destroying the session
*/
public function testDestroy() {
$this->filecache->expects($this->once())
->method('remove')
->with('session');

$this->session->destroy();
}

}

0 comments on commit 7aeebf6

Please sign in to comment.