]> git.andy128k.dev Git - ipf.git/commitdiff
introduce pimple as DI container
authorAndrey Kutejko <andy128k@gmail.com>
Thu, 14 Mar 2019 18:18:17 +0000 (19:18 +0100)
committerAndrey Kutejko <andy128k@gmail.com>
Fri, 15 Mar 2019 07:23:18 +0000 (08:23 +0100)
30 files changed:
composer.json
composer.lock
ipf/admin/app.php
ipf/admin/commands/syncperms.php
ipf/admin/component.php
ipf/admin/controllers/components.php
ipf/admin/controllers/dashboard.php
ipf/admin/controllers/user.php
ipf/admin/forms/login.php
ipf/admin/log.php
ipf/admin/section.php
ipf/admin/templates/admin/base.html
ipf/admin/templates/admin/change.html
ipf/admin/templates/admin/index.html
ipf/admin/templates/admin/items.html
ipf/application.php
ipf/auth/admin.php
ipf/auth/app.php
ipf/auth/commands/createsuperuser.php
ipf/auth/middleware.php
ipf/auth/models.php
ipf/cli.php
ipf/command/migrate.php
ipf/controller/base.php
ipf/middleware/base.php
ipf/middleware/dispatch.php
ipf/project.php
ipf/router.php
ipf/session/app.php
ipf/session/middleware.php

index 122b559b21121ff0646ef08e2bbd5847175aee69..01a35ace3ee035224bf94135835706ab1529bf40 100644 (file)
@@ -23,7 +23,8 @@
     "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"
index 348c147a8e1c57e4c4a2f0188b722c1d09565be1..6c907b7ba09898c85214da69ddefde2c007bac76 100644 (file)
@@ -4,7 +4,7 @@
         "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": [
index cfd0c08db3f1ecb4aed25949b70526fae61fc4b1..ab04895faf0058839f5725d3f6d461deccaf2fcf 100644 (file)
@@ -1,9 +1,23 @@
 <?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(
@@ -36,13 +50,21 @@ class IPF_Admin_App extends IPF_Application
 
     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),
+                    );
                 }
             }
 
@@ -68,6 +90,10 @@ class IPF_Admin_App extends IPF_Application
 
     private $appComponents = array();
 
+    /**
+     * @param IPF_Application $app
+     * @return IPF_Admin_Component[]
+     */
     public function applicationComponents($app)
     {
         if (!array_key_exists($app->slug(), $this->appComponents)) {
@@ -79,8 +105,10 @@ class IPF_Admin_App extends IPF_Application
                     $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;
                 }
             }
@@ -92,7 +120,10 @@ class IPF_Admin_App extends IPF_Application
 
     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;
@@ -113,7 +144,7 @@ class IPF_Admin_App extends IPF_Application
     public function commands()
     {
         return array(
-            new IPF_Admin_Command_SyncPerms($this),
+            new IPF_Admin_Command_SyncPerms($this, $this->container['db']),
         );
     }
 }
@@ -133,4 +164,3 @@ class IPF_Admin_AccessDenied extends IPF_Router_Shortcut
         return new IPF_HTTP_Response_NotFound($request);
     }
 }
-
index 3fa8e7b8eadc0606f48fca0707f6ba88c504fa2b..7210c41a3b3d148857f04ad49fe10683b5974c9f 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Doctrine\DBAL\Connection;
+
 class IPF_Admin_Command_SyncPerms
 {
     public $command = 'syncperms';
@@ -8,9 +10,13 @@ class IPF_Admin_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)
@@ -54,8 +60,7 @@ class IPF_Admin_Command_SyncPerms
 
     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) {
@@ -66,16 +71,14 @@ class IPF_Admin_Command_SyncPerms
 
     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();
     }
index 4d32842cc560acbe70c17347d043c2c25d594abc..272ee7452ba094353b5882b6867338e6c6f93e47 100644 (file)
@@ -1,8 +1,8 @@
 <?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
 {
@@ -16,6 +16,10 @@ abstract class IPF_Admin_Component
 {
     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()
     {
@@ -38,25 +42,20 @@ abstract class IPF_Admin_Component
         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)
@@ -184,7 +183,7 @@ abstract class IPF_Admin_Component
 
             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;
@@ -206,6 +205,9 @@ abstract class IPF_Admin_Component
             '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),
         ));
     }
 
