Fix import questions

parent 94ed9997
/index.php /index.php
/index-test.php /index-test.php
/uploads/temp/*
\ No newline at end of file
...@@ -7,12 +7,19 @@ use common\components\AdminController; ...@@ -7,12 +7,19 @@ use common\components\AdminController;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter; use yii\filters\VerbFilter;
use yii\web\UploadedFile; use yii\web\UploadedFile;
use yii\helpers\Html;
use common\modules\testings\models\TestingTest; use common\modules\testings\models\TestingTest;
use common\modules\testings\models\SearchTestingTest; use common\modules\testings\models\SearchTestingTest;
use common\modules\testings\models\TestingQuestion;
use common\modules\testings\models\TestingTheme;
use common\modules\testings\models\TestingAnswer;
class TestingTestAdminController extends AdminController class TestingTestAdminController extends AdminController
{ {
public $errorSummaryCssClass = 'error-summary';
public $encodeErrorSummary;
public static function actionsTitles() public static function actionsTitles()
{ {
return array( return array(
...@@ -129,10 +136,8 @@ class TestingTestAdminController extends AdminController ...@@ -129,10 +136,8 @@ class TestingTestAdminController extends AdminController
{ {
$model->csv_file = UploadedFile::getInstance($model, 'csv_file'); $model->csv_file = UploadedFile::getInstance($model, 'csv_file');
if ($model->upload()) if($model->upload())
{ {
$resource = CSVHelper::open($csv_file->tempName);
try try
{ {
$log = []; $log = [];
...@@ -140,106 +145,104 @@ class TestingTestAdminController extends AdminController ...@@ -140,106 +145,104 @@ class TestingTestAdminController extends AdminController
set_time_limit(60*3); // Максимальное время выполнения скрипта - 3 минуты set_time_limit(60*3); // Максимальное время выполнения скрипта - 3 минуты
$questionsCount = 0; // Кол-во загруженных вопросов $questionsCount = 0; // Кол-во загруженных вопросов
$gammasCount = 0; // Кол-во гамм (не только созданных) $themesCount = 0; // Кол-во тем (не только созданных)
$inputFileType = \PHPExcel_IOFactory::identify($model->file);
$objReader = \PHPExcel_IOFactory::createReader($inputFileType);
$objPHPExcel = $objReader->load($model->file);
while ($data = CSVHelper::fgetcsv($resource)) $sheet = $objPHPExcel->getSheet(0);
$highestRow = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();
for ($i = 3; $i <= $highestRow; $i++)
{ {
// если в файле пошли пустые строки, то выходим из цикла // извлечение переменных из XLS
if (count($data) < 2) break; $theme_name = trim(preg_replace('/\s+/', ' ', $sheet->getCell('A' . $i)->getValue()));
$question_name = trim(preg_replace('/\s+/', ' ', $sheet->getCell('B' . $i)->getValue()));
// извлечение переменных из CSV $question_type = trim(preg_replace('/\s+/', ' ', $sheet->getCell('C' . $i)->getValue()));
$gamma_type = trim($data[0]); $answer_name = trim(preg_replace('/\s+/', ' ', $sheet->getCell('D' . $i)->getValue()));
// если первый столбец не указывает на цифры 1 или 2 (строительная и промышленная гаммы) - вся строка неправильная $answer_isright = trim($sheet->getCell('E' . $i)->getValue());
if (($gamma_type <> '1') && ($gamma_type <> '2')) continue;
$gamma_name = trim(preg_replace('/\s+/', ' ',$data[1])); // поиск или создание темы
$q_name = trim(preg_replace('/\s+/', ' ',$data[2])); if ($theme_name <> '')
$q_type = trim(preg_replace('/\s+/', ' ',$data[3])); {
$a_name = trim(preg_replace('/\s+/', ' ',$data[4])); $themesCount++;
$a_isright = trim($data[5]);
$author = trim($data[6]); $theme = TestingTheme::find()->where(['name' => $theme_name])->one();
// поиск или создание гаммы if(!$theme)
if ($gamma_name <> '') { {
$theme = new TestingTheme;
$gammasCount++; $theme->name = $theme_name;
}
$cr1 = new CDbCriteria; else
{
$cr1->addCondition('type = :main_gamma'); $log[] = 'Тема ' . $theme_name . ' уже существует.';
$cr1->addCondition('name = :gamma');
$cr1->params = array(
':main_gamma' => $gamma_type,
':gamma' => $gamma_name,
);
$gamma = TestingGamma::model()->find($cr1);
if ($gamma === null) {
$gamma = new TestingGamma;
$gamma->name = $gamma_name;
$gamma->type = $gamma_type;
//$log[] = 'Гамма '.$gamma_name.' создана.';
} else {
//$log[] = 'Гамма '.$gamma_name.' уже существует.';
} }
if ($gamma->save()) { if(!$theme->save())
//$log[] = 'Гамма "'.$gamma_name.'" сохранена.'; {
} else { $log[] = 'Ошибка при сохранении темы "' . $theme_name . '"';
$log[] = 'Ошибка при сохранении гаммы "'.$gamma_name.'"';
} }
} }
// создание вопроса // создание вопроса
if ($q_name <> '') { if ($question_name <> '')
{
$question = new TestingQuestion; $question = new TestingQuestion;
$question->text = $q_name; $question->text = $question_name;
$question->type = $q_type; $question->type = $question_type;
$question->test_id = $model->id; $question->test_id = $id;
$question->gamma_id = $gamma->id; $question->theme_id = $theme->id;
$question->author = $author; $question->is_active = TestingQuestion::ACTIVE;
if ($question->save()) { if($question->save())
//$log[] = 'Вопрос "'.$q_name.'" сохранен.'; {
$questionsCount++; $questionsCount++;
} else { }
$log[] = 'Ошибка при сохранении вопроса "'.$q_name.'"'; else
{
$log[] = 'Ошибка при сохранении вопроса "' . $question_name . '"';
} }
} }
// создание ответа // создание ответа
$answer = new TestingAnswer; $answer = new TestingAnswer;
$answer->text = $a_name; $answer->text = $answer_name;
if (($a_isright == 'да') || ($a_isright == 'Да') || ($a_isright == 'ДА') || ($a_isright == 'y') || ($a_isright == 'yes') || ($a_isright == 'Y')) {
if (in_array($answer_isright, TestingAnswer::$xls_rights_list))
{
$answer->is_right = TestingAnswer::IS_RIGHT; $answer->is_right = TestingAnswer::IS_RIGHT;
} else { }
else
{
$answer->is_right = TestingAnswer::IS_NOT_RIGHT; $answer->is_right = TestingAnswer::IS_NOT_RIGHT;
} }
$answer->question_id = $question->id; $answer->question_id = $question->id;
if ($answer->save()) { if (!$answer->save())
//$log[] = 'Ответ "'.$a_name.'" сохранен.'; {
} else { $log[] = 'Ошибка при сохранении ответа "' . $answer_name . '"';
$log[] = 'Ошибка при сохранении ответа "'.$a_name.'"';
} }
} }
// добавляем отчёт о кол-ве добавленных вопросов и гамм // добавляем отчёт о кол-ве добавленных вопросов и гамм
Yii::app()->user->setFlash('flash', '<i>Всего добавлено <b>' .$questionsCount. '</b> вопросов в <b>'.$gammasCount. '</b> гаммах. Перейти к '.CHtml::link('списку загруженных вопросов',array('/testings/testingQuestionAdmin/manage','test'=>$model->id)).'.</i>'); Yii::$app->session->setFlash('flash', '<i>Всего добавлено <b>' . $questionsCount . '</b> вопросов в <b>' . $themesCount . '</b> темах. Перейти к ' . Html::a('списку загруженных вопросов', ['/testings/testing-question-admin/manage', 'test'=>$model->id]) . '.</i>');
$params['log'] = '<p>' . implode('</p><p>',$log) . '</p>'; $params['log'] = '<p>' . implode('</p><p>', $log) . '</p>';
} }
else catch (Exception $e)
{ {
Yii::$app()->session->setFlash('flash', 'Произошла ошибка при загрузке файла. Обратитесь к администратору!'); $params['log'] = 'Импорт прошел неудачно: ' . $e->getMessage();
} }
}
catch (Exception $e) $model->deleteFile();
}
else
{ {
$params['log'] = 'Импорт прошел неудачно: ' . $e->getMessage(); Yii::$app->session->setFlash('flash', 'Произошла ошибка при загрузке файла. Обратитесь к администратору!');
} }
} }
......
...@@ -20,6 +20,8 @@ class TestingAnswer extends \common\components\ActiveRecordModel ...@@ -20,6 +20,8 @@ class TestingAnswer extends \common\components\ActiveRecordModel
self::IS_RIGHT => 'Да', self::IS_RIGHT => 'Да',
]; ];
public static $xls_rights_list = ['да', 'Да', 'ДА', 'y', 'yes', 'Y'];
public static function tableName() public static function tableName()
{ {
return 'testings_answers'; return 'testings_answers';
......
...@@ -49,7 +49,6 @@ class TestingQuestion extends \common\components\ActiveRecordModel ...@@ -49,7 +49,6 @@ class TestingQuestion extends \common\components\ActiveRecordModel
{ {
return [ return [
'is_active' => 'Активен/скрыт', 'is_active' => 'Активен/скрыт',
'author' => 'Автор вопроса',
'test_id' => 'Тест', 'test_id' => 'Тест',
'theme_id' => 'Тема', 'theme_id' => 'Тема',
'text' => 'Текст вопроса', 'text' => 'Текст вопроса',
......
...@@ -13,9 +13,14 @@ use common\modules\testings\models\TestingQuestion; ...@@ -13,9 +13,14 @@ use common\modules\testings\models\TestingQuestion;
class TestingTest extends \common\components\ActiveRecordModel class TestingTest extends \common\components\ActiveRecordModel
{ {
const SCENARIO_UPLOAD = 'upload';
const PAGE_SIZE = 10; const PAGE_SIZE = 10;
const TEMP_FOLDER = '/uploads/temp/';
public $csv_file; public $csv_file;
public $file;
/** /**
* @inheritdoc * @inheritdoc
...@@ -45,11 +50,11 @@ class TestingTest extends \common\components\ActiveRecordModel ...@@ -45,11 +50,11 @@ class TestingTest extends \common\components\ActiveRecordModel
public function rules() public function rules()
{ {
return [ return [
[['session_id', 'name'], 'required'], [['session_id', 'name'], 'required', 'except' => self::SCENARIO_UPLOAD],
[['minutes', 'questions', 'pass_percent', 'attempt'], 'requiredNotMix'], [['minutes', 'questions', 'pass_percent', 'attempt'], 'requiredNotMix', 'except' => self::SCENARIO_UPLOAD],
[['session_id', 'minutes', 'questions', 'pass_percent', 'attempt', 'mix'], 'integer'], [['session_id', 'minutes', 'questions', 'pass_percent', 'attempt', 'mix'], 'integer', 'except' => self::SCENARIO_UPLOAD],
[['name'], 'string', 'max' => 200], [['name'], 'string', 'max' => 200, 'except' => self::SCENARIO_UPLOAD],
[['csv_file'], 'file', 'skipOnEmpty' => false, 'extensions' => 'xls, xlsx', 'on' => 'upload'], [['csv_file'], 'file', 'skipOnEmpty' => false, 'extensions' => 'xls, xlsx', 'on' => self::SCENARIO_UPLOAD],
[['mix'], 'safe'], [['mix'], 'safe'],
]; ];
} }
...@@ -65,7 +70,7 @@ class TestingTest extends \common\components\ActiveRecordModel ...@@ -65,7 +70,7 @@ class TestingTest extends \common\components\ActiveRecordModel
public function attributeLabels() public function attributeLabels()
{ {
return [ return [
'csv_file' => 'Загрузить csv-файл', 'csv_file' => 'Загрузить XLS-файл',
'attempt' => 'Количество попыток', 'attempt' => 'Количество попыток',
'session_id' => 'Сессия', 'session_id' => 'Сессия',
'name' => 'Наименование теста', 'name' => 'Наименование теста',
...@@ -128,11 +133,22 @@ class TestingTest extends \common\components\ActiveRecordModel ...@@ -128,11 +133,22 @@ class TestingTest extends \common\components\ActiveRecordModel
return ArrayHelper::map(self::find()->where(['session_id' => $session_id]), 'id', 'name'); return ArrayHelper::map(self::find()->where(['session_id' => $session_id]), 'id', 'name');
} }
private function getPath()
{
return Yii::getAlias('@webroot') . self::TEMP_FOLDER;
}
public function upload() public function upload()
{ {
if ($this->validate()) if($this->validate())
{ {
$this->csv_file->saveAs('uploads/' . date('dmYHiS_') . uniqid() . '.' . $this->imageFile->extension); if(!file_exists($this->getPath()))
{
mkdir($this->getPath(), 0777, true);
}
$this->file = $this->getPath() . date('dmYHis-') . uniqid() . '.' . $this->csv_file->extension;
$this->csv_file->saveAs($this->file);
return true; return true;
} }
else else
...@@ -140,4 +156,12 @@ class TestingTest extends \common\components\ActiveRecordModel ...@@ -140,4 +156,12 @@ class TestingTest extends \common\components\ActiveRecordModel
return false; return false;
} }
} }
public function deleteFile()
{
if(file_exists($this->file))
{
unlink($this->file);
}
}
} }
...@@ -33,9 +33,9 @@ class TestingTheme extends \common\components\ActiveRecordModel ...@@ -33,9 +33,9 @@ class TestingTheme extends \common\components\ActiveRecordModel
public function rules() public function rules()
{ {
return [ return [
[['name', 'type'], 'required'], [['name'], 'required'],
[['type'], 'integer'], [['type'], 'safe'],
[['name'], 'stirng', 'max' => 200], [['name'], 'string', 'max' => 200],
// array('id, name, type', 'safe', 'on' => 'search'), // array('id, name, type', 'safe', 'on' => 'search'),
]; ];
} }
......
...@@ -3,23 +3,31 @@ use yii\widgets\ActiveForm; ...@@ -3,23 +3,31 @@ use yii\widgets\ActiveForm;
use yii\helpers\Html; use yii\helpers\Html;
?> ?>
<style type="text/css">
#log_box p {
margin: 0;
}
</style>
<?php if (\Yii::$app->session->hasFlash('flash')): ?> <?php if (\Yii::$app->session->hasFlash('flash')): ?>
<div class="alert alert-success fade in m-b-15"> <div class="alert alert-success fade in m-b-15">
<?php echo $this->msg(\Yii::$app->session->getFlash('flash'), 'ok'); ?> <?php echo \Yii::$app->session->getFlash('flash'); ?>
<span class="close" data-dismiss="alert">×</span> <span class="close" data-dismiss="alert">×</span>
</div> </div>
<?php endif ?> <?php endif ?>
<?php if (isset($log)) : ?> <?php if (isset($log)) : ?>
<div id="log_box"><?php echo $log; ?></div> <div id="log_box"><?php echo $log; ?></div>
<hr>
<script type="text/javascript"> <script type="text/javascript">
jQuery('#log_box p').each(function(){ jQuery('#log_box p').each(function(){
var str = $(this).text(); var str = $(this).text();
var reg = /Ошибка/gi; var reg = /Ошибка/gi;
if (str.match(reg)) { if (str.match(reg)) {
$(this).css('background-color','#ccc').css('color','red'); $(this).css('color','red');
} }
}); });
</script> </script>
...@@ -32,7 +40,7 @@ use yii\helpers\Html; ...@@ -32,7 +40,7 @@ use yii\helpers\Html;
Для загрузки реестра вопросов на сайт необходимо: Для загрузки реестра вопросов на сайт необходимо:
<ol> <ol>
<li>Заполнить <a href="/upload/users/Questions_example_table.xls">шаблон</a> в формате MS Excel.</li> <li>Заполнить <a href="/uploads/templates/Questions_example_table.xlsx">шаблон</a> в формате MS Excel.</li>
<li>Сохранить файл как XLS или XLSX.</li> <li>Сохранить файл как XLS или XLSX.</li>
<li>Загрузить файл на сайт c помощью кнопки ниже.</li> <li>Загрузить файл на сайт c помощью кнопки ниже.</li>
</ol> </ol>
......
...@@ -14,7 +14,7 @@ use yii\widgets\DetailView; ...@@ -14,7 +14,7 @@ use yii\widgets\DetailView;
<p> <p>
<?= Html::a(Yii::t('content', 'Update'), ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?> <?= Html::a(Yii::t('content', 'Update'), ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Импорт вопросов из CSV-файла', ['import-tests', 'id' => $model->id], ['class' => 'btn btn-info']) ?> <?= Html::a('Импорт вопросов из XLS-файла', ['import-tests', 'id' => $model->id], ['class' => 'btn btn-info']) ?>
</p> </p>
<?= DetailView::widget([ <?= DetailView::widget([
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment