diff --git a/composer.json b/composer.json index b3331228..db5a199a 100755 --- a/composer.json +++ b/composer.json @@ -11,7 +11,9 @@ "require": { "php": ">=5.3.7", "phpmailer/phpmailer": "5.2.6", - "symfony/http-foundation": "2.4.*", + "symfony/config": "2.6.*", + "symfony/dependency-injection": "2.6.*", + "symfony/http-foundation": "2.6.*", "php-pushover/php-pushover": "dev-master", "twig/twig": "1.*" } diff --git a/composer.lock b/composer.lock index 48e948b7..451348f4 100644 --- a/composer.lock +++ b/composer.lock @@ -1,9 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], - "hash": "1d763e23381a086e18f83644bd89f16c", + "hash": "925f4c971570ca4d3a856019cdd79add", "packages": [ { "name": "php-pushover/php-pushover", @@ -84,19 +85,174 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "time": "2013-04-11 16:45:39" }, + { + "name": "symfony/config", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Config", + "source": { + "type": "git", + "url": "https://github.com/symfony/Config.git", + "reference": "a9f781ba1221067d1f07c8cec0bc50f81b8d7408" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Config/zipball/a9f781ba1221067d1f07c8cec0bc50f81b8d7408", + "reference": "a9f781ba1221067d1f07c8cec0bc50f81b8d7408", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/filesystem": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Config\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Config Component", + "homepage": "http://symfony.com", + "time": "2015-01-21 20:57:55" + }, + { + "name": "symfony/dependency-injection", + "version": "v2.6.4", + "target-dir": "Symfony/Component/DependencyInjection", + "source": { + "type": "git", + "url": "https://github.com/symfony/DependencyInjection.git", + "reference": "42bbb43fab66292a1865dc9616c299904c3d4d14" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/42bbb43fab66292a1865dc9616c299904c3d4d14", + "reference": "42bbb43fab66292a1865dc9616c299904c3d4d14", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "conflict": { + "symfony/expression-language": "<2.6" + }, + "require-dev": { + "symfony/config": "~2.2", + "symfony/expression-language": "~2.6", + "symfony/yaml": "~2.1" + }, + "suggest": { + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\DependencyInjection\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "http://symfony.com", + "time": "2015-01-25 04:39:26" + }, + { + "name": "symfony/filesystem", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Filesystem", + "source": { + "type": "git", + "url": "https://github.com/symfony/Filesystem.git", + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a1f566d1f92e142fa1593f4555d6d89e3044a9b7", + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Filesystem\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "http://symfony.com", + "time": "2015-01-03 21:13:09" + }, { "name": "symfony/http-foundation", - "version": "v2.4.8", + "version": "v2.6.4", "target-dir": "Symfony/Component/HttpFoundation", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation.git", - "reference": "68abe34601c519359b60363b99c29ecfb6679bc4" + "reference": "8fa63d614d56ccfe033e30411d90913cfc483ff6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/68abe34601c519359b60363b99c29ecfb6679bc4", - "reference": "68abe34601c519359b60363b99c29ecfb6679bc4", + "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/8fa63d614d56ccfe033e30411d90913cfc483ff6", + "reference": "8fa63d614d56ccfe033e30411d90913cfc483ff6", "shasum": "" }, "require": { @@ -108,7 +264,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.6-dev" } }, "autoload": { @@ -124,33 +280,31 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony HttpFoundation Component", "homepage": "http://symfony.com", - "time": "2014-07-15 14:07:10" + "time": "2015-02-01 16:10:57" }, { "name": "twig/twig", - "version": "v1.16.0", + "version": "v1.18.0", "source": { "type": "git", - "url": "https://github.com/fabpot/Twig.git", - "reference": "8ce37115802e257a984a82d38254884085060024" + "url": "https://github.com/twigphp/Twig.git", + "reference": "4cf7464348e7f9893a93f7096a90b73722be99cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/8ce37115802e257a984a82d38254884085060024", - "reference": "8ce37115802e257a984a82d38254884085060024", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/4cf7464348e7f9893a93f7096a90b73722be99cf", + "reference": "4cf7464348e7f9893a93f7096a90b73722be99cf", "shasum": "" }, "require": { @@ -159,7 +313,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.16-dev" + "dev-master": "1.18-dev" } }, "autoload": { @@ -185,7 +339,7 @@ }, { "name": "Twig Team", - "homepage": "https://github.com/fabpot/Twig/graphs/contributors", + "homepage": "http://twig.sensiolabs.org/contributors", "role": "Contributors" } ], @@ -194,23 +348,19 @@ "keywords": [ "templating" ], - "time": "2014-07-05 12:19:05" + "time": "2015-01-25 17:32:08" } ], - "packages-dev": [ - - ], - "aliases": [ - - ], + "packages-dev": [], + "aliases": [], "minimum-stability": "stable", "stability-flags": { "php-pushover/php-pushover": 20 }, + "prefer-stable": false, + "prefer-lowest": false, "platform": { "php": ">=5.3.7" }, - "platform-dev": [ - - ] + "platform-dev": [] } diff --git a/cron/status.cron.php b/cron/status.cron.php index dcfa8e12..01882636 100644 --- a/cron/status.cron.php +++ b/cron/status.cron.php @@ -26,7 +26,7 @@ **/ // include main configuration and functionality -require_once dirname(__FILE__) . '/../src/bootstrap.php'; +require_once __DIR__ . '/../src/bootstrap.php'; if(!psm_is_cli()) { die('This script can only be run from the command line.'); diff --git a/index.php b/index.php index 8088aee4..1e68c8b0 100644 --- a/index.php +++ b/index.php @@ -25,9 +25,24 @@ * @link http://www.phpservermonitor.org/ **/ -require 'src/bootstrap.php'; +require __DIR__ . '/src/bootstrap.php'; psm_no_cache(); -$router = new psm\Router(); -$router->run(); \ No newline at end of file +if(isset($_GET["logout"])) { + $router->getService('user')->doLogout(); + // logged out, redirect to login + header('Location: ' . psm_build_url()); + die(); +} + +$mod = psm_GET('mod', PSM_MODULE_DEFAULT); + +try { + $router->run($mod); +} catch(\InvalidArgumentException $e) { + // invalid module, try the default one + // it that somehow also doesnt exist, we have a bit of an issue + // and we really have no reason catch it + $router->run(PSM_MODULE_DEFAULT); +} \ No newline at end of file diff --git a/install.php b/install.php index 422d377b..b5a8bc4c 100644 --- a/install.php +++ b/install.php @@ -27,7 +27,6 @@ define('PSM_INSTALL', true); -require 'src/bootstrap.php'; +require __DIR__ . '/src/bootstrap.php'; -$router = new psm\Router(); $router->run('install'); diff --git a/src/bootstrap.php b/src/bootstrap.php index e650ce79..80bf6c8a 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -27,9 +27,8 @@ **/ // Include paths -define('PSM_PATH_SRC', dirname(__FILE__) . DIRECTORY_SEPARATOR); -define('PSM_PATH_INC', PSM_PATH_SRC . 'includes' . DIRECTORY_SEPARATOR); -define('PSM_PATH_TPL', PSM_PATH_SRC . 'templates' . DIRECTORY_SEPARATOR); +define('PSM_PATH_SRC', __DIR__ . DIRECTORY_SEPARATOR); +define('PSM_PATH_CONFIG', PSM_PATH_SRC . 'config' . DIRECTORY_SEPARATOR); define('PSM_PATH_LANG', PSM_PATH_SRC . 'lang' . DIRECTORY_SEPARATOR); // user levels @@ -64,7 +63,6 @@ if(!file_exists($vendor_autoload)) { } require_once $vendor_autoload; -// set autoloader, make sure to set $prepend = true so that our autoloader is called first spl_autoload_register(function($class) { // remove leading \ $class = ltrim($class, '\\'); @@ -81,13 +79,13 @@ spl_autoload_register(function($class) { } }); -// auto-find all include files -$includes = glob(PSM_PATH_INC . '*.inc.php'); +$includes = glob(PSM_PATH_SRC . 'includes/*.inc.php'); foreach($includes as $file) { include_once $file; } -// init db connection -$db = new psm\Service\Database(); +$router = new psm\Router(); +// this may seem insignificant, but right now lots of functions depend on the following global var definition: +$db = $router->getService('db'); // sanity check! if(!defined('PSM_INSTALL') || !PSM_INSTALL) { diff --git a/src/config/services.xml b/src/config/services.xml new file mode 100644 index 00000000..98b4577a --- /dev/null +++ b/src/config/services.xml @@ -0,0 +1,52 @@ + + + + + PSM_THEME + + PSM_PATH_SRC + %path.src%templates + + PSM_DB_HOST + PSM_DB_NAME + PSM_DB_USER + PSM_DB_PASS + + + + + + + + + + + + + + %db.host% + %db.name% + %db.user% + %db.pass% + + + + + + + %path.templates%/%config.theme% + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/includes/psmconfig.inc.php b/src/includes/psmconfig.inc.php index a7d486f0..bc620362 100644 --- a/src/includes/psmconfig.inc.php +++ b/src/includes/psmconfig.inc.php @@ -102,12 +102,6 @@ define('PSM_CRON_TIMEOUT', 600); */ define('PSM_CURL_TIMEOUT', 10); - -/** - * Name of the default theme. - */ -define('PSM_THEME', 'default'); - /** * Clone URL for the Pushover.net service. */ @@ -118,3 +112,17 @@ define('PSM_PUSHOVER_CLONE_URL', 'https://pushover.net/apps/clone/php_server_mon * Useful for cronjobs if it cannot be auto-detected. */ //define('PSM_BASE_URL', null); + +if(!defined('PSM_MODULE_DEFAULT')) { + /** + * Default theme + */ + define('PSM_THEME', 'default'); +} + +if(!defined('PSM_MODULE_DEFAULT')) { + /** + * Default module (if none given or invalid one) + */ + define('PSM_MODULE_DEFAULT', 'server_status'); +} diff --git a/src/psm/Module/AbstractController.class.php b/src/psm/Module/AbstractController.class.php index 486e3859..d9b37676 100644 --- a/src/psm/Module/AbstractController.class.php +++ b/src/psm/Module/AbstractController.class.php @@ -28,8 +28,9 @@ namespace psm\Module; use psm\Service\Database; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\DependencyInjection\ContainerAware; -abstract class AbstractController implements ControllerInterface { +abstract class AbstractController extends ContainerAware implements ControllerInterface { /** * Current action @@ -174,9 +175,7 @@ abstract class AbstractController implements ControllerInterface { */ protected function initializeAction($action) { if(isset($this->user_level_required_actions[$action])) { - $ulvl = ($this->user) ? $this->user->getUserLevel() : PSM_USER_ANONYMOUS; - - if($ulvl > $this->user_level_required_actions[$action]) { + if($this->getUser()->getUserLevel() > $this->user_level_required_actions[$action]) { // user is not allowed to access this action.. return false; } @@ -252,7 +251,7 @@ abstract class AbstractController implements ControllerInterface { * @return string */ protected function createHTMLMenu() { - $ulvl = ($this->user) ? $this->user->getUserLevel() : PSM_USER_ANONYMOUS; + $ulvl = $this->getUser()->getUserLevel(); $tpl_data = array( 'label_help' => psm_get_lang('menu', 'help'), @@ -283,7 +282,7 @@ abstract class AbstractController implements ControllerInterface { } if($ulvl != PSM_USER_ANONYMOUS) { - $user = $this->user->getUser(); + $user = $this->getUser()->getUser(); $tpl_data['label_usermenu'] = str_replace( '%user_name%', $user->name, @@ -391,14 +390,6 @@ abstract class AbstractController implements ControllerInterface { return $msgs; } - /** - * Set user service - * @param \psm\Service\User $user - */ - public function setUser(\psm\Service\User $user) { - $this->user = $user; - } - /** * Set the minimum required user level for this controller * @param int $level @@ -471,4 +462,12 @@ abstract class AbstractController implements ControllerInterface { public function isXHR() { return $this->xhr; } + + /** + * Get user service + * @return \psm\Service\User + */ + public function getUser() { + return $this->container->get('user'); + } } diff --git a/src/psm/Module/Config/Controller/ConfigController.class.php b/src/psm/Module/Config/Controller/ConfigController.class.php index c5d748a1..045215d7 100644 --- a/src/psm/Module/Config/Controller/ConfigController.class.php +++ b/src/psm/Module/Config/Controller/ConfigController.class.php @@ -211,7 +211,7 @@ class ConfigController extends AbstractController { $mail->Priority = 1; $mail->Body = $message; $mail->AltBody = str_replace('
', "\n", $message); - $user = $this->user->getUser(); + $user = $this->getUser()->getUser(); $mail->AddAddress($user->email, $user->name); if($mail->Send()) { $this->addMessage(psm_get_lang('config', 'email_sent'), 'success'); @@ -228,7 +228,7 @@ class ConfigController extends AbstractController { protected function testSMS() { $sms = psm_build_sms(); if($sms) { - $user = $this->user->getUser(); + $user = $this->getUser()->getUser(); if(empty($user->mobile)) { $this->addMessage(psm_get_lang('config', 'sms_error_nomobile'), 'error'); } else { @@ -250,7 +250,7 @@ class ConfigController extends AbstractController { protected function testPushover() { $pushover = psm_build_pushover(); $pushover->setDebug(true); - $user = $this->user->getUser(); + $user = $this->getUser()->getUser(); $api_token = psm_get_conf('pushover_api_token'); if(empty($api_token)) { diff --git a/src/psm/Module/ControllerInterface.class.php b/src/psm/Module/ControllerInterface.class.php index fb63e012..834300af 100644 --- a/src/psm/Module/ControllerInterface.class.php +++ b/src/psm/Module/ControllerInterface.class.php @@ -28,8 +28,9 @@ namespace psm\Module; use psm\Service\Database; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; -interface ControllerInterface { +interface ControllerInterface extends ContainerAwareInterface { public function __construct(Database $db, \Twig_Environment $twig); diff --git a/src/psm/Module/Install/Controller/InstallController.class.php b/src/psm/Module/Install/Controller/InstallController.class.php index 0b663ad0..06524091 100644 --- a/src/psm/Module/Install/Controller/InstallController.class.php +++ b/src/psm/Module/Install/Controller/InstallController.class.php @@ -212,7 +212,7 @@ class InstallController extends AbstractController { 'pushover_device' => '', ); - $validator = new \psm\Util\User\UserValidator($this->user); + $validator = $this->container->get('util.user.validator'); $logger = array($this, 'addMessage'); $installer = new \psm\Util\Install\Installer($this->db, $logger); @@ -257,7 +257,7 @@ class InstallController extends AbstractController { unset($new_user['password_repeat']); $user_id = $this->db->save(PSM_DB_PREFIX.'users', $new_user); if(intval($user_id) > 0) { - $this->user->changePassword($user_id, $new_user['password']); + $this->getUser()->changePassword($user_id, $new_user['password']); $this->addMessage('User account has been created successfully.', 'success'); } else { $this->addMessage('There was an error adding your user account.', 'error'); diff --git a/src/psm/Module/Server/Controller/AbstractServerController.class.php b/src/psm/Module/Server/Controller/AbstractServerController.class.php index f009feaf..187c2360 100644 --- a/src/psm/Module/Server/Controller/AbstractServerController.class.php +++ b/src/psm/Module/Server/Controller/AbstractServerController.class.php @@ -45,10 +45,10 @@ abstract class AbstractServerController extends AbstractController { $sql_join = ''; $sql_where = ''; - if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) { + if($this->getUser()->getUserLevel() > PSM_USER_ADMIN) { // restrict by user_id $sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( - `us`.`user_id`={$this->user->getUserId()} + `us`.`user_id`={$this->getUser()->getUserId()} AND `us`.`server_id`=`s`.`server_id` )"; } diff --git a/src/psm/Module/Server/Controller/LogController.class.php b/src/psm/Module/Server/Controller/LogController.class.php index 25470de6..951df2ba 100644 --- a/src/psm/Module/Server/Controller/LogController.class.php +++ b/src/psm/Module/Server/Controller/LogController.class.php @@ -122,10 +122,10 @@ class LogController extends AbstractServerController { */ public function getEntries($type) { $sql_join = ''; - if($this->user != null && $this->user->getUserLevel() > PSM_USER_ADMIN) { + if($this->getUser()->getUserLevel() > PSM_USER_ADMIN) { // restrict by user_id $sql_join = "JOIN `".PSM_DB_PREFIX."users_servers` AS `us` ON ( - `us`.`user_id`={$this->user->getUserId()} + `us`.`user_id`={$this->getUser()->getUserId()} AND `us`.`server_id`=`servers`.`server_id` )"; } diff --git a/src/psm/Module/Server/Controller/ServerController.class.php b/src/psm/Module/Server/Controller/ServerController.class.php index bd3bae09..1b3ec39e 100644 --- a/src/psm/Module/Server/Controller/ServerController.class.php +++ b/src/psm/Module/Server/Controller/ServerController.class.php @@ -60,12 +60,12 @@ class ServerController extends AbstractServerController { */ protected function executeIndex() { $tpl_data = $this->getLabels(); - $tpl_data['user_level'] = $this->user->getUserLevel(); + $tpl_data['user_level'] = $this->getUser()->getUserLevel(); $sidebar = new \psm\Util\Module\Sidebar($this->twig); $this->setSidebar($sidebar); // check if user is admin, in that case we add the buttons - if($this->user->getUserLevel() == PSM_USER_ADMIN) { + if($this->getUser()->getUserLevel() == PSM_USER_ADMIN) { $modal = new \psm\Util\Module\Modal($this->twig, 'delete', \psm\Util\Module\Modal::MODAL_TYPE_DANGER); $this->addModal($modal); $modal->setTitle(psm_get_lang('servers', 'delete_title')); @@ -345,7 +345,7 @@ class ServerController extends AbstractServerController { $tpl_data['html_history'] = $history->createHTML($this->server_id); // add edit/delete buttons for admins - if($this->user->getUserLevel() == PSM_USER_ADMIN) { + if($this->getUser()->getUserLevel() == PSM_USER_ADMIN) { $tpl_data['has_admin_actions'] = true; $tpl_data['url_edit'] = psm_build_url(array('mod' => 'server', 'action' => 'edit', 'id' => $this->server_id, 'back_to' => 'view')); diff --git a/src/psm/Module/Server/Controller/StatusController.class.php b/src/psm/Module/Server/Controller/StatusController.class.php index 42385d4c..4ef5aca9 100644 --- a/src/psm/Module/Server/Controller/StatusController.class.php +++ b/src/psm/Module/Server/Controller/StatusController.class.php @@ -50,7 +50,7 @@ class StatusController extends AbstractServerController { $this->twig->addGlobal('subtitle', psm_get_lang('menu', 'server_status')); // add header accessories - $layout = $this->user->getUserPref('status_layout', 0); + $layout = $this->getUser()->getUserPref('status_layout', 0); $layout_data = array( 'label_last_check' => psm_get_lang('servers', 'last_check'), 'label_last_online' => psm_get_lang('servers', 'last_online'), @@ -97,7 +97,7 @@ class StatusController extends AbstractServerController { protected function executeSaveLayout() { if($this->isXHR()) { $layout = psm_POST('layout', 0); - $this->user->setUserPref('status_layout', $layout); + $this->getUser()->setUserPref('status_layout', $layout); $response = new \Symfony\Component\HttpFoundation\JsonResponse(); $response->setData(array( diff --git a/src/psm/Module/Server/Controller/UpdateController.class.php b/src/psm/Module/Server/Controller/UpdateController.class.php index c2f07ef5..94a3f64a 100644 --- a/src/psm/Module/Server/Controller/UpdateController.class.php +++ b/src/psm/Module/Server/Controller/UpdateController.class.php @@ -41,7 +41,7 @@ class UpdateController extends AbstractController { protected function executeIndex() { $autorun = new \psm\Util\Server\UpdateManager($this->db); - $autorun->setUser($this->user); + $autorun->setUser($this->getUser()); $autorun->run(); header('Location: ' . psm_build_url(array( diff --git a/src/psm/Module/User/Controller/LoginController.class.php b/src/psm/Module/User/Controller/LoginController.class.php index d04d03e7..d8cfc13e 100644 --- a/src/psm/Module/User/Controller/LoginController.class.php +++ b/src/psm/Module/User/Controller/LoginController.class.php @@ -47,7 +47,7 @@ class LoginController extends AbstractController { protected function executeLogin() { if(isset($_POST['user_name']) && isset($_POST['user_password'])) { $rememberme = (isset($_POST['user_rememberme'])) ? true : false; - $result = $this->user->loginWithPostData( + $result = $this->getUser()->loginWithPostData( $_POST['user_name'], $_POST['user_password'], $rememberme @@ -83,10 +83,10 @@ class LoginController extends AbstractController { */ protected function executeForgot() { if(isset($_POST['user_name'])) { - $user = $this->user->getUserByUsername($_POST['user_name']); + $user = $this->getUser()->getUserByUsername($_POST['user_name']); if(!empty($user)) { - $token = $this->user->generatePasswordResetToken($user->user_id); + $token = $this->getUser()->generatePasswordResetToken($user->user_id); // we have a token, send it along $this->sendPasswordForgotMail( $user->user_id, @@ -114,10 +114,11 @@ class LoginController extends AbstractController { * Show/process the password reset form (after the mail) */ protected function executeReset() { + $service_user = $this->getUser(); $user_id = (isset($_GET['user_id'])) ? intval($_GET['user_id']) : 0; $token = (isset($_GET['token'])) ? $_GET['token'] : ''; - if(!$this->user->verifyPasswordResetToken($user_id, $token)) { + if(!$service_user->verifyPasswordResetToken($user_id, $token)) { $this->addMessage(psm_get_lang('login', 'error_reset_invalid_link'), 'error'); return $this->executeLogin(); } @@ -126,7 +127,7 @@ class LoginController extends AbstractController { if($_POST['user_password_new'] !== $_POST['user_password_repeat']) { $this->addMessage(psm_get_lang('login', 'error_login_passwords_nomatch'), 'error'); } else { - $result = $this->user->changePassword($user_id, $_POST['user_password_new']); + $result = $service_user->changePassword($user_id, $_POST['user_password_new']); if($result) { $this->addMessage(psm_get_lang('login', 'success_password_reset'), 'success'); @@ -136,7 +137,7 @@ class LoginController extends AbstractController { } } } - $user = $this->user->getUser($user_id); + $user = $service_user->getUser($user_id); $tpl_data = array( 'title_reset' => psm_get_lang('login', 'title_reset'), diff --git a/src/psm/Module/User/Controller/ProfileController.class.php b/src/psm/Module/User/Controller/ProfileController.class.php index 941cee64..2a17eba0 100644 --- a/src/psm/Module/User/Controller/ProfileController.class.php +++ b/src/psm/Module/User/Controller/ProfileController.class.php @@ -51,7 +51,7 @@ class ProfileController extends AbstractController { */ protected function executeIndex() { $this->twig->addGlobal('subtitle', psm_get_lang('users', 'profile')); - $user = $this->user->getUser(null, true); + $user = $this->getUser()->getUser(null, true); $tpl_data = array( 'label_name' => psm_get_lang('users', 'name'), @@ -88,8 +88,7 @@ class ProfileController extends AbstractController { // dont process anything if no data has been posted return $this->executeIndex(); } - $validator = new \psm\Util\User\UserValidator($this->user); - $user = $this->user->getUser(); + $validator = $this->container->get('util.user.validator'); $fields = $this->profile_fields; $fields[] = 'password'; $fields[] = 'password_repeat'; @@ -105,7 +104,7 @@ class ProfileController extends AbstractController { // validate the lot try { - $validator->username($clean['user_name'], $this->user->getUserId()); + $validator->username($clean['user_name'], $this->getUser()->getUserId()); $validator->email($clean['email']); // always validate password for new users, @@ -123,9 +122,9 @@ class ProfileController extends AbstractController { unset($clean['password']); unset($clean['password_repeat']); - $this->db->save(PSM_DB_PREFIX.'users', $clean, array('user_id' => $this->user->getUserId())); + $this->db->save(PSM_DB_PREFIX.'users', $clean, array('user_id' => $this->getUser()->getUserId())); if(isset($password)) { - $this->user->changePassword($this->user->getUserId(), $password); + $this->getUser()->changePassword($this->getUser()->getUserId(), $password); } $this->addMessage(psm_get_lang('users', 'profile_updated'), 'success'); diff --git a/src/psm/Module/User/Controller/UserController.class.php b/src/psm/Module/User/Controller/UserController.class.php index 669a53fb..bcfa0e0c 100644 --- a/src/psm/Module/User/Controller/UserController.class.php +++ b/src/psm/Module/User/Controller/UserController.class.php @@ -36,12 +36,6 @@ use psm\Service\Database; class UserController extends AbstractController { public $servers; - /** - * User data validator - * @var \psm\Util\User\UserValidator $user_validator - */ - protected $user_validator; - function __construct(Database $db, \Twig_Environment $twig) { parent::__construct($db, $twig); @@ -54,7 +48,6 @@ class UserController extends AbstractController { } public function initialize() { - $this->user_validator = new \psm\Util\User\UserValidator($this->user); $servers = $this->db->select(PSM_DB_PREFIX.'servers', null, array('server_id', 'label'), '', "ORDER BY `active` ASC, `status` DESC, `label` ASC"); // change the indexes to reflect their server ids foreach($servers as $server) { @@ -160,12 +153,12 @@ class UserController extends AbstractController { } else { // edit mode try { - $this->user_validator->userId($user_id); + $this->container->get('util.user.validator')->userId($user_id); } catch(\InvalidArgumentException $e) { $this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error'); return $this->executeIndex(); } - $edit_user = $this->user->getUser($user_id); + $edit_user = $this->getUser()->getUser($user_id); $title = psm_get_lang('system', 'edit') . ' ' . $edit_user->name; $placeholder_password = psm_get_lang('users', 'password_leave_blank'); $lvl_selected = $edit_user->level; @@ -199,7 +192,7 @@ class UserController extends AbstractController { } $tpl_data['levels'] = array(); - foreach($this->user_validator->getUserLevels() as $lvl) { + foreach($this->container->get('util.user.validator')->getUserLevels() as $lvl) { $tpl_data['levels'][] = array( 'value' => $lvl, 'label' => psm_get_lang('users', 'level_' . $lvl), @@ -231,19 +224,20 @@ class UserController extends AbstractController { } } - // validate the lot + $user_validator = $this->container->get('util.user.validator'); + try { - $this->user_validator->username($clean['user_name'], $user_id); - $this->user_validator->email($clean['email']); - $this->user_validator->level($clean['level']); + $user_validator->username($clean['user_name'], $user_id); + $user_validator->email($clean['email']); + $user_validator->level($clean['level']); // always validate password for new users, // but only validate it for existing users when they change it. if($user_id == 0 || ($user_id > 0 && $clean['password'] != '')) { - $this->user_validator->password($clean['password'], $clean['password_repeat']); + $user_validator->password($clean['password'], $clean['password_repeat']); } if($user_id > 0) { - $this->user_validator->userId($user_id); + $user_validator->userId($user_id); } } catch(\InvalidArgumentException $e) { $this->addMessage(psm_get_lang('users', 'error_' . $e->getMessage()), 'error'); @@ -266,7 +260,7 @@ class UserController extends AbstractController { $this->addMessage(psm_get_lang('users', 'inserted'), 'success'); } if(isset($password)) { - $this->user->changePassword($user_id, $password); + $this->getUser()->changePassword($user_id, $password); } // update servers @@ -296,7 +290,7 @@ class UserController extends AbstractController { $id = (isset($_GET['id'])) ? intval($_GET['id']) : 0; try { - $this->user_validator->userId($id); + $this->container->get('util.user.validator')->userId($id); $this->db->delete(PSM_DB_PREFIX . 'users', array('user_id' => $id,)); $this->db->delete(PSM_DB_PREFIX.'users_servers', array('user_id' => $id)); diff --git a/src/psm/Router.class.php b/src/psm/Router.class.php index f2c6b315..ffd72e6a 100644 --- a/src/psm/Router.class.php +++ b/src/psm/Router.class.php @@ -23,20 +23,20 @@ * @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3 * @version Release: @package_version@ * @link http://www.phpservermonitor.org/ - * @since phpservermon 3.0 + * @since phpservermon 3.0 **/ namespace psm; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; /** * The router class opens the controller and initializes the module. * - * The router has the list of available modules, and it will check them for - * available controllers. * It uses a so-called $mod param to determine which controller to load. - * The $mod can either be passed as GET var or directly to the run() method. - * The $mod has 2 components, separated by an underscore. The first part determines + * The $mod of run() has 2 components, separated by an underscore. The first part determines * the module to load, the second on the controller. It uses the keys defined in * the module config. If the controller part is absent, it will always try to load * the controller with the same name as the module. @@ -44,103 +44,51 @@ use Symfony\Component\HttpFoundation\Response; class Router { /** - * Default module (if none given or invalid one) - * @var string $default_module + * Service container + * @var \Symfony\Component\DependencyInjection\ContainerBuilder $container */ - public $default_module = 'server_status'; - - /** - * Controller map - * @var array $map - */ - protected $map = array(); - - /** - * Registered services - * @var array $services - */ - protected $services = array(); + protected $container; public function __construct() { - global $db; - $this->services['db'] = $db; - $this->services['user'] = new \psm\Service\User($db); - - $loader = new \Twig_Loader_Filesystem(PSM_PATH_TPL . PSM_THEME); - $this->services['twig'] = new \Twig_Environment($loader); - if(PSM_DEBUG) { - $this->services['twig']->enableDebug(); - } - - $modules = $this->getModules(); - - foreach($modules as $id => $module) { - $this->map[$id] = $module->getControllers(); - } + $this->container = $this->buildServiceContainer(); } /** - * Get registered modules - * - * Note, the index of each module is also the key used for mapping getvars. - * @return array - */ - public function getModules() { - return array( - 'config' => new Module\Config\ConfigModule(), - 'error' => new Module\Error\ErrorModule(), - 'server' => new Module\Server\ServerModule(), - 'user' => new Module\User\UserModule(), - 'install' => new Module\Install\InstallModule(), - ); - } - - /** - * Run. + * Run a module. * * The $mod param is in the format $module_$controller. * If the "_$controller" part is omitted, it will attempt to load * the controller with the same name as the module. - * If no mod is given it will attempt to load the default module. - * @param string $mod if empty, the mod getvar will be used, or fallback to default + * + * @param string $mod * @throws \InvalidArgumentException * @throws \LogicException */ - public function run($mod = null) { - if(!psm_is_cli() && isset($_GET["logout"])) { - $this->services['user']->doLogout(); - // logged out, redirect to login - header('Location: ' . psm_build_url()); - die(); + public function run($mod) { + $user = $this->container->get('user'); + + if(strpos($mod, '_') !== false) { + list($mod, $controller) = explode('_', $mod); + } else { + $controller = $mod; } - if($mod === null) { - $mod = psm_GET('mod', $this->default_module); - } + $controller = $this->getController($mod, $controller); - try { - $controller = $this->getController($mod); - } catch(\InvalidArgumentException $e) { - // invalid module, try the default one - // it that somehow also doesnt exist, we have a bit of an issue - // and we really have no reason catch it - $controller = $this->getController($this->default_module); - } // get min required level for this controller and make sure the user matches $min_lvl = $controller->getMinUserLevelRequired(); $action = null; if($min_lvl < PSM_USER_ANONYMOUS) { // if user is not logged in, load login module - if(!$this->services['user']->isUserLoggedIn()) { - $controller = $this->getController('user_login'); - } elseif($this->services['user']->getUserLevel() > $min_lvl) { + if(!$user->isUserLoggedIn()) { + $controller = $this->getController('user', 'login'); + } elseif($user->getUserLevel() > $min_lvl) { $controller = $this->getController('error'); $action = '401'; } } - $controller->setUser($this->services['user']); $response = $controller->initialize($action); if(!($response instanceof Response)) { @@ -150,42 +98,66 @@ class Router { } /** - * Get an instance of the requested mod. - * @param string $mod + * Get an instance of the requested controller. + * @param string $module_id + * @param string $controller_id if NULL, default controller will be used * @return \psm\Module\ControllerInterface * @throws \InvalidArgumentException */ - public function getController($mod) { - $controller = $this->getControllerClass($mod); - - if($controller === false) { - throw new \InvalidArgumentException('Controller is not registered'); + public function getController($module_id, $controller_id = null) { + if($controller_id === null) { + // by default, we use the controller with the same id as the module. + $controller_id = $module_id; } - $controller = new $controller($this->services['db'], $this->services['twig']); + + $module = $this->getModule($module_id); + $controllers = $module->getControllers(); + if(!isset($controllers[$controller_id]) || !class_exists($controllers[$controller_id])) { + throw new \InvalidArgumentException('Controller "' . $controller_id . '" is not registered or does not exist.'); + } + $controller = new $controllers[$controller_id]( + $this->container->get('db'), + $this->container->get('twig') + ); if(!$controller instanceof \psm\Module\ControllerInterface) { - throw new \Exception('Controller does not use ControllerInterface'); + throw new \Exception('Controller does not implement ControllerInterface'); } + $controller->setContainer($this->container); return $controller; } /** - * Get the classname of the controller for the provided mod - * @param string $mod - * @return string|false FALSE if not found, string otherwise + * Get service from container + * @param string $id + * @return mixed FALSE on failure, service otherwise + * @throws \InvalidArgumentException */ - protected function getControllerClass($mod) { - if(strpos($mod, '_') !== false) { - list($mod, $controller) = explode('_', $mod); - } else { - $controller = $mod; - } + public function getService($id) { + return $this->container->get($id); + } - if(!isset($this->map[$mod][$controller]) || !class_exists($this->map[$mod][$controller])) { - return false; - } else { - return $this->map[$mod][$controller]; - } + /** + * Get a module + * @param string $module_id + * @return \psm\Module\ModuleInterface + * @throws \InvalidArgumentException + */ + protected function getModule($module_id) { + return $this->container->get('module.' . $module_id); + } + + /** + * Build a new service container + * @return \Symfony\Component\DependencyInjection\ContainerBuilder + * @throws \InvalidArgumentException + */ + protected function buildServiceContainer() { + $builder = new ContainerBuilder(); + $loader = new XmlFileLoader($builder, new FileLocator(PSM_PATH_CONFIG)); + $loader->load('services.xml'); + + return $builder; } } \ No newline at end of file diff --git a/src/psm/Service/Database.class.php b/src/psm/Service/Database.class.php index 6a993dd1..a0de02ad 100644 --- a/src/psm/Service/Database.class.php +++ b/src/psm/Service/Database.class.php @@ -88,12 +88,6 @@ class Database { $this->db_user = $user; $this->db_pass = $pass; $this->connect(); - } elseif(defined('PSM_DB_HOST') && defined('PSM_DB_USER') && defined('PSM_DB_PASS') && defined('PSM_DB_NAME')) { - $this->db_host = PSM_DB_HOST; - $this->db_name = PSM_DB_NAME; - $this->db_user = PSM_DB_USER; - $this->db_pass = PSM_DB_PASS; - $this->connect(); } }