@@ -216,7 +218,7 @@ abstract class IPF_Admin_Component
             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();
         }
@@ -243,7 +245,7 @@ abstract class IPF_Admin_Component
 
             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;
@@ -280,6 +282,9 @@ abstract class IPF_Admin_Component
             '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),
         ));
     }
 
@@ -356,6 +361,7 @@ abstract class IPF_Admin_Component
             'filters' => $filters,
             'is_search' => $this->searcheable(),
             'search_value' => $searchValue,
+            'can_add' => $this->isAccessible(array('add'), $this->request),
         ));
     }
 
index 86b0e5da9d66f100884726a713177dc6e3af1653..77861737efba94be7bf258a3e927d36aa817154c 100644 (file)
@@ -69,6 +69,7 @@ class IPF_Admin_Components_Controller extends IPF_Admin_Base_Controller
 
     protected function checkPermissions()
     {
+        $connection = $this->container['db'];
         $requiredPermissions = func_get_args();
         if (!$this->component->isAccessible($requiredPermissions, $this->request))
             throw new IPF_Admin_AccessDenied;
index 277b4e37f537e1aa73585af440c8be3fd605391b..35d514bc131f3a88e189a3afb5a2f5a36ccc7028 100644 (file)
@@ -2,13 +2,21 @@
 
 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);
     }
@@ -19,7 +27,7 @@ class IPF_Admin_Dashboard_Controller extends IPF_Admin_Base_Controller
         if (!$currentPage)
             $currentPage = 1;
 
-        $count = IPF_Admin_Log::count();
+        $count = $this->adminLog()->count();
 
         $perPage = 20;
         $pagerLayout = new IPF_Pager_Layout;
@@ -27,7 +35,7 @@ class IPF_Admin_Dashboard_Controller extends IPF_Admin_Base_Controller
 
         $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,
@@ -35,4 +43,3 @@ class IPF_Admin_Dashboard_Controller extends IPF_Admin_Base_Controller
         return $this->render('admin/log.html', $context);
     }
 }
-
index 00319fa47a54bdc7e01960bbca0ff06eecc0f7ab..8a5613922ce20dd4f8b47d76f86f992f99378ced 100644 (file)
@@ -20,14 +20,16 @@ class IPF_Admin_User_Controller extends IPF_Admin_Base_Controller
         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(
index b05b32f8a48e429befea93cd4515ce8404a49a2c..55289f327e94b40bd4ef6dfc95057027283ddc80 100644 (file)
@@ -5,8 +5,13 @@ class IPF_Admin_Forms_Login extends IPF_Form
     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'));
@@ -16,7 +21,7 @@ class IPF_Admin_Forms_Login extends IPF_Form
     {
         $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.'));
 
@@ -29,4 +34,3 @@ class IPF_Admin_Forms_Login extends IPF_Form
         return $this->renderLayout(new IPF_Admin_Form_Layout);
     }
 }
-
index 747cbbdf5396b0108f6087d89bfb5800ffee05f7..3750655213daadeac910eebdd0c2717fad4b8b48 100644 (file)
@@ -1,30 +1,71 @@
 <?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)'
@@ -38,9 +79,11 @@ class IPF_Admin_Log
         $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);
     }
 }
index 1f2cac7051c4931d113862e57e253ce129d5aa0f..ac528787d07d62672227d9371cd8c16a7037b7fa 100644 (file)
@@ -1,13 +1,15 @@
 <?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
