mirror of
https://github.com/YunoHost-Apps/limesurvey_ynh.git
synced 2024-09-03 19:36:32 +02:00
474 lines
18 KiB
PHP
474 lines
18 KiB
PHP
|
<?php
|
||
|
|
||
|
if (!defined('BASEPATH'))
|
||
|
die('No direct script access allowed');
|
||
|
/*
|
||
|
* LimeSurvey
|
||
|
* Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
|
||
|
* All rights reserved.
|
||
|
* License: GNU/GPL License v2 or later, see LICENSE.php
|
||
|
* LimeSurvey is free software. This version may have been modified pursuant
|
||
|
* to the GNU General Public License, and as distributed it includes or
|
||
|
* is derivative of works licensed under the GNU General Public License or
|
||
|
* other free or open source software licenses.
|
||
|
* See COPYRIGHT.php for copyright notices and details.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
class Survey extends LSActiveRecord
|
||
|
{
|
||
|
/**
|
||
|
* This is a static cache, it lasts only during the active request. If you ever need
|
||
|
* to clear it, like on activation of a survey when in the same request a row is read,
|
||
|
* saved and read again you can use resetCache() method.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $findByPkCache = array();
|
||
|
|
||
|
/**
|
||
|
* Returns the title of the survey. Uses the current language and
|
||
|
* falls back to the surveys' default language if the current language is not available.
|
||
|
*/
|
||
|
public function getLocalizedTitle()
|
||
|
{
|
||
|
if (isset($this->languagesettings[App()->lang->langcode]))
|
||
|
{
|
||
|
return $this->languagesettings[App()->lang->langcode]->surveyls_title;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return $this->languagesettings[$this->language]->surveyls_title;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Expires a survey. If the object was invoked using find or new surveyId can be ommited.
|
||
|
* @param int $surveyId
|
||
|
*/
|
||
|
public function expire($surveyId = null)
|
||
|
{
|
||
|
$dateTime = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", Yii::app()->getConfig('timeadjust'));
|
||
|
$dateTime = dateShift($dateTime, "Y-m-d H:i:s", '-1 day');
|
||
|
|
||
|
if (!isset($surveyId))
|
||
|
{
|
||
|
$this->expires = $dateTime;
|
||
|
if ($this->scenario == 'update')
|
||
|
{
|
||
|
return $this->save();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
self::model()->updateByPk($surveyId,array('expires' => $dateTime));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the table's name
|
||
|
*
|
||
|
* @access public
|
||
|
* @return string
|
||
|
*/
|
||
|
public function tableName()
|
||
|
{
|
||
|
return '{{surveys}}';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the table's primary key
|
||
|
*
|
||
|
* @access public
|
||
|
* @return string
|
||
|
*/
|
||
|
public function primaryKey()
|
||
|
{
|
||
|
return 'sid';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the static model of Settings table
|
||
|
*
|
||
|
* @static
|
||
|
* @access public
|
||
|
* @param string $class
|
||
|
* @return Survey
|
||
|
*/
|
||
|
public static function model($class = __CLASS__)
|
||
|
{
|
||
|
return parent::model($class);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns this model's relations
|
||
|
*
|
||
|
* @access public
|
||
|
* @return array
|
||
|
*/
|
||
|
public function relations()
|
||
|
{
|
||
|
$alias = $this->getTableAlias();
|
||
|
return array(
|
||
|
'languagesettings' => array(self::HAS_MANY, 'SurveyLanguageSetting', 'surveyls_survey_id', 'index' => 'surveyls_language'),
|
||
|
'defaultlanguage' => array(self::BELONGS_TO, 'SurveyLanguageSetting', array('language' => 'surveyls_language', 'sid' => 'surveyls_survey_id'), 'together' => true),
|
||
|
'owner' => array(self::BELONGS_TO, 'User', '', 'on' => "$alias.owner_id = owner.uid"),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns this model's scopes
|
||
|
*
|
||
|
* @access public
|
||
|
* @return array
|
||
|
*/
|
||
|
public function scopes()
|
||
|
{
|
||
|
return array(
|
||
|
'active' => array('condition' => "active = 'Y'"),
|
||
|
'open' => array('condition' => '(startdate <= :now1 OR startdate IS NULL) AND (expires >= :now2 OR expires IS NULL)', 'params' => array(
|
||
|
':now1' => dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", Yii::app()->getConfig("timeadjust")),
|
||
|
':now2' => dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", Yii::app()->getConfig("timeadjust"))
|
||
|
)
|
||
|
),
|
||
|
'public' => array('condition' => "listpublic = 'Y'"),
|
||
|
'registration' => array('condition' => "allowregister = 'Y' AND startdate > :now3 AND (expires < :now4 OR expires IS NULL)", 'params' => array(
|
||
|
':now3' => dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", Yii::app()->getConfig("timeadjust")),
|
||
|
':now4' => dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", Yii::app()->getConfig("timeadjust"))
|
||
|
))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns this model's validation rules
|
||
|
*
|
||
|
*/
|
||
|
public function rules()
|
||
|
{
|
||
|
return array(
|
||
|
array('datecreated', 'default','value'=>date("Y-m-d")),
|
||
|
array('startdate', 'default','value'=>NULL),
|
||
|
array('expires', 'default','value'=>NULL),
|
||
|
array('admin,adminemail,bounce_email,faxto','LSYii_Validators'),
|
||
|
array('active', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('anonymized', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('savetimings', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('datestamp', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('usecookie', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('allowregister', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('allowsave', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('autoredirect', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('allowprev', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('printanswers', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('ipaddr', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('refurl', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('publicstatistics', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('publicgraphs', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('listpublic', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('htmlemail', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('sendconfirmation', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('tokenanswerspersistence', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('assessments', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('usetokens', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('showxquestions', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('shownoanswer', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('showwelcome', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('showprogress', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('questionindex', 'numerical','min' => 0, 'max' => 2, 'allowEmpty'=>false),
|
||
|
array('nokeyboard', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('alloweditaftercompletion', 'in','range'=>array('Y','N'), 'allowEmpty'=>true),
|
||
|
array('bounceprocessing', 'in','range'=>array('L','N','G'), 'allowEmpty'=>true),
|
||
|
array('usecaptcha', 'in','range'=>array('A','B','C','D','X','R','S','N'), 'allowEmpty'=>true),
|
||
|
array('showgroupinfo', 'in','range'=>array('B','N','D','X'), 'allowEmpty'=>true),
|
||
|
array('showqnumcode', 'in','range'=>array('B','N','C','X'), 'allowEmpty'=>true),
|
||
|
array('format', 'in','range'=>array('G','S','A'), 'allowEmpty'=>true),
|
||
|
array('googleanalyticsstyle', 'numerical', 'integerOnly'=>true, 'min'=>'0', 'max'=>'2', 'allowEmpty'=>true),
|
||
|
array('autonumber_start','numerical', 'integerOnly'=>true,'allowEmpty'=>true),
|
||
|
array('tokenlength','numerical', 'integerOnly'=>true,'allowEmpty'=>true, 'min'=>'5', 'max'=>'36'),
|
||
|
array('bouncetime','numerical', 'integerOnly'=>true,'allowEmpty'=>true),
|
||
|
array('navigationdelay','numerical', 'integerOnly'=>true,'allowEmpty'=>true),
|
||
|
// array('expires','date', 'format'=>array('yyyy-MM-dd', 'yyyy-MM-dd HH:mm', 'yyyy-MM-dd HH:mm:ss',), 'allowEmpty'=>true),
|
||
|
// array('startdate','date', 'format'=>array('yyyy-MM-dd', 'yyyy-MM-dd HH:mm', 'yyyy-MM-dd HH:mm:ss',), 'allowEmpty'=>true),
|
||
|
// array('datecreated','date', 'format'=>array('yyyy-MM-dd', 'yyyy-MM-dd HH:mm', 'yyyy-MM-dd HH:mm:ss',), 'allowEmpty'=>true),
|
||
|
// Date rules currently don't work properly with MSSQL, deactivating for now
|
||
|
array('template', 'tmplfilter'),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Defines the customs validation rule tmplfilter
|
||
|
*
|
||
|
* @param mixed $attribute
|
||
|
* @param mixed $params
|
||
|
*/
|
||
|
public function tmplfilter($attribute,$params)
|
||
|
{
|
||
|
if(!array_key_exists($this->$attribute,getTemplateList()))
|
||
|
$this->$attribute = 'default';
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* permission scope for this model
|
||
|
*
|
||
|
* @access public
|
||
|
* @param int $loginID
|
||
|
* @return CActiveRecord
|
||
|
*/
|
||
|
public function permission($loginID)
|
||
|
{
|
||
|
$loginID = (int) $loginID;
|
||
|
$criteria = $this->getDBCriteria();
|
||
|
$criteria->mergeWith(array(
|
||
|
'condition' => 'sid IN (SELECT entity_id FROM {{permissions}} WHERE entity = :entity AND uid = :uid AND permission = :permission AND read_p = 1)
|
||
|
OR owner_id = :owner_id',
|
||
|
));
|
||
|
$criteria->params[':uid'] = $loginID;
|
||
|
$criteria->params[':permission'] = 'survey';
|
||
|
$criteria->params[':owner_id'] = $loginID;
|
||
|
$criteria->params[':entity'] = 'survey';
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns additional languages formatted into a string
|
||
|
*
|
||
|
* @access public
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getAdditionalLanguages()
|
||
|
{
|
||
|
$sLanguages = trim($this->additional_languages);
|
||
|
if ($sLanguages != '')
|
||
|
return explode(' ', $sLanguages);
|
||
|
else
|
||
|
return array();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns all languages array
|
||
|
*
|
||
|
* @access public
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getAllLanguages()
|
||
|
{
|
||
|
$sLanguages = self::getAdditionalLanguages();
|
||
|
$baselang=$this->language;
|
||
|
array_unshift($sLanguages,$baselang);
|
||
|
return $sLanguages;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the additional token attributes
|
||
|
*
|
||
|
* @access public
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getTokenAttributes()
|
||
|
{
|
||
|
$attdescriptiondata = @unserialize($this->attributedescriptions);
|
||
|
// checked for invalid data
|
||
|
if($attdescriptiondata == null)
|
||
|
{
|
||
|
return array();
|
||
|
}
|
||
|
// Catches malformed data
|
||
|
if ($attdescriptiondata && strpos(key(reset($attdescriptiondata)),'attribute_')===false)
|
||
|
{
|
||
|
// don't know why yet but this breaks normal tokenAttributes functionning
|
||
|
//$attdescriptiondata=array_flip(GetAttributeFieldNames($this->sid));
|
||
|
}
|
||
|
elseif (is_null($attdescriptiondata))
|
||
|
{
|
||
|
$attdescriptiondata=array();
|
||
|
}
|
||
|
// Legacy records support
|
||
|
if ($attdescriptiondata === false)
|
||
|
{
|
||
|
$attdescriptiondata = explode("\n", $this->attributedescriptions);
|
||
|
$fields = array();
|
||
|
$languagesettings = array();
|
||
|
foreach ($attdescriptiondata as $attdescription)
|
||
|
{
|
||
|
if (trim($attdescription) != '')
|
||
|
{
|
||
|
$fieldname = substr($attdescription, 0, strpos($attdescription, '='));
|
||
|
$desc = substr($attdescription, strpos($attdescription, '=') + 1);
|
||
|
$fields[$fieldname] = array(
|
||
|
'description' => $desc,
|
||
|
'mandatory' => 'N',
|
||
|
'show_register' => 'N',
|
||
|
'cpdbmap' =>''
|
||
|
);
|
||
|
$languagesettings[$fieldname] = $desc;
|
||
|
}
|
||
|
}
|
||
|
$ls = SurveyLanguageSetting::model()->findByAttributes(array('surveyls_survey_id' => $this->sid, 'surveyls_language' => $this->language));
|
||
|
self::model()->updateByPk($this->sid, array('attributedescriptions' => serialize($fields)));
|
||
|
$ls->surveyls_attributecaptions = serialize($languagesettings);
|
||
|
$ls->save();
|
||
|
$attdescriptiondata = $fields;
|
||
|
}
|
||
|
$aCompleteData=array();
|
||
|
foreach ($attdescriptiondata as $sKey=>$aValues)
|
||
|
{
|
||
|
if (!is_array($aValues)) $aValues=array();
|
||
|
$aCompleteData[$sKey]= array_merge(array(
|
||
|
'description' => '',
|
||
|
'mandatory' => 'N',
|
||
|
'show_register' => 'N',
|
||
|
'cpdbmap' =>''
|
||
|
),$aValues);
|
||
|
}
|
||
|
return $aCompleteData;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true in a token table exists for the given $surveyId
|
||
|
*
|
||
|
* @staticvar array $tokens
|
||
|
* @param int $iSurveyID
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public function hasTokens($iSurveyID) {
|
||
|
static $tokens = array();
|
||
|
$iSurveyID = (int) $iSurveyID;
|
||
|
|
||
|
if (!isset($tokens[$iSurveyID])) {
|
||
|
// Make sure common_helper is loaded
|
||
|
Yii::import('application.helpers.common_helper', true);
|
||
|
|
||
|
$tokens_table = "{{tokens_{$iSurveyID}}}";
|
||
|
if (tableExists($tokens_table)) {
|
||
|
$tokens[$iSurveyID] = true;
|
||
|
} else {
|
||
|
$tokens[$iSurveyID] = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $tokens[$iSurveyID];
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Creates a new survey - does some basic checks of the suppplied data
|
||
|
*
|
||
|
* @param array $aData Array with fieldname=>fieldcontents data
|
||
|
* @return integer The new survey id
|
||
|
*/
|
||
|
public function insertNewSurvey($aData)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
if (isset($aData['wishSID'])) // if wishSID is set check if it is not taken already
|
||
|
{
|
||
|
$aData['sid'] = $aData['wishSID'];
|
||
|
unset($aData['wishSID']);
|
||
|
}
|
||
|
else
|
||
|
$aData['sid'] = randomChars(6, '123456789');
|
||
|
|
||
|
$isresult = self::model()->findByPk($aData['sid']);
|
||
|
}
|
||
|
while (!is_null($isresult));
|
||
|
|
||
|
$survey = new self;
|
||
|
foreach ($aData as $k => $v)
|
||
|
$survey->$k = $v;
|
||
|
$sResult= $survey->save();
|
||
|
if ($sResult==false) return false;
|
||
|
else return $aData['sid'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Deletes a survey and all its data
|
||
|
*
|
||
|
* @access public
|
||
|
* @param int $iSurveyID
|
||
|
* @param bool @recursive
|
||
|
* @return void
|
||
|
*/
|
||
|
public function deleteSurvey($iSurveyID, $recursive=true)
|
||
|
{
|
||
|
Survey::model()->deleteByPk($iSurveyID);
|
||
|
|
||
|
if ($recursive == true)
|
||
|
{
|
||
|
if (tableExists("{{survey_".intval($iSurveyID)."}}")) //delete the survey_$iSurveyID table
|
||
|
{
|
||
|
Yii::app()->db->createCommand()->dropTable("{{survey_".intval($iSurveyID)."}}");
|
||
|
}
|
||
|
|
||
|
if (tableExists("{{survey_".intval($iSurveyID)."_timings}}")) //delete the survey_$iSurveyID_timings table
|
||
|
{
|
||
|
Yii::app()->db->createCommand()->dropTable("{{survey_".intval($iSurveyID)."_timings}}");
|
||
|
}
|
||
|
|
||
|
if (tableExists("{{tokens_".intval($iSurveyID)."}}")) //delete the tokens_$iSurveyID table
|
||
|
{
|
||
|
Yii::app()->db->createCommand()->dropTable("{{tokens_".intval($iSurveyID)."}}");
|
||
|
}
|
||
|
|
||
|
$oResult = Question::model()->findAllByAttributes(array('sid' => $iSurveyID));
|
||
|
foreach ($oResult as $aRow)
|
||
|
{
|
||
|
Answer::model()->deleteAllByAttributes(array('qid' => $aRow['qid']));
|
||
|
Condition::model()->deleteAllByAttributes(array('qid' =>$aRow['qid']));
|
||
|
QuestionAttribute::model()->deleteAllByAttributes(array('qid' => $aRow['qid']));
|
||
|
DefaultValue::model()->deleteAllByAttributes(array('qid' => $aRow['qid']));
|
||
|
}
|
||
|
|
||
|
Question::model()->deleteAllByAttributes(array('sid' => $iSurveyID));
|
||
|
Assessment::model()->deleteAllByAttributes(array('sid' => $iSurveyID));
|
||
|
QuestionGroup::model()->deleteAllByAttributes(array('sid' => $iSurveyID));
|
||
|
SurveyLanguageSetting::model()->deleteAllByAttributes(array('surveyls_survey_id' => $iSurveyID));
|
||
|
Permission::model()->deleteAllByAttributes(array('entity_id' => $iSurveyID, 'entity'=>'survey'));
|
||
|
SavedControl::model()->deleteAllByAttributes(array('sid' => $iSurveyID));
|
||
|
SurveyURLParameter::model()->deleteAllByAttributes(array('sid' => $iSurveyID));
|
||
|
//Remove any survey_links to the CPDB
|
||
|
SurveyLink::model()->deleteLinksBySurvey($iSurveyID);
|
||
|
Quota::model()->deleteQuota(array('sid' => $iSurveyID), true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function findByPk($pk, $condition = '', $params = array()) {
|
||
|
if (empty($condition) && empty($params)) {
|
||
|
if (array_key_exists($pk, $this->findByPkCache)) {
|
||
|
return $this->findByPkCache[$pk];
|
||
|
} else {
|
||
|
$result = parent::findByPk($pk, $condition, $params);
|
||
|
if (!is_null($result)) {
|
||
|
$this->findByPkCache[$pk] = $result;
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return parent::findByPk($pk, $condition, $params);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* findByPk uses a cache to store a result. Use this method to force clearing that cache.
|
||
|
*/
|
||
|
public function resetCache() {
|
||
|
$this->findByPkCache = array();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Attribute renamed to questionindex in dbversion 169
|
||
|
* Y maps to 1 otherwise 0;
|
||
|
* @param type $value
|
||
|
*/
|
||
|
public function setAllowjumps($value)
|
||
|
{
|
||
|
if ($value === 'Y') {
|
||
|
$this->questionindex = 1;
|
||
|
} else {
|
||
|
$this->questionindex = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|