Skip to content

Commit

Permalink
Dev WIP New plugin system
Browse files Browse the repository at this point in the history
  • Loading branch information
SamMousa committed Feb 4, 2015
1 parent 3cb735f commit 9147018
Show file tree
Hide file tree
Showing 29 changed files with 610 additions and 559 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -3,3 +3,4 @@
/application/vendor
/tmp
/upload
application/config/plugins.php
34 changes: 34 additions & 0 deletions application/components/PhpConfigFile.php
@@ -0,0 +1,34 @@
<?php
/**
* Class that saves configuration as a PHP file.
*/
class PhpConfigFile extends CComponent{

protected $_config = [];
protected $file;

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

public function setConfig(array $config, $merge = true) {
$this->_config = $merge ? CMap::mergeArray($this->fileConfig, $config) : $config;
}

public function getFileConfig() {
return include $this->file;
}

public function getConfig() {
if (!isset($this->_config)) {
$this->_config = $this->getFileConfig();
}
return $this->_config;
}

public function save() {
$code = "<?php\nreturn " . var_export($this->config, true) . ';';
return false !== file_put_contents($this->file, $code);
}
}
16 changes: 14 additions & 2 deletions application/config/internal.php
Expand Up @@ -29,7 +29,7 @@
'application.controllers.*',
'application.modules.*',
),
'preload' => ['log'],
'preload' => ['log', 'pluginManager'],
'components' => array(
'bootstrap' => array(
'class' => 'TbApi',
Expand Down Expand Up @@ -106,7 +106,19 @@
),
'pluginManager' => [
'class' => "\\ls\\pluginmanager\\PluginManager",
'api' => "\\ls\\pluginmanager\\LimesurveyApi"
'apiMap' => [
"1.0" => "\\ls\\pluginmanager\\LimesurveyApi"
],
'oldPluginDirs' => [
// 'webroot.plugins', // User plugins
'application.core.plugins' // Core plugins
],
'pluginDirs' => [
__DIR__ . '/../core/plugins',
__DIR__ . '/../../plugins',

],
'loader' => $loader // Composer classloader.
],
'yiiwheels' => [
'class' => 'yiiwheels.YiiWheels'
Expand Down
131 changes: 47 additions & 84 deletions application/controllers/PluginsController.php
Expand Up @@ -70,46 +70,52 @@ public function actionActivate($id)

public function actionConfigure($id)
{
$arPlugin = Plugin::model()->findByPk($id)->attributes;
$oPluginObject = App()->getPluginManager()->loadPlugin($arPlugin['name'], $arPlugin['id']);

if ($arPlugin === null)
{
Yii::app()->user->setFlash('pluginmanager', 'Plugin not found');
$this->redirect(array('plugins/'));
}
$pluginConfig = \ls\pluginmanager\PluginConfig::findAll(false)[$id];
$plugin = App()->pluginManager->loadPlugin($pluginConfig);

// If post handle data, yt0 seems to be the submit button
if (App()->request->isPostRequest)
{

$aSettings = $oPluginObject->getPluginSettings(false);
$aSave = array();
foreach ($aSettings as $name => $setting)
{
$aSave[$name] = App()->request->getPost($name, null);
}
$oPluginObject->saveSettings($aSave);
Yii::app()->user->setFlash('pluginmanager', 'Settings saved');
if(!is_null(App()->request->getPost('redirect')))
{
$this->forward('plugins/index', true);
}
if (App()->request->isPostRequest) {
$plugin->saveSettings(App()->request->getPost($plugin->id));
}

// Prepare settings to be send to the view.
$aSettings = $oPluginObject->getPluginSettings();
if (empty($aSettings))
{
// And show a message
Yii::app()->user->setFlash('pluginmanager', 'This plugin has no settings');
$this->forward('plugins/index', true);
}

// Send to view plugin porperties: name and description
$aPluginProp = App()->getPluginManager()->getPluginInfo($arPlugin['name']);

$this->render('/plugins/configure', array('settings' => $aSettings, 'plugin' => $arPlugin, 'properties' => $aPluginProp));
// var_dump($settings);
// var_dump($plugin);
// die();
// if ($arPlugin === null)
// {
// Yii::app()->user->setFlash('pluginmanager', 'Plugin not found');
// $this->redirect(array('plugins/'));
// }
//
// // If post handle data, yt0 seems to be the submit button
// if (App()->request->isPostRequest)
// {
//
// $aSettings = $oPluginObject->getPluginSettings(false);
// $aSave = array();
// foreach ($aSettings as $name => $setting)
// {
// $aSave[$name] = App()->request->getPost($name, null);
// }
// $oPluginObject->saveSettings($aSave);
// App()->user->setFlash('pluginmanager', 'Settings saved');
// if(!is_null(App()->request->getPost('redirect')))
// {
// $this->forward('plugins/index', true);
// }
// }
//
// // Prepare settings to be send to the view.
// $aSettings = $oPluginObject->getPluginSettings();
// if (empty($aSettings))
// {
// // And show a message
// Yii::app()->user->setFlash('pluginmanager', 'This plugin has no settings');
// $this->forward('plugins/index', true);
// }
//
// // Send to view plugin porperties: name and description
// $aPluginProp = App()->getPluginManager()->getPluginInfo($arPlugin['name']);

$this->render('configure', ['plugin' => $plugin]);
}

public function actionDeactivate($id)
Expand Down Expand Up @@ -162,52 +168,9 @@ public function actionDirect($plugin, $function)

public function actionIndex()
{
$oPluginManager = App()->getPluginManager();

// Scan the plugins folder.
$aDiscoveredPlugins = $oPluginManager->scanPlugins();
$aInstalledPlugins = $oPluginManager->getInstalledPlugins();
$aInstalledNames = array_map(function ($installedPlugin) {
return $installedPlugin->name;
}, $aInstalledPlugins);

// Install newly discovered plugins.
foreach ($aDiscoveredPlugins as $discoveredPlugin)
{
if (!in_array($discoveredPlugin['pluginClass'], $aInstalledNames))
{
$oPlugin = new Plugin();
$oPlugin->name = $discoveredPlugin['pluginClass'];
$oPlugin->active = 0;
$oPlugin->save();
}
}

$aoPlugins = Plugin::model()->findAll();
$data = array();
foreach ($aoPlugins as $oPlugin)
{
/* @var $plugin Plugin */
if (array_key_exists($oPlugin->name, $aDiscoveredPlugins))
{
$aPluginSettings = App()->getPluginManager()->loadPlugin($oPlugin->name, $oPlugin->id)->getPluginSettings(false);
$data[] = array(
'id' => $oPlugin->id,
'name' => $aDiscoveredPlugins[$oPlugin->name]['pluginName'],
'description' => $aDiscoveredPlugins[$oPlugin->name]['description'],
'active' => $oPlugin->active,
'settings' => $aPluginSettings,
'new' => !in_array($oPlugin->name, $aInstalledNames)
);
} else
{
// This plugin is missing, maybe the files were deleted but the record was not removed from the database
// Now delete this record. Depending on the plugin the settings will be preserved
App()->user->setFlash('pluginDelete' . $oPlugin->id, sprintf(gT("Plugin '%s' was missing and is removed from the database."), $oPlugin->name));
$oPlugin->delete();
}
}
echo $this->render('/plugins/index', compact('data'));

$plugins = new CArrayDataProvider(App()->pluginManager->scanPlugins());
return $this->render('index', ['plugins' => $plugins]);
}

public function filters()
Expand Down
2 changes: 1 addition & 1 deletion application/core/LSUserIdentity.php
Expand Up @@ -46,7 +46,7 @@ class LSUserIdentity extends CUserIdentity {
*
* @var string
*/
public $plugin = 'Authdb';
public $plugin = 'ls\\core\\plugins\\AuthDb';

public function authenticate() {
// First initialize the result, we can later retieve it to get the exact error code/message
Expand Down
11 changes: 8 additions & 3 deletions application/core/WebApplication.php
Expand Up @@ -17,11 +17,16 @@
*/
require_once(dirname(dirname(__FILE__)) . '/helpers/globals.php');
/**
* Implements global config
* @property CLogRouter $log Log router component.
*/
* Implements global config
* @property CLogRouter $log Log router component.
* @property \ls\pluginmanager\PluginManager $pluginManager
*/
class WebApplication extends CWebApplication
{
/**
*
* @var Composer\Autoload\ClassLoader
*/
public $loader;
protected $config = array();

Expand Down
@@ -1,48 +1,37 @@
<?php
namespace ls\core\plugins;
use ls\pluginmanager\AuthPluginBase;
use \ls\pluginmanager\PluginEvent;
use \Yii;
use \CHtml;

class Authdb extends AuthPluginBase
class AuthDb extends AuthPluginBase
{
protected $storage = 'DbStorage';
protected $_onepass = null;

static protected $description = 'Core: Database authentication + exports';
static protected $name = 'LimeSurvey internal database';

public function init()
{
/**
* Here you should handle subscribing to the events your plugin will handle
*/
$this->subscribe('beforeLogin');
$this->subscribe('newLoginForm');
$this->subscribe('afterLoginFormSubmit');
$this->subscribe('newUserSession');
$this->subscribe('beforeDeactivate');
// Now register for the core exports
$this->subscribe('listExportPlugins');
$this->subscribe('listExportOptions');
$this->subscribe('newExport');
}

public function beforeDeactivate()
public function eventBeforeDeactivate(PluginEvent $event)
{
$this->getEvent()->set('success', false);
$event->set('success', false);

// Optionally set a custom error message.
$this->getEvent()->set('message', gT('Core plugin can not be disabled.'));
$event->set('message', gT('Core plugin can not be disabled.'));
}

public function beforeLogin()
public function eventBeforeLogin(PluginEvent $event)
{
$this->getEvent()->set('default', get_class($this)); // This is the default login method, should be configurable from plugin settings
$event->set('default', get_class($this)); // This is the default login method, should be configurable from plugin settings

// We can skip the login form here and set username/password etc.
$request = $this->api->getRequest();
if (!is_null($request->getParam('onepass'))) {
// We have a one time password, skip the login form
$this->setOnePass($request->getParam('onepass'));
$this->setUsername($request->getParam('user'));
$this->setUsername($event, $request->getParam('user'));
$this->setAuthPlugin(); // This plugin will handle authentication and skips the login form
}
}
Expand All @@ -57,7 +46,7 @@ protected function getOnePass()
return $this->_onepass;
}

public function newLoginForm()
public function eventNewLoginForm(PluginEvent $event)
{
$sUserName='';
$sPassword='';
Expand All @@ -67,25 +56,23 @@ public function newLoginForm()
$sPassword=Yii::app()->getConfig("defaultpass");
}

$this->getEvent()->getContent($this)
$event->getContent($this)
->addContent(CHtml::tag('li', array(), "<label for='user'>" . gT("Username") . "</label>".CHtml::textField('user',$sUserName,array('size'=>40,'maxlength'=>40))))
->addContent(CHtml::tag('li', array(), "<label for='password'>" . gT("Password") . "</label>".CHtml::passwordField('password',$sPassword,array('size'=>40,'maxlength'=>40))));
}

public function newUserSession()
public function eventNewUserSession(PluginEvent $event)
{
// Do nothing if this user is not Authdb type
$identity = $this->getEvent()->get('identity');
if ($identity->plugin != 'Authdb')
{
$identity = $event->get('identity');
if ($identity->plugin != __CLASS__) {
return;
}

// Here we do the actual authentication
$username = $this->getUsername();
$password = $this->getPassword();
$onepass = $this->getOnePass();

$user = $this->api->getUserByName($username);

if ($user !== null and $username==$user->users_name) // Control of equality for uppercase/lowercase with mysql
Expand All @@ -109,7 +96,7 @@ public function newUserSession()
{
$user->one_time_pw='';
$user->save();
$this->setAuthSuccess($user);
$this->setAuthSuccess($event, $user);
return;
}

Expand All @@ -119,7 +106,7 @@ public function newUserSession()
return;
}

$this->setAuthSuccess($user);
$this->setAuthSuccess($event, $user);
}

/**
Expand All @@ -137,9 +124,8 @@ protected function setOnePass($onepass)


// Now the export part:
public function listExportOptions()
public function eventListExportOptions(PluginEvent $event)
{
$event = $this->getEvent();
$type = $event->get('type');

switch ($type) {
Expand Down Expand Up @@ -173,7 +159,7 @@ public function listExportOptions()
/**
* Registers this export type
*/
public function listExportPlugins()
public function eventListExportPlugins(PluginEvent $event)
{
$event = $this->getEvent();
$exports = $event->get('exportplugins');
Expand All @@ -193,7 +179,7 @@ public function listExportPlugins()
/**
* Returns the required IWriter
*/
public function newExport()
public function eventNewExport()
{
$event = $this->getEvent();
$type = $event->get('type');
Expand Down

0 comments on commit 9147018

Please sign in to comment.