Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update save way to add custom made EM functions (php and js) #1077

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,17 @@
// extending LEM wit js functions similar to the php file with same name
// js functions are required for group-by-group or all-in-one presentations of surveys

function sayHello(msg)
{
return 'Hello ' + msg;
}

function sayBye(msg)
{
return 'Good Bye ' + msg + ". " + notRegistered();
}

function notRegistered()
{
return "Result is 42!";
}
@@ -0,0 +1,79 @@
<?php
/**
* Sample for a LEM extension to add new functions for LimeSurvey ExpressionManager
* Copyright (C) 2018 orvil (O. Villani)
* License: GNU/GPL License v2 or later, see LICENSE.php
*
* Howto:
* 1. Create (if not already existing) a new folder below the path '/application/extensions/' in your LS installation named 'emexpressions'.
* So path is now /application/extensions/emexpressions
*
* 2. create in this (new) subfolder another folder with the name of your extension [in this case eg. 'sampleextension']
* This is your extension-folder
*
* 3. create or copy in your extension-folder a *.php file with exactly the same name as the folder has, but with '.php' at the end
* This is your extension php file [in this case 'sampleextension.php']
* *
* 4. This extension php file has to contain a class with exactly the same name as the extension-folder / extension php file has
* This is the extension class [ in this case 'sampleextension']
*
* 5. The every extension class requires:
* - a private variable named $RDP_ValidFunctions
* - a constructor where the additional EM functions are defined (the same way as they are in em_core_helper.php)
* - a function called 'newRDP_ValidFunctions()' where the property 'RDP_ValidFunctions' is returned
*
* 6. In the extension php file but OUTSIDE(!) of the class definition implement those functions you need and
* that are defined for RDP_ValidFunctions
*
* 7. Create or copy in this extension-folder a *.js file with exactly the same name as the folder has, but with '.js' at the end
* This is the extension javaScript file [in this case 'sampleextension.js']
* The extension javaScript file has to have equivalent functions to the additional php functions in extension php file
* This is necesarry for surveys running in view-by-group and all-in-one mode
*/


// class has to have the same name as the file (except the .php at the end)
class sampleextension
{
private $RDP_ValidFunctions; // names and # params of valid functions

// define ADDITIONAL functions here, inside the constructor, in the same way as they are defined in em_core_helper.php
function __construct()
{
$this->RDP_ValidFunctions = array(
'sayHello' => array('sayHello', 'sayHello', gT('says Hello'), 'string sayHello(toWhom)', '',1),
'sayBye' => array('sayBye', 'sayBye', gT('says Bye'), 'string sayBye(toWhom)', '',1),
//'yourFunction' => array('phpFuncName', 'jsFuncName', gT('info to show on mouseover'), 'string yourFunction(param)', '', nrOfAllowedParam),
);
}

// function 'newRDP_ValidFunctions' will be used to register the new EM definitions
// don't change the name of this function!
function newRDP_ValidFunctions()
{
return $this->RDP_ValidFunctions;
}
}

// place additional (registered) functions for EM below ///////////////////////////////////////////////////////////////////
function sayHello($msg)
{
return "Hello " . $msg;
}

function sayBye($msg)
{
return "Good Bye " . $msg . ". " . notRegistered();
}

// place functions NOT to be registered for EM below ///////////////////////////////////////////////////////////////////////////

// This is an example for a function not registered into RDP_ValidFunctions
// This means, you can't call this function via EM, so {notRegistered()} will not work inside LS
// but you can call it via a registered function - see function sayBye()
function notRegistered()
{
return "Result is 42!";
}

?>
60 changes: 60 additions & 0 deletions application/helpers/expressions/em_core_helper.php
Expand Up @@ -27,6 +27,32 @@
* @author Thomas M. White (TMSWhite)
*/

// prepare to extend LEM functions
// import ALL php and js files from subdirectories of application/extensions/emexpressions/
// where the name of the subdir fits the name of the php and js file
$emexDir = CFileHelper::findFiles(Yii::app()->basePath . "/extensions/emexpressions", array('fileTypes' => array('php')));

// rover through all emexpression directories
foreach($emexDir as $thisEmexDir)
{
$splitDir = explode('/', rtrim(str_replace('\\', '/', $thisEmexDir))); // os independent

// check if subpath (+ ".php" appended) fits filename
$emexName = $splitDir[count($splitDir)-2];

if($splitDir[count($splitDir)-1] == $emexName.'.php')
{
// if so, import the php file
Yii::import('application.extensions.emexpressions.' . $emexName . "." . $emexName, true);

// equivalent *.js file avaliable too?
if(in_array(Yii::app()->basePath . "/extensions/emexpressions/" . $emexName . "/" . $emexName . ".js", CFileHelper::findFiles(Yii::app()->basePath . "/extensions/emexpressions/" . $emexName, array('fileTypes' => array('js')))))
{
Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl . "/application/extensions/emexpressions/" . $emexName . "/" . $emexName . ".js", CClientScript::POS_HEAD);
}
}
}

class ExpressionManager
{
// These are the allowable suffixes for variables - each represents an attribute of a variable.
Expand Down Expand Up @@ -246,6 +272,40 @@ function __construct()
'ucwords' => array('ucwords', 'ucwords', gT('Uppercase the first character of each word in a string'), 'string ucwords(string)', 'http://php.net/ucwords', 1),
'unique' => array('exprmgr_unique', 'LEMunique', gT('Returns true if all non-empty responses are unique'), 'boolean unique(arg1, ..., argN)', '', -1),
);

// now add RDP_ValidFunctions from emexpressions subfolder/subfiles
// requires to read (again) the directory structure
$emexDir = CFileHelper::findFiles(Yii::app()->basePath . "/extensions/emexpressions", array('fileTypes' => array('php')));

// rover through all emexpression directories
foreach($emexDir as $thisEmexDir)
{
$splitDir = explode('/', rtrim(str_replace('\\', '/', $thisEmexDir))); // os independent

// check if subpath (+ ".php" appended) fits filename => if so, import the definitions
if($splitDir[count($splitDir)-1] == $splitDir[count($splitDir)-2].'.php')
{
// get the name of the extension class. Class is called by its name in a variable!
// that's why directory, php-file and class share the same name
$emexClassName = $splitDir[count($splitDir)-2];

// try to create an instance
try{
$emex = new $emexClassName();

// get the RDP definitions and merge them to the existiong ones here
$this->RDP_ValidFunctions = array_merge($this->RDP_ValidFunctions, $emex->newRDP_ValidFunctions());

//clear the object
$emex = NULL;
unset($emex);

} catch (Exception $e) {
// TODO: some msg. for admin here?
}
}
}

/* Reset the language */
if ($baseLang) {
Yii::app()->setLanguage($baseLang);
Expand Down