@@ -21,11 +23,11 @@ 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) {
index 882bccd2da17780139c13665bacf44055d1a7c80..d4dee94875edc821a474dd7c29ac41912eb83930 100644 (file)
@@ -45,7 +45,7 @@
             <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>
index a8482dd77ba89e5566196352918a7950a649034b..2126e49072ec698759215fc4f678c08636677d7e 100644 (file)
@@ -44,9 +44,9 @@
               {/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>
index 95b300b077cb20fded71abf5ba411f16ce39a125..88f673bda5f16b408f6ec8a6bc6f4c694ef3cedf 100644 (file)
@@ -14,9 +14,9 @@
                <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>
index bbf31c8d7518bfc4adb23f77ef5543f5f909ef6b..6b48a6da71d3da7684948cc853066e1850d7d82e 100644 (file)
@@ -8,7 +8,7 @@
   <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>
index 71bb436abc2bb49ed662bdc18129a52786bc9465..3c6da45efbf47816ebef1c484b28944fa8905136 100644 (file)
@@ -2,54 +2,35 @@
 
 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))));
     }
 
     /**
index 5d222d2372fe95a76aa37517ab7a705aacecbad0..7f35324a84de23556ae96d5ec9358005c83bc782 100644 (file)
@@ -2,13 +2,17 @@
 
 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
 {
@@ -18,6 +22,7 @@ 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'];
 
@@ -78,7 +83,7 @@ class UserForm extends \IPF_ObjectForm
             $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,
             ));
         }
 
@@ -109,16 +114,13 @@ class UserForm extends \IPF_ObjectForm
 
 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;
     }
 
     /**
@@ -129,10 +131,13 @@ abstract class Component extends \IPF_Admin_Component
         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;
 
@@ -140,7 +145,7 @@ abstract class Component extends \IPF_Admin_Component
             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);
 
@@ -155,15 +160,22 @@ abstract class Component extends \IPF_Admin_Component
         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 .
@@ -174,7 +186,7 @@ class AdminUser extends Component
 
     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()
@@ -194,7 +206,7 @@ class AdminUser extends Component
 
     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()
@@ -224,14 +236,17 @@ class AdminUser extends Component
 
     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 {
@@ -242,22 +257,24 @@ class AdminUser extends Component
 
     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);
@@ -265,13 +282,15 @@ class AdminUser extends Component
 
     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)),
         );
     }
 
@@ -305,18 +324,17 @@ class AdminRole extends Component
 {
     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()
@@ -340,19 +358,21 @@ class AdminRole extends Component
 
     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 {
@@ -362,22 +382,24 @@ class AdminRole extends Component
 
     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'); }
@@ -387,16 +409,21 @@ class AdminRole extends Component
 
 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;
index 15190507e86e7b063e6ce28de4f137112e128a11..1ad4ca982d3d5092d829338dead7aa5caee11722 100644 (file)
@@ -1,11 +1,25 @@
 <?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');
     }
 
@@ -16,13 +30,13 @@ class IPF_Auth_App extends IPF_Application
 
     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]);
     }
 
@@ -53,15 +67,31 @@ class IPF_Auth_App extends IPF_Application
     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'];
+    }
 }
index fa88d93db9450db24511a665c99402e3fc06c99e..43a179daaa16d9ff649674abc95f009a33cec67d 100644 (file)
@@ -7,6 +7,14 @@ class CreateSuperUser
     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";
@@ -15,7 +23,7 @@ class CreateSuperUser
         $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;
@@ -26,4 +34,3 @@ class CreateSuperUser
         print "Done\n";
     }
 }
-
index 2d203c852cea1fa9b4ccdaf6a750715c83d82af1..ee2d567892900a270930a7d9ab4dc77a8d440dcb 100644 (file)
@@ -12,7 +12,8 @@ class Middleware extends \IPF_Middleware
 
         $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();
@@ -31,4 +32,3 @@ class Middleware extends \IPF_Middleware
         return $response;
     }
 }
-
index 378ff8d767bd04dc9a7d1cc70bf27a304dd5ad65..4af576722ca6de03f8b621c2384a37442d898b28 100644 (file)
@@ -2,24 +2,15 @@
 
 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);
 
@@ -35,7 +26,6 @@ abstract class DBObject
             $values[$name] = $value;
         }
 
-        $connection = \PFF\Container::db();
         if ($this->id) {
             $connection->update($this->table, $values, ['id' => $this->id]);
         } else {
@@ -59,7 +49,7 @@ class AnonymousUser
         return true;
     }
 
-    public function can(/* $permission ... */)
+    public function can(Connection $connection, ...$permissions)
     {
         return false;
     }
@@ -101,29 +91,25 @@ class User extends DBObject
         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' .
