"andy128k/migrations": "dev-master",
"andy128k/pegp": "0.1.*@dev",
"andy128k/routeexpression": "dev-master",
- "andy128k/ipf-legacy-template": "dev-master"
+ "andy128k/ipf-legacy-template": "dev-master",
+ "pimple/pimple": "~3.0"
},
"require-dev": {
"phpunit/phpunit": "5"
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "79837da54a36204e6bdf7388ad043a9b",
+ "content-hash": "6efa15ba9b218a571e0da69898cfc2d1",
"packages": [
{
"name": "andy128k/ipf-legacy-template",
"exception"
],
"time": "2015-02-10T20:07:52+00:00"
+ },
+ {
+ "name": "pimple/pimple",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "21e3e0dc89183c96fad7f12e09e1d345558e9a56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/21e3e0dc89183c96fad7f12e09e1d345558e9a56",
+ "reference": "21e3e0dc89183c96fad7f12e09e1d345558e9a56",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/container": "^1.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Pimple": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "https://pimple.symfony.com",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ],
+ "time": "2018-04-20T06:17:25+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "014d250daebff39eba15ba990eeb2a140798e77c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/014d250daebff39eba15ba990eeb2a140798e77c",
+ "reference": "014d250daebff39eba15ba990eeb2a140798e77c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "time": "2018-12-29T15:36:03+00:00"
}
],
"packages-dev": [
<?php
-use \PFF\Functions as F;
+use Doctrine\DBAL\Connection;
+use PFF\Functions as F;
+use Pimple\Container;
class IPF_Admin_App extends IPF_Application
{
+ /** @var Container */
+ private $container;
+
+ function configure(Container $container, IPF_Settings $settings)
+ {
+ $container['admin_log'] = function ($c) {
+ return new IPF_Admin_Log($c['db'], $c['router']);
+ };
+
+ $this->container = $container;
+ }
+
public static function urls($prefix='admin')
{
return array('prefix' => '#^/'.$prefix.'/', 'urls' => array(
public function appList($request)
{
+ /** @var Connection $connection */
+ $connection = $this->container['db'];
+ /** @var IPF_Application[] $apps */
+ $apps = $this->container['apps'];
+
$app_list = array();
- foreach ($this->getProject()->appList() as $app) {
+ foreach ($apps as $app) {
$components = array();
foreach ($this->applicationComponents($app) as $component) {
if ($component->isAccessible(array('view'), $request)) {
- $component->request = $request;
- $components[] = $component;
+ $components[] = (object)array(
+ 'slug' => $component->slug(),
+ 'name' => $component->verbose_name(),
+ 'can_add' => $component->isAccessible(array('add'), $request),
+ );
}
}
private $appComponents = array();
+ /**
+ * @param IPF_Application $app
+ * @return IPF_Admin_Component[]
+ */
public function applicationComponents($app)
{
if (!array_key_exists($app->slug(), $this->appComponents)) {
$section = new IPF_Admin_SimpleSection($section);
}
- foreach ($section->components($this->getProject(), $app) as $component) {
+ foreach ($section->components($this->container, $app) as $component) {
$component->app = $app;
+ $component->admin_log = $this->container['admin_log'];
+ $component->auth_app = $this->container['apps']['auth'];
$components[] = $component;
}
}
public function getApplicationBySlug($slug)
{
- foreach ($this->getProject()->appList() as $app)
+ /** @var IPF_Application[] $apps */
+ $apps = $this->container['apps'];
+
+ foreach ($apps as $app)
if ($app->slug() === $slug)
return $app;
return null;
public function commands()
{
return array(
- new IPF_Admin_Command_SyncPerms($this),
+ new IPF_Admin_Command_SyncPerms($this, $this->container['db']),
);
}
}
return new IPF_HTTP_Response_NotFound($request);
}
}
-
<?php
+use Doctrine\DBAL\Connection;
+
class IPF_Admin_Command_SyncPerms
{
public $command = 'syncperms';
/** @var IPF_Admin_App */
private $admin_app;
- public function __construct(IPF_Admin_App $admin_app)
+ /** @var Connection */
+ private $connection;
+
+ public function __construct(IPF_Admin_App $admin_app, Connection $connection)
{
$this->admin_app = $admin_app;
+ $this->connection = $connection;
}
public function run($args=null)
private function fetchExistingPermissions()
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('SELECT name FROM auth_permission ORDER BY name');
+ $stmt = $this->connection->prepare('SELECT name FROM auth_permission ORDER BY name');
$stmt->execute();
$existing = [];
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
private function addPermission($permission)
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('INSERT INTO auth_permission (name) VALUES (:name)');
+ $stmt = $this->connection->prepare('INSERT INTO auth_permission (name) VALUES (:name)');
$stmt->bindValue('name', $permission, PDO::PARAM_STR);
$stmt->execute();
}
private function deletePermission($permission)
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('DELETE FROM auth_permission WHERE name = :name');
+ $stmt = $this->connection->prepare('DELETE FROM auth_permission WHERE name = :name');
$stmt->bindValue('name', $permission, PDO::PARAM_STR);
$stmt->execute();
}
<?php
-use \PFF\Functions as F;
-use \PFF\Placeholder as P;
-use \PFF\HtmlBuilder\Tag as Tag;
+use PFF\Functions as F;
+use PFF\HtmlBuilder\Tag as Tag;
+use PFF\Placeholder as P;
interface IPF_Admin_ListFilter
{
{
public $perPage = 50;
public $app = null, $request = null;
+ /** @var IPF_Admin_ILog|null */
+ public $admin_log;
+ /** @var IPF_Auth_App */
+ public $auth_app;
public function slug()
{
return array('view', 'add', 'change', 'delete');
}
- public function isAccessible($what, $request=null)
+ public function isAccessible($what, $request)
{
- if (!$request)
- $request = $this->request;
if (!$request)
throw new IPF_Exception('No request.');
if (count(array_diff($what, $this->getPerms($request))))
return false;
- if ($request->user->is_superuser || !\PFF\Container::auth()->arePermissionsEnabled())
- return true;
-
$authPermissions = F::bind('array_map',
- F::bind('sprintf', '%s|%s|%s', $this->app->slug(), $this->slug(), P::p()),
- P::p())
+ F::bind('sprintf', '%s|%s|%s', $this->app->slug(), $this->slug(), P::p()),
+ P::p())
->call($what);
- return $request->user->can($authPermissions);
+ return $this->auth_app->userCan($request->user, $authPermissions);
}
protected function context($request)
if ($form->isValid()) {
list($id, $object) = $this->saveObject($form, null);
- IPF_Admin_Log::logObject($this, 'add', $object, $id);
+ $this->admin_log->logObject($this, 'add', $object, $id);
return $this->changeSucceed();
}
$errors = true;
'errors' => $errors,
'objecttools' => array(),
'ipf_referrer' => $this->referrerOfChangeAction(),
+ 'can_add' => $this->isAccessible(array('add'), $this->request),
+ 'can_change' => $this->isAccessible(array('change'), $this->request),
+ 'can_delete' => $this->isAccessible(array('delete'), $this->request),
));
}
throw new IPF_HTTP_Error404;
if ($this->request->method == 'POST') {
- IPF_Admin_Log::logObject($this, 'delete', $object);
+ $this->admin_log->logObject($this, 'delete', $object);
$this->deleteObject($object);
return $this->changeSucceed();
}
if ($form->isValid()) {
list($id, $object) = $this->saveObject($form, $object);
- IPF_Admin_Log::logObject($this, 'change', $object, $id);
+ $this->admin_log->logObject($this, 'change', $object, $id);
return $this->changeSucceed();
}
$errors = true;
'errors' => $errors,
'objecttools' => $objecttools,
'ipf_referrer' => $this->referrerOfChangeAction(),
+ 'can_add' => $this->isAccessible(array('add'), $this->request),
+ 'can_change' => $this->isAccessible(array('change'), $this->request),
+ 'can_delete' => $this->isAccessible(array('delete'), $this->request),
));
}
'filters' => $filters,
'is_search' => $this->searcheable(),
'search_value' => $searchValue,
+ 'can_add' => $this->isAccessible(array('add'), $this->request),
));
}
protected function checkPermissions()
{
+ $connection = $this->container['db'];
$requiredPermissions = func_get_args();
if (!$this->component->isAccessible($requiredPermissions, $this->request))
throw new IPF_Admin_AccessDenied;
class IPF_Admin_Dashboard_Controller extends IPF_Admin_Base_Controller
{
+ /**
+ * @return IPF_Admin_ILog
+ */
+ private function adminLog()
+ {
+ return $this->container['admin_log'];
+ }
+
function index()
{
$this->ensureUserIsStaff();
$context = array(
'page_title' => __('Site Administration'),
- 'admin_log' => IPF_Admin_Log::recent(),
+ 'admin_log' => $this->adminLog()->recent(),
);
return $this->render('admin/index.html', $context);
}
if (!$currentPage)
$currentPage = 1;
- $count = IPF_Admin_Log::count();
+ $count = $this->adminLog()->count();
$perPage = 20;
$pagerLayout = new IPF_Pager_Layout;
$context = array(
'page_title' => __('Recent Actions'),
- 'admin_log' => IPF_Admin_Log::recent($perPage, ($currentPage - 1) * $perPage),
+ 'admin_log' => $this->adminLog()->recent($perPage, ($currentPage - 1) * $perPage),
'count' => $count,
'current_page' => $currentPage,
'pages' => $pages,
return $this->render('admin/log.html', $context);
}
}
-
if (!$success_url)
$success_url = $this->project->router->reverse(array('IPF_Admin_Dashboard_Controller', 'index'));
+ $auth_app = $this->authApp();
+
if ($this->request->method == 'POST') {
- $form = new IPF_Admin_Forms_Login($this->request->POST);
+ $form = new IPF_Admin_Forms_Login($this->request->POST, array('auth_app' => $auth_app));
if ($form->isValid()) {
- $this->authApp()->login($this->request, $form->user);
+ $auth_app->login($this->request, $form->user);
return new IPF_HTTP_Response_Redirect($success_url);
}
} else {
- $form = new IPF_Admin_Forms_Login(array('next'=>$success_url));
+ $form = new IPF_Admin_Forms_Login(array('next'=>$success_url), array('auth_app' => $auth_app));
}
$context = array(
public $message = null;
public $user = null;
+ /** @var IPF_Auth_App */
+ private $auth_app;
+
protected function initFields($extra=array())
{
+ $this->auth_app = $extra['auth_app'];
+
$this->fields['username'] = new IPF_Form_Field_Varchar(array('required'=>true));
$this->fields['password'] = new IPF_Form_Field_Varchar(array('required'=>true,'widget'=>'IPF_Form_Widget_PasswordInput'));
$this->fields['next'] = new IPF_Form_Field_Varchar(array('required'=>false,'widget'=>'IPF_Form_Widget_HiddenInput'));
{
$data = parent::clean();
- $user = \PFF\Container::auth()->findUserByUsername($data['username']);
+ $user = $this->auth_app->findUserByUsername($data['username']);
if (!$user || !$user->checkPassword($data['password']))
throw new IPF_Exception_Form(__('The login or the password is not valid. The login and the password are case sensitive.'));
return $this->renderLayout(new IPF_Admin_Form_Layout);
}
}
-
<?php
-class IPF_Admin_Log
+use Doctrine\DBAL\Connection;
+
+interface IPF_Admin_ILog {
+ /**
+ * @return integer
+ */
+ public function count();
+
+ /**
+ * @param int $limit
+ * @param int $offset
+ * @return array
+ */
+ public function recent($limit=10, $offset=0);
+
+ /**
+ * @param string $who
+ * @param string $action
+ * @param string $repr
+ * @param string $class
+ * @param string|null $url
+ */
+ public function log($who, $action, $repr, $class, $url=null);
+
+ /**
+ * @param IPF_Admin_Component $component
+ * @param string $action
+ * @param mixed $object
+ * @param int|null $object_id
+ */
+ public function logObject($component, $action, $object, $object_id=null);
+}
+
+class IPF_Admin_Log implements IPF_Admin_ILog
{
- public static function count()
+ /** @var Connection */
+ private $connection;
+ /** @var IPF_Router */
+ private $router;
+
+ function __construct(Connection $connection, IPF_Router $router)
+ {
+ $this->connection = $connection;
+ $this->router = $router;
+ }
+
+ public function count()
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('SELECT COUNT(1) AS cnt FROM admin_log');
+ $stmt = $this->connection->prepare('SELECT COUNT(1) AS cnt FROM admin_log');
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row['cnt'];
}
- public static function recent($limit=10, $offset=0)
+ public function recent($limit=10, $offset=0)
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('SELECT * FROM admin_log ORDER BY created_at DESC LIMIT :limit OFFSET :offset');
+ $stmt = $this->connection->prepare('SELECT * FROM admin_log ORDER BY created_at DESC LIMIT :limit OFFSET :offset');
$stmt->bindValue('limit', (int)$limit, PDO::PARAM_INT);
$stmt->bindValue('offset', (int)$offset, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_OBJ);
}
- public static function log($who, $action, $repr, $class, $url=null)
+ public function log($who, $action, $repr, $class, $url=null)
{
- $connection = \PFF\Container::databaseConnection();
- $stmt = $connection->prepare('INSERT INTO admin_log ' .
+ $stmt = $this->connection->prepare('INSERT INTO admin_log ' .
'(username, user_id, action, object_class, object_repr, object_url)' .
' VALUES ' .
'(:username, :user_id, :action, :object_class, :object_repr, :object_url)'
$stmt->execute();
}
- public static function logObject($component, $action, $object, $object_id=null)
+ public function logObject($component, $action, $object, $object_id=null)
{
- $url = $object_id ? IPF_HTTP_URL::urlForView(array('IPF_Admin_Components_Controller', 'editItem'), array($component->app->slug(), $component->slug(), $object_id)) : '';
- self::log($component->request->user, $action, (string)$object, $component->verbose_name(), $url);
+ $url = $object_id
+ ? $this->router->reverse(['IPF_Admin_Components_Controller', 'editItem'], [$component->app->slug(), $component->slug(), $object_id])
+ : '';
+ $this->log($component->request->user, $action, (string)$object, $component->verbose_name(), $url);
}
}
<?php
+use Pimple\Container;
+
interface IPF_Admin_ISection
{
/**
- * @param IPF_Project $project
+ * @param Container $container
* @param IPF_Application $app
* @return IPF_Admin_Component[]
*/
- public function components(IPF_Project $project, IPF_Application $app);
+ public function components(Container $container, IPF_Application $app);
}
class IPF_Admin_SimpleSection implements IPF_Admin_ISection
}
/**
- * @param IPF_Project $project
+ * @param Container $container
* @param IPF_Application $app
* @return IPF_Admin_Component[]
*/
- public function components(IPF_Project $project, IPF_Application $app)
+ public function components(Container $container, IPF_Application $app)
{
$components = array();
foreach ($this->component_names as $c) {
<h3>{$app.name}</h3>
<ul>
{foreach $app.components as $component}
- <li><a href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug())}">{$component->verbose_name()}</a></li>
+ <li><a href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug)}">{$component->name}</a></li>
{/foreach}
</ul>
</li>
{/block}
</fieldset>
<div class="submit-row change-form">
- {if ($mode=='change') && $component->isAccessible(array('delete'))}<p class="float-left"><a href="{url array('IPF_Admin_Components_Controller', 'deleteItem'), array($app->slug(), $component->slug(), $object_id)}?ipf_referrer={$ipf_referrer}" class="deletelink">{trans 'Delete'}</a></p>{/if}
- {if ($mode=='change') && $component->isAccessible(array('change'))}<input type="submit" value="{trans 'Save'}" class="default" />{/if}
- {if ($mode=='add') && $component->isAccessible(array('add'))}<input type="submit" value="{trans 'Add'}" class="default" />{/if}
+ {if ($mode=='change') && $can_delete}<p class="float-left"><a href="{url array('IPF_Admin_Components_Controller', 'deleteItem'), array($app->slug(), $component->slug(), $object_id)}?ipf_referrer={$ipf_referrer}" class="deletelink">{trans 'Delete'}</a></p>{/if}
+ {if ($mode=='change') && $can_change}<input type="submit" value="{trans 'Save'}" class="default" />{/if}
+ {if ($mode=='add') && $can_add}<input type="submit" value="{trans 'Add'}" class="default" />{/if}
<input type="button" value="{trans 'Cancel'}" onclick="javascript:history.back();" />
</div>
</div>
<tbody>
{foreach $app.components as $component}
<tr>
- <th scope="row"><a href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug())}">{$component->verbose_name()}</a></th>
- <td>{if $component->isAccessible(array('add'))}<a class="addlink" href="{url array('IPF_Admin_Components_Controller', 'addItem'), array($app.path, $component->slug())}">{trans 'Add'}</a>{/if}</td>
- <td><a class="changelink" href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug())}">{trans 'Change'}</a></td>
+ <th scope="row"><a href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug)}">{$component->name}</a></th>
+ <td>{if $component->can_add}<a class="addlink" href="{url array('IPF_Admin_Components_Controller', 'addItem'), array($app.path, $component->slug)}">{trans 'Add'}</a>{/if}</td>
+ <td><a class="changelink" href="{url array('IPF_Admin_Components_Controller', 'listItems'), array($app.path, $component->slug)}">{trans 'Change'}</a></td>
</tr>
{/foreach}
</tbody>
<div id="content-main">
<ul class="object-tools">
{block objecttools}
- {if $component->isAccessible(array('add'))}<li><a href="add/">{$title_add}</a></li>{/if}
+ {if $can_add}<li><a href="add/">{$title_add}</a></li>{/if}
<li><a href="javascript:print();">{trans 'Print'}</a></li>
{/block}
</ul>
abstract class IPF_Application
{
- /** @var IPF_Project */
- private $project;
-
- /** @var string */
- private $name, $path;
-
- public function __construct(IPF_Project $project)
- {
- $this->project = $project;
-
- $this->name = preg_replace('/_App$/', '', get_class($this));
-
- $rc = new ReflectionClass($this);
- $this->path = dirname($rc->getFileName()) . DIRECTORY_SEPARATOR;
- }
-
- public function getProject()
+ /**
+ * Configures application
+ *
+ * @param \Pimple\Container $container
+ * @param IPF_Settings $settings
+ */
+ public function configure(\Pimple\Container $container, IPF_Settings $settings)
{
- return $this->project;
}
public function getName()
{
- return $this->name;
+ return preg_replace('/_App$/', '', get_class($this));
}
public function getTitle()
{
- return $this->name;
+ return $this->getName();
}
public function getPath()
{
- return $this->path;
+ $rc = new ReflectionClass($this);
+ return dirname($rc->getFileName()) . DIRECTORY_SEPARATOR;
}
public function slug()
{
- return strtolower(preg_replace('/^IPF_/', '', $this->name));
- }
-
- /**
- * Configures application
- *
- * @param IPF_Settings $settings
- */
- public function configure(IPF_Settings $settings)
- {
+ return strtolower(preg_replace('/^IPF_/', '', preg_replace('/_App$/', '', get_class($this))));
}
/**
namespace IPF\Auth\Admin;
+use Doctrine\DBAL\Connection;
+use IPF\Auth\Permission as Permission;
+use IPF\Auth\Role as Role;
use IPF_Admin_App;
-use IPF_Auth_App;
-use IPF_Project;
+use IPF_Admin_Component;
+use IPF_Admin_ILog;
use IPF_Application;
-use \IPF\Auth\Role as Role;
-use \IPF\Auth\Permission as Permission;
-use \PFF\HtmlBuilder\Text as Text;
+use IPF_Auth_App;
+use IPF_Database;
+use PFF\HtmlBuilder\Text as Text;
+use Pimple\Container;
class UserForm extends \IPF_ObjectForm
{
{
$auth_app = $extra['auth_app'];
$permissions_choices = $extra['permissions_choices'];
+ $roles_choices = $extra['roles_choices'];
$this->isAdd = $extra['is_add'];
$this->fields['roles'] = new \IPF_Admin_Form_Field_MultipleChoice(array(
'label' => __('Groups'),
'help_text' => __('In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.'),
- 'choices' => \PFF\Collection::columnByProperty(Role::all(), 'id', 'name'),
+ 'choices' => $roles_choices,
));
}
abstract class Component extends \IPF_Admin_Component
{
- /** @var IPF_Project */
- protected $project;
-
- /** @var IPF_Auth_App */
- private $auth_app;
+ /** @var Container */
+ protected $container;
- function __construct(IPF_Project $project, IPF_Auth_App $auth_app)
+ function __construct(Container $container, IPF_Auth_App $auth_app)
{
- $this->project = $project;
$this->auth_app = $auth_app;
+ $this->container = $container;
}
/**
return $this->auth_app;
}
- protected function permissionChoices()
+ protected function permissionChoices(Connection $connection)
{
+ /** @var IPF_Application[] $apps */
+ $apps = $this->container['apps'];
+
$admin_app = null;
- foreach ($this->project->appList() as $a)
+ foreach ($apps as $a)
if ($a instanceof IPF_Admin_App)
$admin_app = $a;
throw new \Exception('Admin application is not registered.');
$choices = array();
- foreach (Permission::all() as $p) {
+ foreach (Permission::all($connection) as $p) {
list($appSlug, $componentSlug, $permission) = explode('|', $p->name);
$component = $admin_app->getComponentBySlugs($appSlug, $componentSlug);
return $choices;
}
+
+ /**
+ * @return Connection
+ */
+ protected function getConnection()
+ {
+ return $this->container['db'];
+ }
}
class AdminUser extends Component
{
public function getItems($searchValue, $filters, $page, $pageSize)
{
- $connection = \PFF\Container::db();
$userModelClass = $this->authApp()->userModel;
- $items = \IPF_Database::queryAllObjects($connection, $userModelClass,
+ $items = \IPF_Database::queryAllObjects($this->getConnection(), $userModelClass,
'SELECT * FROM auth_user' .
' ORDER BY username' .
' LIMIT ' . $pageSize .
public function itemsCount($searchValue, $filters)
{
- return \PFF\Container::db()->fetchColumn('SELECT COUNT(1) FROM auth_user');
+ return $this->getConnection()->fetchColumn('SELECT COUNT(1) FROM auth_user');
}
public function list_display()
public function column_groups($obj)
{
- return Text::escape(implode(' / ', \PFF\Arr::pluck($obj->roles(), 'name')));
+ return Text::escape(implode(' / ', \PFF\Arr::pluck($obj->roles($this->getConnection()), 'name')));
}
function _searchFields()
protected function _getForm($user, $data)
{
+ $connection = $this->getConnection();
+
$extra = array(
'auth_app' => $this->authApp(),
- 'permissions_choices' => $this->permissionChoices(),
+ 'permissions_choices' => $this->permissionChoices($connection),
+ 'roles_choices' => \PFF\Collection::columnByProperty(Role::all($connection), 'id', 'name'),
);
if ($user) {
$extra['initial'] = array(
- 'permissions' => \PFF\Arr::pluck($user->permissions(), 'id'),
- 'roles' => \PFF\Arr::pluck($user->roles(), 'id'),
+ 'permissions' => \PFF\Arr::pluck($user->permissions($connection), 'id'),
+ 'roles' => \PFF\Arr::pluck($user->roles($connection), 'id'),
);
$extra['is_add'] = false;
} else {
public function saveObject($form, $user)
{
+ $connection = $this->getConnection();
+
if (!$user)
$user = $this->authApp()->createUser();
$form->toObject($user);
if ($form->cleaned_data['password1'])
$user->setPassword($form->cleaned_data['password1']);
- $user->save();
+ $user->save($connection);
if ($this->authApp()->arePermissionsEnabled()) {
- Permission::revokeAll($user);
- $permissions = Permission::findAll($form->cleaned_data['permissions']);
- Permission::grantAll($permissions, $user);
+ Permission::revokeAll($connection, $user);
+ $permissions = Permission::findAll($connection, $form->cleaned_data['permissions']);
+ Permission::grantAll($connection, $permissions, $user);
- Role::leaveAll($user);
- foreach (Role::findAll($form->cleaned_data['roles']) as $role) {
- $role->join($user);
+ Role::leaveAll($connection, $user);
+ foreach (Role::findAll($connection, $form->cleaned_data['roles']) as $role) {
+ $role->join($connection, $user);
}
}
return array($user->id, $user);
public function deleteObject($user)
{
- \PFF\Container::db()->delete('auth_user', ['id' => $user->id]);
+ $this->getConnection()->delete('auth_user', ['id' => $user->id]);
}
protected function objectTools($user)
{
+ $router = $this->container['router'];
+
return array(
- 'impersonate' => $this->project->router->reverse(array('IPF_Admin_User_Controller', 'impersonate'), array($user->id)),
+ 'impersonate' => $router->reverse(array('IPF_Admin_User_Controller', 'impersonate'), array($user->id)),
);
}
{
public function getItems($searchValue, $filters, $page, $pageSize)
{
- $items = Role::queryAll('SELECT * FROM auth_role' .
+ $connection = $this->getConnection();
+ $items = IPF_Database::queryAllObjects($connection, Role::class, 'SELECT * FROM auth_role' .
' ORDER BY name' .
' LIMIT ' . $pageSize .
- ' OFFSET ' . (($page - 1) * $pageSize)
- );
+ ' OFFSET ' . (($page - 1) * $pageSize), [], []);
return \PFF\Collection::indexByProperty($items, 'id');
}
public function itemsCount($searchValue, $filters)
{
- $connection = \PFF\Container::db();
- return $connection->fetchColumn('SELECT COUNT(1) FROM auth_role');
+ return $this->getConnection()->fetchColumn('SELECT COUNT(1) FROM auth_role');
}
public function list_display()
public function getObjectByID($id)
{
- return Role::queryOne('SELECT * FROM auth_role WHERE id = ?', [$id]);
+ return IPF_Database::queryOneObject($this->getConnection(), Role::class, 'SELECT * FROM auth_role WHERE id = ?', [$id], []);
}
protected function _getForm($role, $data)
{
+ $connection = $this->getConnection();
+
$extra = array(
'auth_app' => $this->authApp(),
- 'permissions_choices' => $this->permissionChoices(),
+ 'permissions_choices' => $this->permissionChoices($connection),
);
if ($role) {
$extra['initial'] = array(
- 'permissions' => \PFF\Arr::pluck($role->permissions(), 'id'),
+ 'permissions' => \PFF\Arr::pluck($role->permissions($connection, $connection), 'id'),
);
return new RoleForm($data, $role, $extra);
} else {
public function saveObject($form, $role)
{
+ $connection = $this->getConnection();
+
if (!$role)
$role = new Role;
$form->toObject($role);
- $role->save();
+ $role->save($connection);
- Permission::revokeAll($role);
- $permissions = Permission::findAll($form->cleaned_data['permissions']);
- Permission::grantAll($permissions, $role);
+ Permission::revokeAll($connection, $role);
+ $permissions = Permission::findAll($connection, $form->cleaned_data['permissions']);
+ Permission::grantAll($connection, $permissions, $role);
return array($role->id, $role);
}
public function deleteObject($role)
{
- \PFF\Container::db()->delete('auth_role', ['id' => $role->id]);
+ $this->getConnection()->delete('auth_role', ['id' => $role->id]);
}
public function page_title() { return __('Role'); }
class AuthAdminSection implements \IPF_Admin_ISection
{
- public function components(IPF_Project $project, IPF_Application $app)
+ /**
+ * @param Container $container
+ * @param IPF_Application $app
+ * @return IPF_Admin_Component[]
+ */
+ public function components(Container $container, IPF_Application $app)
{
/** @var IPF_Auth_App $app */
$components = array(
- new AdminUser($project, $app),
+ new AdminUser($container, $app),
);
if ($app->arePermissionsEnabled()) {
- $components[] = new AdminRole($project, $app);
+ $components[] = new AdminRole($container, $app);
}
return $components;
<?php
+use Doctrine\DBAL\Connection;
+use IPF\Auth\User;
+use Pimple\Container;
+
class IPF_Auth_App extends IPF_Application
{
+ /** @var Container */
+ private $container;
+
public $userModel;
- function configure(IPF_Settings $settings)
+ /**
+ * Configures application
+ *
+ * @param Container $container
+ * @param IPF_Settings $settings
+ */
+ public function configure(Container $container, IPF_Settings $settings)
{
+ $this->container = $container;
$this->userModel = $settings->get('auth_user_model', 'IPF\\Auth\\User');
}
function findUser($id)
{
- $connection = \PFF\Container::db();
+ $connection = $this->getConnection();
return \IPF_Database::queryOneObject($connection, $this->userModel, 'SELECT * FROM auth_user WHERE id = ?', [$id]);
}
function findUserByUsername($username)
{
- $connection = \PFF\Container::db();
+ $connection = $this->getConnection();
return \IPF_Database::queryOneObject($connection, $this->userModel, 'SELECT * FROM auth_user WHERE username = ?', [$username]);
}
function arePermissionsEnabled()
{
if ($this->permissionsEnabled === null) {
- $this->permissionsEnabled = (bool)\PFF\Container::db()->fetchColumn('SELECT COUNT(1) FROM auth_permission');
+ $connection = $this->getConnection();
+ $this->permissionsEnabled = (bool)$connection->fetchColumn('SELECT COUNT(1) FROM auth_permission');
}
return $this->permissionsEnabled;
}
+ public function userCan($user, $authPermissions)
+ {
+ return $user->is_superuser
+ || !$this->arePermissionsEnabled()
+ || $user->can($this->getConnection(), $authPermissions);
+ }
+
public function commands()
{
return array(
- new \IPF\Auth\Commands\CreateSuperUser,
+ new \IPF\Auth\Commands\CreateSuperUser($this),
);
}
+
+ /**
+ * @return Connection
+ */
+ private function getConnection()
+ {
+ return $this->container['db'];
+ }
}
public $command = 'createsuperuser';
public $description = 'Create superuser';
+ /** @var \IPF_Auth_App */
+ private $auth_app;
+
+ public function __construct(\IPF_Auth_App $auth_app)
+ {
+ $this->auth_app = $auth_app;
+ }
+
public function run($args=null)
{
print "Create superuser\n";
$password = \IPF_Shell::ask(' Password: ');
$email = \IPF_Shell::ask(' E-mail: ');
- $su = \PFF\Container::auth()->createUser();
+ $su = $this->auth_app->createUser();
$su->username = $username;
$su->email = $email;
$su->is_staff = true;
print "Done\n";
}
}
-
$user_id = \PFF\Arr::get($request->session->data, self::SessionKey, 0);
if ($user_id > 0) {
- $request->user = \PFF\Container::auth()->findUser($user_id);
+ $auth_app = $this->container['apps']['auth'];
+ $request->user = $auth_app->findUser($user_id);
if ($request->user && 43200 < time() - strtotime($request->user->last_login.' GMT')) {
$request->user->last_login = gmdate('Y-m-d H:i:s');
$request->user->save();
return $response;
}
}
-
namespace IPF\Auth;
+use Doctrine\DBAL\Connection;
+use IPF_Database;
+
abstract class DBObject
{
public $id;
protected $table = 'specify table name here';
- public static function queryOne($sql, $params = [], $types = [])
- {
- $connection = \PFF\Container::db();
- return \IPF_Database::queryOneObject($connection, static::class, $sql, $params, $types);
- }
-
- public static function queryAll($sql, $params = [], $types = [])
- {
- $connection = \PFF\Container::db();
- return \IPF_Database::queryAllObjects($connection, static::class, $sql, $params, $types);
- }
-
- public function save()
+ public function save(Connection $connection)
{
$r = new \ReflectionObject($this);
$values[$name] = $value;
}
- $connection = \PFF\Container::db();
if ($this->id) {
$connection->update($this->table, $values, ['id' => $this->id]);
} else {
return true;
}
- public function can(/* $permission ... */)
+ public function can(Connection $connection, ...$permissions)
{
return false;
}
return false;
}
- public function permissions()
+ public function permissions(Connection $connection)
{
- return Permission::queryAll('SELECT auth_permission.* FROM auth_permission ' .
+ return IPF_Database::queryAllObjects($connection, Permission::class, 'SELECT auth_permission.* FROM auth_permission ' .
' INNER JOIN auth_user_permission ON permission_id = id ' .
' WHERE user_id = ? ' .
- ' ORDER BY name',
- [$this->id]
- );
+ ' ORDER BY name', [$this->id], []);
}
- public function roles()
+ public function roles(Connection $connection)
{
- return Role::queryAll('SELECT auth_role.* FROM auth_role ' .
+ return IPF_Database::queryAllObjects($connection, Role::class, 'SELECT auth_role.* FROM auth_role ' .
' INNER JOIN auth_user_role ON role_id = id ' .
' WHERE user_id = ? ' .
- ' ORDER BY name',
- [$this->id]
- );
+ ' ORDER BY name', [$this->id], []);
}
- public function effectivePermissions()
+ public function effectivePermissions(Connection $connection)
{
- return Permission::queryAll('SELECT auth_permission.* FROM auth_permission ' .
+ return IPF_Database::queryAllObjects($connection, Permission::class, 'SELECT auth_permission.* FROM auth_permission ' .
'WHERE ' .
'EXISTS(SELECT 1 FROM auth_user_permission AS up ' .
' WHERE up.permission_id = auth_permission.id' .
' WHERE rp.permission_id = auth_permission.id' .
' AND rp.role_id = ur.role_id' .
' AND ur.user_id = :user_id)' .
- ' ORDER BY name',
- ['user_id' => $this->id]
- );
+ ' ORDER BY name', ['user_id' => $this->id], []);
}
- public function can(/* $permission ... */)
+ public function can(Connection $connection, ...$permissions)
{
$cond = array();
$params = array();
- foreach (func_get_args() as $permission) {
+ foreach ($permissions as $permission) {
if ($permission instanceof Permission) {
$cond[] = 'id = ?';
$params[] = $permission->id;
}
}
- return $this->effectivePermissions()
+ return $this->effectivePermissions($connection)
->select(null)->select('COUNT(1)')
->where(implode(' OR ', $cond), $params)
->fetchColumn() == count($params);
class Role extends DBObject
{
protected $table = 'auth_role';
+ /** @var string */
public $name;
public function __toString()
return $this->name;
}
- public static function all()
+ public static function all(Connection $connection)
{
- return static::queryAll('SELECT * FROM auth_role ORDER BY name');
+ return IPF_Database::queryAllObjects($connection, Role::class, 'SELECT * FROM auth_role ORDER BY name', [], []);
}
- public static function findAll($ids)
+ public static function findAll(Connection $connection, $ids)
{
if (!$ids) {
return [];
}
- return static::queryAll('SELECT * FROM auth_role WHERE id IN (?) ORDER BY name',
- [$ids],
- [\Doctrine\DBAL\Connection::PARAM_INT_ARRAY]
- );
+ return IPF_Database::queryAllObjects($connection, Role::class, 'SELECT * FROM auth_role WHERE id IN (?) ORDER BY name', [$ids], [\Doctrine\DBAL\Connection::PARAM_INT_ARRAY]);
}
- public function permissions()
+ public function permissions(Connection $connection)
{
- return Permission::queryAll('SELECT auth_permission.* FROM auth_permission ' .
+ return IPF_Database::queryAllObjects($connection, Permission::class, 'SELECT auth_permission.* FROM auth_permission ' .
' INNER JOIN auth_role_permission ON permission_id = id ' .
' WHERE role_id = ? ' .
- ' ORDER BY name',
- [$this->id]
- );
+ ' ORDER BY name', [$this->id], []);
}
- public function join($user)
+ public function join(Connection $connection, $user)
{
- \PFF\Container::db()->insert('auth_user_role', ['user_id' => $user->id, 'role_id' => $this->id]);
+ $connection->insert('auth_user_role', ['user_id' => $user->id, 'role_id' => $this->id]);
}
- public function leave($user)
+ public function leave(Connection $connection, $user)
{
if ($this->id) {
- self::leaveAll($user, $this->id);
+ self::leaveAll($connection, $user, $this->id);
}
}
- public static function leaveAll($user, $only=null)
+ public static function leaveAll(Connection $connection, $user, $only=null)
{
$cond = array('user_id' => $user->id);
if ($only) {
$cond['role_id'] = $only;
}
- \PFF\Container::db()->delete('auth_user_role', $cond);
+ $connection->delete('auth_user_role', $cond);
}
}
protected $table = 'auth_permission';
public $name;
- public static function all()
+ public static function all(Connection $connection)
{
- return static::queryAll('SELECT * FROM auth_permission ORDER BY name');
+ return IPF_Database::queryAllObjects($connection, Permission::class, 'SELECT * FROM auth_permission ORDER BY name', [], []);
}
- public static function findAll($ids)
+ public static function findAll(Connection $connection, $ids)
{
if (!$ids) {
return [];
}
- return static::queryAll('SELECT * FROM auth_permission WHERE id IN (?) ORDER BY name',
- [$ids],
- [\Doctrine\DBAL\Connection::PARAM_INT_ARRAY]
- );
+ return IPF_Database::queryAllObjects($connection, Permission::class, 'SELECT * FROM auth_permission WHERE id IN (?) ORDER BY name', [$ids], [\Doctrine\DBAL\Connection::PARAM_INT_ARRAY]);
}
- public function grant($obj)
+ public function grant(Connection $connection, $obj)
{
list($table, $data) = self::link($obj);
$data['permission_id'] = $this->id;
- \PFF\Container::db()->insert($table, $data);
+ $connection->insert($table, $data);
}
- public static function grantAll($permissions, $obj)
+ public static function grantAll(Connection $connection, $permissions, $obj)
{
if (!$permissions) {
return;
list($table, $data) = self::link($obj);
foreach ($permissions as $p) {
$values = array_merge($data, array('permission_id' => $p->id));
- \PFF\Container::db()->insert($table, $values);
+ $connection->insert($table, $values);
}
}
- public function revoke($obj)
+ public function revoke(Connection $connection, $obj)
{
if ($this->id) {
- self::revokeAll($obj, $this->id);
+ self::revokeAll($connection, $obj, $this->id);
}
}
- public static function revokeAll($obj, $only=null)
+ public static function revokeAll(Connection $connection, $obj, $only=null)
{
list($table, $cond) = self::link($obj);
if ($only) {
$cond['permission_id'] = $only;
}
- $connection = \PFF\Container::db();
$connection->delete($table, $cond);
}
public function run($args=null) { ... body
*/
-class IPF_Cli
-{
- /** @var IPF_Project */
- private $project;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
- /** @var array */
- protected $commands;
-
- public function __construct(IPF_Project $project)
- {
- $this->project = $project;
- }
+class IPF_Cli_Provider implements ServiceProviderInterface {
- public function findCommands()
+ public function register(Container $container)
{
- $this->commands = array(
- 'IPF' => array(
+ $container['ipf_commands'] = function($c) {
+ return array(
new IPF_Command_Shell,
new IPF_Command_DebugServer,
new IPF_Command_Routes,
new IPF_Command_Pack,
new IPF_Command_Unpack,
new IPF_Command_CreateMigration,
- new IPF_Command_Migrate,
- ),
- );
-
- foreach ($this->project->appList() as $app) {
- $commands = $app->commands();
- if (count($commands))
- $this->commands[$app->getName()] = $commands;
- }
+ new IPF_Command_Migrate($c['apps'], $c['db']),
+ );
+ };
+
+ $container['project_commands'] = function($c) {
+ $commands = array();
+ foreach (IPF::get('commands', array()) as $cmd) {
+ if (is_string($cmd))
+ $cmd = new $cmd;
+ $commands[] = $cmd;
+ }
+ return $commands;
+ };
+
+ $container['cli_commands'] = function ($c) {
+ $commands = [
+ 'IPF' => $c['ipf_commands'],
+ ];
+
+ /** @var IPF_Application[] $apps */
+ $apps = $c['apps'];
+ foreach ($apps as $app) {
+ $app_commands = $app->commands();
+ if (count($app_commands))
+ $commands[$app->getName()] = $app_commands;
+ }
- $project = array();
- foreach (IPF::get('commands', array()) as $cmd) {
- if (is_string($cmd))
- $cmd = new $cmd;
- $project[] = $cmd;
- }
- if (count($project))
- $this->commands['Project'] = $project;
+ $project_commands = $c['project_commands'];
+ if (count($project_commands))
+ $commands['Project'] = $project_commands;
+
+ return $commands;
+ };
+
+ $container['cli'] = function ($c) {
+ return new IPF_Cli($c['cli_commands']);
+ };
+ }
+}
+
+class IPF_Cli
+{
+ /** @var array */
+ private $commands;
+
+ public function __construct(array $commands)
+ {
+ $this->commands = $commands;
}
private function getCommand($commandName)
return null;
}
- protected function usage()
+ private function usage()
{
print "Usage: php index.php <subcommand> [options] [args]\n";
<?php
+use Doctrine\DBAL\Connection;
+
class IPF_Command_Migrate
{
public $command = 'migrate';
public $description = 'Migrate DB schema';
- public function run($args=null)
+ /** @var IPF_Application[] $appList */
+ private $appList;
+ /** @var Connection */
+ private $connection;
+
+ function __construct(array $appList, Connection $connection)
{
- $project = IPF_Project::getInstance();
+ $this->appList = $appList;
+ $this->connection = $connection;
+ }
+ public function run($args=null)
+ {
$paths = array(IPF::get('project_root').'/project/db/migrations');
- foreach ($project->appList() as $app) {
+ foreach ($this->appList as $app) {
$paths[] = $app->getPath() . 'migrations';
}
- $connection = \PFF\Container::databaseConnection();
$m = new \PFF\Migrations\Migrations;
- $m->migrate($connection, $paths);
+ $m->migrate($this->connection, $paths);
}
}
-
<?php
+use Pimple\Container;
+
class IPF_Controller
{
/** @var IPF_Project */
protected $project;
protected $request;
protected $params;
+ /** @var Container */
+ protected $container;
- function __construct(IPF_Project $project)
+ function __construct(IPF_Project $project, Container $container)
{
$this->project = $project;
+ $this->container = $container;
}
function process($action, $request, $matches)
<?php
+use Pimple\Container;
+
class IPF_Middleware
{
/** @var IPF_Middleware */
protected $next;
/** @var IPF_Settings */
- protected $settings;
+ protected $settings; // deprecated
/** @var IPF_Project */
- protected $project;
+ protected $project; // deprecated
+
+ /** @var Container */
+ protected $container;
/**
* @param IPF_Middleware|null $next Next middleware in a chain
* @param IPF_Settings $settings
* @param IPF_Project $project
+ * @param Container $container
*/
- function __construct($next, IPF_Settings $settings, IPF_Project $project)
+ function __construct($next, IPF_Settings $settings, IPF_Project $project, Container $container)
{
$this->next = $next;
$this->settings = $settings;
$this->project = $project;
+ $this->container = $container;
}
function processRequest($request)
$request->params = $match;
try {
- $controller = $route->controller();
- $controller = new $controller($this->project);
+ $controllerClass = $route->controller();
+ /** @var IPF_Controller $controller */
+ $controller = new $controllerClass($this->project, $this->container);
return $controller->process($route->action(), $request, $match);
} catch (IPF_Router_Shortcut $e) {
return $e->response($request);
<?php
+use Pimple\Container;
+
final class IPF_Project
{
+ /** @var Container */
+ private $container = null;
private $apps = array();
public $router = null;
public $request = null;
private function __construct()
{
+ $this->container = new Container();
+
+ $apps = array();
foreach (IPF::get('applications') as $name) {
$className = $name.'_App';
/** @var IPF_Application $app */
- $app = new $className($this);
- $app->configure(IPF::$settings);
+ $app = new $className();
+ $app->configure($this->container, IPF::$settings);
$this->apps[$name] = $app;
- \PFF\Container::set($app->slug(), $app);
+ $apps[$app->slug()] = $app;
}
- $this->router = new IPF_Router;
+ $this->container['apps'] = $apps;
+ $this->container['router'] = function ($c) {
+ return new IPF_Router;
+ };
+ $this->router = $this->container['router'];
}
private function __clone()
$m = null;
foreach (array_reverse($middlewares) as $mw) {
- $m = new $mw($m, IPF::$settings, $this);
+ $m = new $mw($m, IPF::$settings, $this, $this->container);
}
return $m;
}
public function run()
{
- \PFF\Container::setFactory('databaseConnection', array('IPF_Database', 'connect'));
+ $this->container['databaseConnection'] = function ($c) {
+ return IPF_Database::connect();
+ };
+ $this->container['db'] = $this->container->factory(function ($c) {
+ return IPF_Database::connectDBAL();
+ });
- \PFF\Container::setFunction('db', array('IPF_Database', 'connectDBAL'));
+ $this->container->register(new IPF_Cli_Provider());
if (IPF::get('debug')) {
error_reporting(E_ALL);
}
if (php_sapi_name() === 'cli') {
- $cli = new IPF_Cli($this);
- $cli->findCommands();
- $cli->run();
+ $this->container['cli']->run();
} else {
$this->request = new IPF_HTTP_Request;
}
}
}
-
class IPF_Router
{
+ /** @var IPF_Route[] */
private $routes = array();
public function __construct()
return $this->matcher;
}
+ /**
+ * @return string
+ */
public function controller()
{
return \PFF\Arr::get($this->params, 'controller', 'IPF_Controller_Function');
}
+ /**
+ * @return string
+ */
public function action()
{
return \PFF\Arr::get($this->params, 'func', 'index');
class IPF_Session_App extends IPF_Application
{
-}
-
-
-abstract class Session
-{
- public static $backends = array(
- 'CookieSession',
- 'DBSession',
- );
+ /** @var SessionBackend[] */
+ private $backends;
- public static function get($key)
+ public function configure(\Pimple\Container $container, IPF_Settings $settings)
{
- if (!$key)
- return null;
-
- list($backend, $data) = self::detectBackend($key);
- if (!$backend)
- return null;
-
- $session = new $backend($key, $data);
-
- if ($session->expired()) {
- $session->delete();
- return null;
- }
-
- return $session;
+ $this->backends = [
+ new CookieSessionBackend(),
+ new DBSessionBackend($container, $settings->get('secret_key')),
+ ];
}
- private static function detectBackend($key)
+ /**
+ * @param string $session_cookie
+ * @return Session
+ */
+ public function getSession($session_cookie)
{
- foreach (self::$backends as $backend) {
- $data = $backend::getData($key);
- if ($data)
- return array($backend, $data);
+ $session = $this->detectSession($session_cookie);
+ if ($session && $session->expired()) {
+ $session->delete();
+ $session = null;
+ }
+ if ($session) {
+ return $session;
+ } else {
+ return new Session(null, array(), $this->backends[0]);
}
- return null;
- }
-
- public static function create()
- {
- $backend = self::$backends[0];
- return new $backend(null, array());
}
-
- protected $key = null;
- public $data = array();
-
- public function __construct($key, $data)
+ /**
+ * @param string $key
+ * @return Session
+ */
+ private function detectSession($key)
{
- $this->key = $key;
- $this->data = $data;
- }
+ if (!$key) {
+ return null;
+ }
- public function delete()
- {
- }
+ foreach ($this->backends as $backend) {
+ $data = $backend->getData($key);
+ if ($data)
+ return new Session($key, $data, $backend);
+ }
- public function cookie()
- {
- $this->data['updated_at'] = time();
- $this->save();
- return $this->key;
+ return null;
}
+}
- protected abstract function save();
-
- public function updatedAt()
- {
- return $this->data['updated_at'];
- }
- public function expired()
- {
- return time() - $this->updatedAt() > 60 * 60 * 24 * 7;
- }
+interface SessionBackend
+{
+ /**
+ * @param string $key
+ * @return array|null
+ */
+ public function getData($key);
+
+ /**
+ * @param string $key
+ * @param array $data
+ * @return string
+ */
+ public function save($key, $data);
+
+ /**
+ * @param string $key
+ */
+ public function delete($key);
}
-
-class CookieSession extends Session
+class CookieSessionBackend implements SessionBackend
{
- public static function getData($key)
+ public function getData($key)
{
$key = explode('|', $key, 2);
if (count($key) !== 2)
return unserialize(base64_decode($data));
}
- protected function save()
+ public function save($key, $data)
{
- $data = base64_encode(serialize($this->data));
- $this->key = $data.'|'.IPF_Crypto::sign($data);
+ $encoded = base64_encode(serialize($data));
+ return $encoded . '|' . IPF_Crypto::sign($encoded);
}
-}
+ public function delete($key)
+ {
+ // DO NOTHING
+ }
+}
-class DBSession extends Session
+class DBSessionBackend implements SessionBackend
{
- private static function getConnection()
+ /** @var \Pimple\Container */
+ private $container;
+ /** @var string */
+ private $secret_key;
+
+ public function __construct(Pimple\Container $container, $secret_key)
{
- return \PFF\Container::databaseConnection();
+ $this->container = $container;
+ $this->secret_key = $secret_key;
}
- public static function getData($key)
+ public function getData($key)
{
- $connection = self::getConnection();
+ $connection = $this->getDatabaseConnection();
$stmt = $connection->prepare('SELECT data FROM session WHERE session_key = :key');
$stmt->bindValue('key', $key, PDO::PARAM_STR);
$stmt->execute();
return null;
}
- public function delete()
+ public function save($key, $data)
{
- $connection = self::getConnection();
+ $connection = $this->getDatabaseConnection();
+ if ($key) {
+ $stmt = $connection->prepare('UPDATE session SET data = :data, updated_at = NOW() WHERE session_key = :key');
+ } else {
+ $key = $this->getNewSessionKey();
+ $stmt = $connection->prepare('INSERT INTO session (session_key, data) VALUES (:key, :data)');
+ }
+ $stmt->bindValue('key', $key, PDO::PARAM_STR);
+ $stmt->bindValue('data', serialize($data), PDO::PARAM_STR);
+ $stmt->execute();
+ return $key;
+ }
+
+ private function getNewSessionKey()
+ {
+ return md5(microtime() . rand(0, 123456789) . rand(0, 123456789) . $this->secret_key);
+ }
+
+ public function delete($key)
+ {
+ $connection = $this->getDatabaseConnection();
$stmt = $connection->prepare('DELETE FROM session WHERE session_key = :key');
- $stmt->bindValue('key', $this->key, PDO::PARAM_STR);
+ $stmt->bindValue('key', $key, PDO::PARAM_STR);
$stmt->execute();
+ }
+
+ /**
+ * @return \PDO
+ */
+ private function getDatabaseConnection()
+ {
+ return $this->container['databaseConnection'];
+ }
+}
+
+final class Session
+{
+ /** @var SessionBackend */
+ private $backend;
+ private $key = null;
+ public $data = array();
+
+ public function __construct($key, $data, SessionBackend $backend)
+ {
+ $this->key = $key;
+ $this->data = $data;
+ $this->backend = $backend;
+ }
+
+ public function delete()
+ {
+ $this->backend->delete($this->key);
$this->key = null;
}
- protected function save()
+ public function cookie()
{
- $connection = self::getConnection();
- if ($this->key) {
- $stmt = $connection->prepare('UPDATE session SET data = :data, updated_at = NOW() WHERE session_key = :key');
- } else {
- $this->key = self::getNewSessionKey();
- $stmt = $connection->prepare('INSERT INTO session (session_key, data) VALUES (:key, :data)');
- }
- $stmt->bindValue('key', $this->key, PDO::PARAM_STR);
- $stmt->bindValue('data', serialize($this->data), PDO::PARAM_STR);
- $stmt->execute();
+ $this->data['updated_at'] = time();
+ $this->key = $this->backend->save($this->key, $this->data);
+ return $this->key;
+ }
+
+ public function updatedAt()
+ {
+ return $this->data['updated_at'];
}
- private static function getNewSessionKey($secret_key=null)
+ public function expired()
{
- if (!$secret_key)
- $secret_key = IPF::get('secret_key');
- return md5(microtime().rand(0, 123456789).rand(0, 123456789).$secret_key);
+ return time() - $this->updatedAt() > 60 * 60 * 24 * 7;
}
}
{
function processRequest($request)
{
- $session_cookie = \PFF\Arr::get($request->COOKIE, $this->settings->get('session_cookie_id'));
-
- $request->session = Session::get($session_cookie);
- if (!$request->session)
- $request->session = Session::create();
+ /** @var IPF_Session_App $session_app */
+ $session_app = $this->container['apps']['session'];
+ $session_cookie = \PFF\Arr::get($request->COOKIE, $this->settings->get('session_cookie_id'));
+ $request->session = $session_app->getSession($session_cookie);
return false;
}
return $response;
}
}
-