@@ -133,16 +119,14 @@ class User extends DBObject
             ' 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;
@@ -157,7 +141,7 @@ class User extends DBObject
             }
         }
 
-        return $this->effectivePermissions()
+        return $this->effectivePermissions($connection)
             ->select(null)->select('COUNT(1)')
             ->where(implode(' OR ', $cond), $params)
             ->fetchColumn() == count($params);
@@ -185,6 +169,7 @@ class User extends DBObject
 class Role extends DBObject
 {
     protected $table = 'auth_role';
+    /** @var string */
     public $name;
 
     public function __toString()
@@ -192,51 +177,46 @@ class Role extends DBObject
         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);
     }
 }
 
@@ -245,30 +225,27 @@ class Permission extends DBObject
     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;
@@ -277,25 +254,24 @@ class Permission extends DBObject
         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);
     }
 
index 58df0215eabfb540b64a266f4d4f20f24519f78d..bf69e69f8a32c430fa92263ae787c08f9d2eabbe 100644 (file)
@@ -8,23 +8,15 @@
     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,
@@ -35,24 +27,54 @@ class IPF_Cli
                 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)
@@ -64,7 +86,7 @@ class IPF_Cli
         return null;
     }
 
-    protected function usage()
+    private function usage()
     {
         print "Usage: php index.php <subcommand> [options] [args]\n";
 
index ed50c45c6ce7d58906ba209ea282c2ee13cc7fd0..2535ec96338ac963a61b0f9491eb412ff84e3075 100644 (file)
@@ -1,22 +1,31 @@
 <?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);
     }
 }
-
index 6e0b7cc7c3d51cb2f47e0df53487a32af66b01f8..2b12d41fbb506b7d157ef031019499af641c2148 100644 (file)
@@ -1,15 +1,20 @@
 <?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)
index 42e289607d77631a3de3362c7a68249de8f82195..5a493d163af16b34ba6ccfe52d0e6a7416154cf5 100644 (file)
@@ -1,26 +1,33 @@
 <?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)
index abfe8f42ee0bb61b177a8079117174f0a2fc1d37..01ff379a01947bd31a593bd93fb9bb9495e859c4 100644 (file)
@@ -15,8 +15,9 @@ class IPF_Dispatch_Middleware extends IPF_Middleware
         $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);
index c54bb2a14aeb42b4365bcad7062edf088d4448d5..d66551c1ca918a943872b8f038f57125ea65e288 100644 (file)
@@ -1,7 +1,11 @@
 <?php
 
+use Pimple\Container;
+
 final class IPF_Project
 {
+    /** @var Container */
+    private $container = null;
     private $apps = array();
     public $router = null;
     public $request = null;
@@ -17,16 +21,23 @@ final class IPF_Project
 
     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()
@@ -46,25 +57,28 @@ final class IPF_Project
 
         $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;
 
@@ -75,4 +89,3 @@ final class IPF_Project
         }
     }
 }
-
index bceeb36391d175be8076d0b215ccb9d15bcc5f75..0572b6a094602a4046fb845c1a2498cc671cae28 100644 (file)
@@ -2,6 +2,7 @@
 
 class IPF_Router
 {
+    /** @var IPF_Route[] */
     private $routes = array();
 
     public function __construct()
@@ -143,11 +144,17 @@ class IPF_Route
         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');
index 61db6790f343f35b9f07f77dc6378ac59909430c..d94f59672c505fe0987c02853d12edc80cbaf2ba 100644 (file)
@@ -2,89 +2,80 @@
 
 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)
@@ -96,24 +87,34 @@ class CookieSession extends Session
         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();
@@ -124,34 +125,78 @@ class DBSession extends Session
             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;
     }
 }
index 5048976225bae0d9ee8e5fec2ea96f9df9759242..19e765e30dfc43e5e7e1a6ad46e8eb489012d3e1 100644 (file)
@@ -4,12 +4,11 @@ class IPF_Session_Middleware extends IPF_Middleware
 {
     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;
     }
 
@@ -20,4 +19,3 @@ class IPF_Session_Middleware extends IPF_Middleware
         return $response;
     }
 }
-