Browse Source

Form module

master
Egorka 6 years ago
parent
commit
df731cae71
  1. 31
      backend/components/form_builder/assets/FormBuilderAsset.php
  2. 6
      backend/components/form_builder/js/form-builder.min.js
  3. 6
      backend/components/form_builder/js/form-render.min.js
  4. 12
      backend/components/menu/css/menu.css
  5. 2
      backend/config/main.php
  6. 3
      backend/messages/ru/menu.php
  7. 27
      backend/views/menu/menu.php
  8. 64
      common/modules/forms/FormsModule.php
  9. 109
      common/modules/forms/controllers/FormController.php
  10. 172
      common/modules/forms/controllers/manage/FormController.php
  11. 104
      common/modules/forms/controllers/manage/FormMessageController.php
  12. 122
      common/modules/forms/entities/Form.php
  13. 75
      common/modules/forms/entities/FormMessage.php
  14. 21
      common/modules/forms/entities/queries/FormQuery.php
  15. 69
      common/modules/forms/forms/FormForm.php
  16. 50
      common/modules/forms/forms/FormMessageSearch.php
  17. 56
      common/modules/forms/forms/FormSearch.php
  18. 46
      common/modules/forms/helpers/FormHelper.php
  19. 17
      common/modules/forms/mail/form-html.php
  20. 18
      common/modules/forms/mail/form-text.php
  21. 28
      common/modules/forms/messages/ru/form.php
  22. 43
      common/modules/forms/migrations/m180729_170631_create_forms_table.php
  23. 40
      common/modules/forms/migrations/m180729_170643_create_forms_messages_table.php
  24. 31
      common/modules/forms/repositories/FormMessageRepository.php
  25. 31
      common/modules/forms/repositories/FormRepository.php
  26. 2
      common/modules/forms/runtime/.gitignore
  27. 78
      common/modules/forms/services/FormManageService.php
  28. 42
      common/modules/forms/services/FormMessageManageService.php
  29. 19
      common/modules/forms/views/form/view.php
  30. 51
      common/modules/forms/views/manage/form-message/index.php
  31. 69
      common/modules/forms/views/manage/form-message/view.php
  32. 79
      common/modules/forms/views/manage/form/_form.php
  33. 71
      common/modules/forms/views/manage/form/_form/_form-builder.php
  34. 61
      common/modules/forms/views/manage/form/_form/_form-items.php
  35. 16
      common/modules/forms/views/manage/form/create.php
  36. 44
      common/modules/forms/views/manage/form/index.php
  37. 18
      common/modules/forms/views/manage/form/update.php
  38. 93
      common/modules/forms/views/manage/form/view.php
  39. 47
      common/modules/forms/widgets/FormClassField.php
  40. 389
      common/modules/forms/widgets/FormGenerator.php
  41. 151
      common/modules/forms/widgets/FormViewField.php
  42. 27
      common/modules/forms/widgets/FormWidget.php
  43. 31
      common/modules/forms/widgets/templates/DynaForm.tpl
  44. 13
      common/modules/forms/widgets/templates/DynaView.tpl
  45. 2
      common/modules/pages/entities/Page.php
  46. 15
      common/modules/pages/views/page/view.php
  47. 3
      composer.json
  48. 2
      frontend/web/themes/start/layouts/home.php
  49. 19
      frontend/web/themes/start/modules/pages/views/page/view.php

31
backend/components/form_builder/assets/FormBuilderAsset.php

@ -0,0 +1,31 @@
<?php
/**
* Created by Error202
* Date: 11.07.2018
*/
namespace backend\components\form_builder\assets;
use yii\jui\JuiAsset;
use yii\web\AssetBundle;
class FormBuilderAsset extends AssetBundle
{
public $sourcePath = '@backend/components/form_builder';
public $js = [
'js/form-builder.min.js',
'js/form-render.min.js'
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapPluginAsset',
JuiAsset::class,
];
public $publishOptions = [
'forceCopy' => YII_ENV_DEV ? true : false,
];
}

6
backend/components/form_builder/js/form-builder.min.js vendored

File diff suppressed because one or more lines are too long

6
backend/components/form_builder/js/form-render.min.js vendored

File diff suppressed because one or more lines are too long

12
backend/components/menu/css/menu.css

@ -18,7 +18,15 @@ p { line-height: 1.5em; }
* Nestable * Nestable
*/ */
.dd { position: relative; display: block; margin: 0; padding: 0; max-width: 600px; list-style: none; font-size: 13px; line-height: 20px; } .dd {
position: relative;
display: block;
margin: 0; padding: 0;
max-width: 600px;
list-style: none;
font-size: 13px;
line-height: 20px;
}
.dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; } .dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; }
@ -126,7 +134,7 @@ p { line-height: 1.5em; }
@media only screen and (min-width: 700px) { @media only screen and (min-width: 700px) {
.dd { float: left; width: 48%; } .dd { float: left; width: 70%; }
.dd + .dd { margin-left: 2%; } .dd + .dd { margin-left: 2%; }
} }

2
backend/config/main.php

@ -8,7 +8,7 @@ $params = array_merge(
return [ return [
'id' => 'app-backend', 'id' => 'app-backend',
'language' => 'ru', 'language' => 'ru_RU',
'basePath' => dirname(__DIR__), 'basePath' => dirname(__DIR__),
'aliases' => [ 'aliases' => [
'@staticRoot' => $params['staticPath'], '@staticRoot' => $params['staticPath'],

3
backend/messages/ru/menu.php

@ -21,4 +21,7 @@ return [
'Menu Item Saved' => 'Пункт меню сохранен', 'Menu Item Saved' => 'Пункт меню сохранен',
'Menu Item Deleted' => 'Пункт меню удален', 'Menu Item Deleted' => 'Пункт меню удален',
'Menu Saved' => 'Меню сохранено', 'Menu Saved' => 'Меню сохранено',
'Insert Code' => 'Код вставки',
'For template' => 'Для шаблона',
'For editor' => 'Для редактора',
]; ];

27
backend/views/menu/menu.php

@ -95,7 +95,7 @@ $this->params['breadcrumbs'][] = $this->title;
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-9"> <div class="col-md-6">
<div class="box box-default"> <div class="box box-default">
<div class="box-header with-border"><?= Yii::t('menu', 'Menu Items') ?></div> <div class="box-header with-border"><?= Yii::t('menu', 'Menu Items') ?></div>
<div class="box-body"> <div class="box-body">
@ -107,6 +107,31 @@ $this->params['breadcrumbs'][] = $this->title;
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('menu', 'Insert Code') ?></div>
<div class="box-body">
<?php
$code = Html::encode(
"<?= \core\widgets\menu\MenuWidget::widget([
'menu_id' => ".$menu->id.",
]) ?>");
?>
<p><?= Yii::t('menu', 'For template') ?></p>
<pre><?= $code ?></pre>
<?php
$code = Html::encode(
"[? \core\widgets\menu\MenuWidget::widget([
'menu_id' => ".$menu->id.",
]) ?]");
?>
<p><?= Yii::t('menu', 'For editor') ?></p>
<pre><?= $code ?></pre>
</div>
</div>
</div> </div>

64
common/modules/forms/FormsModule.php

@ -0,0 +1,64 @@
<?php
namespace common\modules\forms;
use core\components\modules\ModuleInterface;
use yii\helpers\ArrayHelper;
/**
* blog module definition class
*/
class FormsModule extends \yii\base\Module implements ModuleInterface
{
/**
* @inheritdoc
*/
public $controllerNamespace = 'common\modules\forms\controllers';
/**
* @inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
public function bootstrap($app)
{
$app->getUrlManager()->addRules([
'forms/manage/form/view/<id:\d+>' => 'forms/manage/form/view',
]);
// add languages
$app->getI18n()->translations = ArrayHelper::merge($app->getI18n()->translations, [
'form' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/modules/forms/messages',
],
]);
// add menu items
if (basename($app->getBasePath()) === 'backend') {
$app->params['adminMenu'][] = [
'label' => \Yii::t( 'form', 'Forms' ),
'icon' => 'address-card-o',
'items' => [
[
'label' => \Yii::t( 'form', 'Forms' ),
'icon' => 'caret-right',
'url' => [ '/forms/manage/form/index' ]
],
[
'label' => \Yii::t( 'form', 'Messages' ),
'icon' => 'caret-right',
'url' => [ '/forms/manage/form-message/index' ]
],
],
'visible' => \Yii::$app->user->can( 'admin' ) || \Yii::$app->user->can( 'FormsManagement' ),
];
}
}
}

109
common/modules/forms/controllers/FormController.php

@ -0,0 +1,109 @@
<?php
/**
* Created by Error202
* Date: 01.08.2018
*/
namespace common\modules\forms\controllers;
use common\modules\forms\entities\Form;
use common\modules\forms\services\FormMessageManageService;
use frontend\components\FrontendController;
use yii\base\Model;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\mail\MailerInterface;
use yii\web\NotFoundHttpException;
use Yii;
class FormController extends FrontendController
{
public $mailer;
public $message_service;
public function __construct( string $id, $module, MailerInterface $mailer, FormMessageManageService $message_service, array $config = [] ) {
parent::__construct( $id, $module, $config );
$this->mailer = $mailer;
$this->message_service = $message_service;
}
public function actionSend($id)
{
$form = $this->findModel($id);
$className = 'DynaForm' . $id;
$classPath = '\\common\\modules\\forms\\runtime\\' . $className;
/* @var $dynaForm Model */
$dynaForm = new $classPath();
if ($dynaForm->load(Yii::$app->request->post()) && $dynaForm->validate()) {
// send message
$this->sendMessage($form->data, $form, $dynaForm);
if ($form->complete_page_id) {
return $this->redirect(['/pages/page/view', 'id' => $form->complete_page_id]);
}
//return $form->complete_text;
return $this->render('view', ['text' => $form->complete_text]);
}
return $this->redirect(Yii::$app->request->referrer);
}
private function sendMessage($json_string, Form $form, $dynaForm)
{
$messageItems = $this->prepareItems($json_string, $dynaForm);
// save message
$this->message_service->create($form->id, Json::encode($messageItems, JSON_UNESCAPED_UNICODE));
//prepare e-mail message
$sent = $this->mailer->compose(
['html' => '@common/modules/forms/mail/form-html', 'text' => '@common/modules/forms/mail/form-text'],
['items' => $messageItems]
)
->setTo($form->from)
->setSubject($form->subject)
->send();
if (!$sent) {
throw new \RuntimeException('Sending error.');
}
}
private function prepareItems($json_string, $dynaForm): array
{
$items = [];
$json = Json::decode($json_string, true);
foreach ($json as $item) {
if ($item['type'] == 'button') {continue;}
if ($item['type'] == 'paragraph') {continue;}
if ($item['type'] == 'header') {continue;}
$item['name'] = str_replace( '-', '_', $item['name'] );
$items[] = [
'key' => isset($item['label']) ? $item['label'] : '',
'value' => is_array($dynaForm->{$item['name']}) ? implode(', ', array_map(function($el){return Html::encode($el);}, $dynaForm->{$item['name']})) : Html::encode($dynaForm->{$item['name']}),
];
}
return $items;
}
/*private function prepareMessage($json_string, $dynaForm): string
{
$message = '';
$json = Json::decode($json_string, true);
foreach ($json as $item) {
if ($item['type'] == 'button') {continue;}
$item['name'] = str_replace('-', '_', $item['name']);
$message.=$item['label'] . ': ' . Html::encode($dynaForm->{$item['name']}) . "\n";
}
return $message;
}*/
protected function findModel($id): Form
{
if (($model = Form::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested form does not exist.');
}
}

172
common/modules/forms/controllers/manage/FormController.php

@ -0,0 +1,172 @@
<?php
namespace common\modules\forms\controllers\manage;
use common\modules\forms\services\FormManageService;
use common\modules\forms\forms\FormSearch;
use common\modules\forms\entities\Form;
use common\modules\pages\entities\Page;
use common\modules\forms\forms\FormForm;
use yii\web\NotFoundHttpException;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\Response;
use Yii;
class FormController extends Controller
{
private $service;
public function __construct($id, $module, FormManageService $service, $config = [])
{
parent::__construct($id, $module, $config);
$this->service = $service;
}
public function behaviors(): array
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['FormsManagement'],
],
[ // all the action are accessible to admin
'allow' => true,
'roles' => ['admin'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* @return mixed
*/
public function actionIndex()
{
$searchModel = new FormSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* @param $id
*
* @return string
* @throws NotFoundHttpException
*/
public function actionView($id)
{
return $this->render('view', [
'form' => $this->findModel($id),
]);
}
/**
* @return mixed
*/
public function actionCreate()
{
$form = new FormForm();
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
try {
$form = $this->service->create($form);
return $this->redirect(['view', 'id' => $form->id]);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
}
return $this->render('create', [
'model' => $form,
]);
}
/**
* @param $id
*
* @return string|\yii\web\Response
* @throws NotFoundHttpException
*/
public function actionUpdate($id)
{
$form_model = $this->findModel($id);
$form = new FormForm($form_model);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
try {
$this->service->edit($form_model->id, $form);
return $this->redirect(['view', 'id' => $form_model->id]);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
}
return $this->render('update', [
'model' => $form,
'form_model' => $form_model,
]);
}
/**
* @param integer $id
* @return mixed
*/
public function actionDelete($id)
{
try {
$this->service->remove($id);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
return $this->redirect(['index']);
}
public function actionPageSearch($q = null, $id = null)
{
\Yii::$app->response->format = Response::FORMAT_JSON;
$out = ['results' => ['id' => '', 'text' => '']];
if (!is_null($q)) {
$data = Page::find()->select('id, title as text')->andWhere(['tree' => 1])->andWhere(['like', 'title', $q])->limit(20)->asArray()->all();
$out['results'] = array_values($data);
}
elseif ($id > 0) {
$tag_name = Page::findOne($id)->title;
$out['results'] = ['id' => $tag_name, 'text' => $tag_name];
}
else {
$data = Page::find()->select('id, title as text')->andWhere(['tree' => 1])->orderBy(['id' => SORT_DESC])->limit(20)->asArray()->all();
$out['results'] = array_values($data);
}
return $out;
}
/**
* @param integer $id
* @return Form the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id): Form
{
if (($model = Form::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested form does not exist.');
}
}

104
common/modules/forms/controllers/manage/FormMessageController.php

@ -0,0 +1,104 @@
<?php
namespace common\modules\forms\controllers\manage;
use common\modules\forms\entities\FormMessage;
use common\modules\forms\forms\FormMessageSearch;
use common\modules\forms\services\FormMessageManageService;
use yii\web\NotFoundHttpException;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\Controller;
use Yii;
class FormMessageController extends Controller
{
private $service;
public function __construct($id, $module, FormMessageManageService $service, $config = [])
{
parent::__construct($id, $module, $config);
$this->service = $service;
}
public function behaviors(): array
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['FormsManagement'],
],
[ // all the action are accessible to admin
'allow' => true,
'roles' => ['admin'],
],
],
],
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* @return mixed
*/
public function actionIndex()
{
$searchModel = new FormMessageSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* @param $id
*
* @return string
* @throws NotFoundHttpException
*/
public function actionView($id)
{
return $this->render('view', [
'message' => $this->findModel($id),
]);
}
/**
* @param integer $id
* @return mixed
*/
public function actionDelete($id)
{
try {
$this->service->remove($id);
} catch (\DomainException $e) {
Yii::$app->errorHandler->logException($e);
Yii::$app->session->setFlash('error', $e->getMessage());
}
return $this->redirect(['index']);
}
/**
* @param $id
*
* @return FormMessage
* @throws NotFoundHttpException
*/
protected function findModel($id): FormMessage
{
if (($model = FormMessage::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The message does not exist.');
}
}

122
common/modules/forms/entities/Form.php

@ -0,0 +1,122 @@
<?php
namespace common\modules\forms\entities;
use common\modules\forms\entities\queries\FormQuery;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use Yii;
/**
* @property int $id
* @property string $name
* @property int $complete_page_id
* @property string $complete_text
* @property int $created_at
* @property int $updated_at
* @property string $subject
* @property string $from
* @property string $reply
* @property string $return
* @property int $status
* @property string $data
* @property int $captcha
*
* @property FormMessage[] $messages
*
*/
class Form extends ActiveRecord
{
const STATUS_ACTIVE = 1;
const STATUS_DRAFT = 0;
public static function create(
$name,
$data,
$subject,
$from, $reply, $return,
$complete_text, $complete_page_id,
$status,
$captcha
): self
{
$form = new static();
$form->name = $name;
$form->data = $data;
$form->subject = $subject;
$form->from = $from;
$form->reply = $reply;
$form->return = $return;
$form->complete_text = $complete_text;
$form->complete_page_id = $complete_page_id;
$form->status = $status;
$form->captcha = $captcha;
return $form;
}
public function edit(
$name,
$data,
$subject,
$from, $reply, $return,
$complete_text, $complete_page_id,
$status,
$captcha
): void
{
$this->name = $name;
$this->data = $data;
$this->subject = $subject;
$this->from = $from;
$this->reply = $reply;
$this->return = $return;
$this->complete_text = $complete_text;
$this->complete_page_id = $complete_page_id;
$this->status = $status;
$this->captcha = $captcha;
}
public static function tableName(): string
{
return '{{%forms}}';
}
public function behaviors(): array
{
return [
TimestampBehavior::class,
];
}
public function transactions(): array
{
return [
self::SCENARIO_DEFAULT => self::OP_ALL,
];
}
public function attributeLabels() {
return [
'name' => Yii::t('form', 'Name'),
'data' => Yii::t('form', 'Form'),
'subject' => Yii::t('form', 'Subject'),
'from' => Yii::t('form', 'From E-mail'),
'reply' => Yii::t('form', 'Reply E-mail'),
'return' => Yii::t('form', 'Return E-mail'),
'complete_text' => Yii::t('form', 'Complete Text'),
'complete_page_id' => Yii::t('form', 'Complete Page'),
'status' => Yii::t('form', 'Status'),
'captcha' => Yii::t('form', 'Use Captcha'),
];
}
public function getMessages()
{
return $this->hasMany(FormMessage::class, ['form_id' => 'id']);
}
public static function find(): FormQuery
{
return new FormQuery(static::class);
}
}

75
common/modules/forms/entities/FormMessage.php

@ -0,0 +1,75 @@
<?php
namespace common\modules\forms\entities;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use Yii;
/**
* @property int $id
* @property int $form_id
* @property string $data
* @property int $new
* @property int $created_at
* @property int $updated_at
*
* @property Form $form
*
*/
class FormMessage extends ActiveRecord
{
const STATUS_ACTIVE = 1;
const STATUS_DRAFT = 0;
public static function create(
$form_id,
$data
): self
{
$message = new static();
$message->form_id = $form_id;
$message->data = $data;
return $message;
}
public function edit(
$form_id,
$data
): void
{
$this->form_id = $form_id;
$this->data = $data;
}
public static function tableName(): string
{
return '{{%forms_messages}}';
}
public function behaviors(): array
{
return [
TimestampBehavior::class,
];
}
public function transactions(): array
{
return [
self::SCENARIO_DEFAULT => self::OP_ALL,
];
}
public function attributeLabels() {
return [
'form_id' => Yii::t('form', 'Form'),
'data' => Yii::t('form', 'Form Data'),
];
}
public function getForm()
{
return $this->hasOne(Form::class, ['id' => 'form_id']);
}
}

21
common/modules/forms/entities/queries/FormQuery.php

@ -0,0 +1,21 @@
<?php
/**
* Created by Error202
* Date: 27.07.2018
*/
namespace common\modules\forms\entities\queries;
use common\modules\forms\entities\Form;
use yii\db\ActiveQuery;
class FormQuery extends ActiveQuery
{
public function active()
{
return $this->andWhere([
'active' => Form::STATUS_ACTIVE,
]);
}
}

69
common/modules/forms/forms/FormForm.php

@ -0,0 +1,69 @@
<?php
namespace common\modules\forms\forms;
use common\modules\forms\entities\Form;
use core\validators\SlugValidator;
use yii\base\Model;
use Yii;
class FormForm extends Model
{
public $name;
public $data;
public $subject;
public $from;
public $reply;
public $return;
public $complete_text;
public $complete_page_id;
public $status;
public $captcha;
public $_form;
public function __construct(Form $form = null, $config = [])
{
if ($form) {
$this->name = $form->name;
$this->data = $form->data;
$this->subject = $form->subject;
$this->from = $form->from;
$this->reply = $form->reply;
$this->return = $form->return;
$this->complete_text = $form->complete_text;
$this->complete_page_id = $form->complete_page_id;
$this->status = $form->status;
$this->captcha = $form->captcha;
$this->_form = $form;
}
parent::__construct($config);
}
public function rules(): array
{
return [
[['name', 'from', 'data'], 'required'],
[['status', 'captcha', 'complete_page_id'], 'integer'],
[['name', 'subject'], 'string', 'max' => 255],
[['from', 'reply', 'return'], 'email'],
[['data', 'complete_text'], 'string'],
];
}
public function attributeLabels() {
return [
'name' => Yii::t('form', 'Name'),
'data' => Yii::t('form', 'Form'),
'subject' => Yii::t('form', 'Subject'),
'from' => Yii::t('form', 'From E-mail'),
'reply' => Yii::t('form', 'Reply E-mail'),
'return' => Yii::t('form', 'Return E-mail'),
'complete_text' => Yii::t('form', 'Complete Text'),
'complete_page_id' => Yii::t('form', 'Complete Page'),
'status' => Yii::t('form', 'Status'),
'captcha' => Yii::t('form', 'Use Captcha'),
];
}
}

50
common/modules/forms/forms/FormMessageSearch.php

@ -0,0 +1,50 @@
<?php
namespace common\modules\forms\forms;
use common\modules\forms\entities\FormMessage;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class FormMessageSearch extends Model
{
public $id;
public $form_id;
public function rules(): array
{
return [
[['id', 'form_id'], 'integer'],
];
}
/**
* @param array $params
* @return ActiveDataProvider
*/
public function search(array $params): ActiveDataProvider
{
$query = FormMessage::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => ['id' => SORT_DESC]
]
]);
$this->load($params);
if (!$this->validate()) {
$query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'form_id' => $this->form_id
]);
return $dataProvider;
}
}

56
common/modules/forms/forms/FormSearch.php

@ -0,0 +1,56 @@
<?php
namespace common\modules\forms\forms;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\modules\forms\entities\Form;
class FormSearch extends Model
{
public $id;
public $name;
public $slug;
public $subject;
public function rules(): array
{
return [
[['id'], 'integer'],
[['name', 'slug', 'subject'], 'safe'],
];
}
/**
* @param array $params
* @return ActiveDataProvider
*/
public function search(array $params): ActiveDataProvider
{
$query = Form::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => ['id' => SORT_DESC]
]
]);
$this->load($params);
if (!$this->validate()) {
$query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
]);
$query
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'slug', $this->slug])
->andFilterWhere(['like', 'subject', $this->subject]);
return $dataProvider;
}
}

46
common/modules/forms/helpers/FormHelper.php

@ -0,0 +1,46 @@
<?php
/**
* Created by Error202
* Date: 29.07.2018
*/
namespace common\modules\forms\helpers;
use common\modules\forms\entities\Form;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
class FormHelper {
public static function statusList(): array
{
return [
Form::STATUS_DRAFT => Yii::t('form', 'Draft'),
Form::STATUS_ACTIVE => Yii::t('form', 'Active'),
];
}
public static function statusName($status): string
{
return ArrayHelper::getValue(self::statusList(), $status);
}
public static function statusLabel($status): string
{
switch ($status) {
case Form::STATUS_DRAFT:
$class = 'label label-default';
break;
case Form::STATUS_ACTIVE:
$class = 'label label-success';
break;
default:
$class = 'label label-default';
}
return Html::tag('span', ArrayHelper::getValue(self::statusList(), $status), [
'class' => $class,
]);
}
}

17
common/modules/forms/mail/form-html.php

@ -0,0 +1,17 @@
<?php
/**
* Created by Error202
* Date: 01.08.2018
*/
/**
* @var $this \yii\web\View
* @var $items array
*/
?>
<h3><?= Yii::t('form', 'Message from site') ?></h3>
<?php foreach ($items as $item): ?>
<?= $item['key'] ?>: <?= $item['value'] ?><br>
<?php endforeach; ?>

18
common/modules/forms/mail/form-text.php

@ -0,0 +1,18 @@
<?php
/**
* Created by Error202
* Date: 01.08.2018
*/
/**
* @var $this \yii\web\View
* @var $items array
*/
?>
<?= Yii::t('form', 'Message from site') ?>
-------
<?php foreach ($items as $item): ?>
<?= $item['key'] ?>: <?= $item['value'] ?><?php echo PHP_EOL?>
<?php endforeach; ?>

28
common/modules/forms/messages/ru/form.php

@ -0,0 +1,28 @@
<?php
return [
'Form' => 'Форма',
'Forms' => 'Формы',
'Messages' => 'Сообщения',
'Name' => 'Название',
'Subject' => 'Тема сообщения',
'From E-mail' => 'Адрес отправителя',
'Reply E-mail' => 'Адрес для ответов',
'Return E-mail' => 'Адрес для возврата',
'Complete Text' => 'Сообщение после отправки',
'Complete Page' => 'Страница после отправки',
'Status' => 'Статус',
'Use Captcha' => 'Использовать код защиты формы',
'Create Form' => 'Новая форма',
'Update Form: {name}' => 'Редактирование формы: {name}',
'Common' => 'Основное',
'Complete Message' => 'Сообщение после отправки',
'Publish' => 'Публикация',
'Select page...' => 'Укажите страницу...',
'Draft' => 'Черновик',
'Active' => 'Опубликовано',
'Insert Code' => 'Код вставки',
'For template' => 'Для шаблона',
'For editor' => 'Для редактора',
'Form Data' => 'Данные формы',
'Date' => 'Дата',
];

43
common/modules/forms/migrations/m180729_170631_create_forms_table.php

@ -0,0 +1,43 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `forms`.
*/
class m180729_170631_create_forms_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
$this->createTable('{{%forms}}', [
'id' => $this->primaryKey(),
'name' => $this->string()->notNull(),
'data' => 'LONGTEXT',
'from' => $this->string()->notNull(),
'reply' => $this->string(),
'return' => $this->string(),
'subject' => $this->string(),
'complete_text' => 'LONGTEXT',
'complete_page_id' => $this->string(),
'status' => $this->integer(1),
'captcha' => $this->integer(1)->defaultValue(0),
'created_at' => $this->integer()->unsigned(),
'updated_at' => $this->integer()->unsigned(),
], $tableOptions);
$this->createIndex('{{%idx-forms-status}}', '{{%forms}}', 'status');
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('{{%forms}}');
}
}

40
common/modules/forms/migrations/m180729_170643_create_forms_messages_table.php

@ -0,0 +1,40 @@
<?php
use yii\db\Migration;
/**
* Handles the creation of table `forms_messages`.
*/
class m180729_170643_create_forms_messages_table extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
$this->createTable('{{%forms_messages}}', [
'id' => $this->primaryKey(),
'form_id' => $this->integer()->notNull(),
'data' => 'LONGTEXT',
'new' => $this->integer(1)->defaultValue(1),
'created_at' => $this->integer()->unsigned(),
'updated_at' => $this->integer()->unsigned(),
], $tableOptions);
$this->createIndex('idx_forms_messages_form_id', '{{%forms_messages}}', 'form_id');
$this->addForeignKey('frg_forms_messages_form_id_forms_id', '{{%forms_messages}}', 'form_id', '{{%forms}}', 'id', 'CASCADE');
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropForeignKey('frg_forms_messages_form_id_forms_id', '{{%forms_messages}}');
$this->dropIndex('idx_forms_messages_form_id', '{{%forms_messages}}');
$this->dropTable('{{%forms_messages}}');
}
}

31
common/modules/forms/repositories/FormMessageRepository.php

@ -0,0 +1,31 @@
<?php
namespace common\modules\forms\repositories;
use common\modules\forms\entities\FormMessage;
use core\repositories\NotFoundException;
class FormMessageRepository
{
public function get($id): FormMessage
{
if (!$message = FormMessage::findOne($id)) {
throw new NotFoundException('Message is not found.');
}
return $message;
}
public function save(FormMessage $message): void
{
if (!$message->save()) {
throw new \RuntimeException('Saving error.');
}
}
public function remove(FormMessage $message): void
{
if (!$message->delete()) {
throw new \RuntimeException('Removing error.');
}
}
}

31
common/modules/forms/repositories/FormRepository.php

@ -0,0 +1,31 @@
<?php
namespace common\modules\forms\repositories;
use common\modules\forms\entities\Form;
use core\repositories\NotFoundException;
class FormRepository
{
public function get($id): Form
{
if (!$form = Form::findOne($id)) {
throw new NotFoundException('Form is not found.');
}
return $form;
}
public function save(Form $form): void
{
if (!$form->save()) {
throw new \RuntimeException('Saving error.');
}
}
public function remove(Form $form): void
{
if (!$form->delete()) {
throw new \RuntimeException('Removing error.');
}
}
}

2
common/modules/forms/runtime/.gitignore vendored

@ -0,0 +1,2 @@
*
!.gitignore

78
common/modules/forms/services/FormManageService.php

@ -0,0 +1,78 @@
<?php
namespace common\modules\forms\services;
use common\modules\forms\entities\Form;
use common\modules\forms\forms\FormForm;
use common\modules\forms\repositories\FormRepository;
use common\modules\forms\widgets\FormGenerator;
use yii\helpers\Json;
class FormManageService
{
private $repository;
public function __construct(FormRepository $repository)
{
$this->repository = $repository;
}
public function clearJsonLabels($json)
{
$new_data = [];
$data = Json::decode($json, true);
foreach ($data as $item) {
if (isset($item['label'])) {
$item['label'] = str_replace( '<br>', '', $item['label'] );
}
$new_data[] = $item;
}
return Json::encode($new_data, JSON_UNESCAPED_UNICODE);
}
public function create(FormForm $form): Form
{
$form = Form::create(
$form->name,
$this->clearJsonLabels($form->data),
$form->subject,
$form->from,
$form->reply,
$form->return,
$form->complete_text,
$form->complete_page_id,
$form->status,
$form->captcha
);
$this->repository->save($form);
FormGenerator::generateFormClass($form->id, Json::decode($form->data, true));
FormGenerator::generateFormView($form->id, Json::decode($form->data, true));
return $form;
}
public function edit($id, FormForm $form): void
{
$form_entity = $this->repository->get($id);
$form_entity->edit(
$form->name,
$this->clearJsonLabels($form->data),
$form->subject,
$form->from,
$form->reply,
$form->return,
$form->complete_text,
$form->complete_page_id,
$form->status,
$form->captcha
);
$this->repository->save($form_entity);
FormGenerator::generateFormClass($id, Json::decode($form->data, true));
FormGenerator::generateFormView($id, Json::decode($form->data, true));
}
public function remove($id): void
{
$form = $this->repository->get($id);
$this->repository->remove($form);
}
}

42
common/modules/forms/services/FormMessageManageService.php

@ -0,0 +1,42 @@
<?php
namespace common\modules\forms\services;
use common\modules\forms\entities\FormMessage;
use common\modules\forms\repositories\FormMessageRepository;
class FormMessageManageService
{
private $repository;
public function __construct(FormMessageRepository $repository)
{
$this->repository = $repository;
}
public function create($form_id, $data): FormMessage
{
$message = FormMessage::create(
$form_id,
$data
);
$this->repository->save($message);
return $message;
}
public function edit($id, $form_id, $data): void
{
$message = $this->repository->get($id);
$message->edit(
$form_id,
$data
);
$this->repository->save($message);
}
public function remove($id): void
{
$message = $this->repository->get($id);
$this->repository->remove($message);
}
}

19
common/modules/forms/views/form/view.php

@ -0,0 +1,19 @@
<?php
/**
* Created by Error202
* Date: 01.08.2018
*/
/**
* @var $this \yii\web\View
* @var $text string
*/
?>
<div class="form-result">
<?= $text ?>
</div>

51
common/modules/forms/views/manage/form-message/index.php

@ -0,0 +1,51 @@
<?php
use common\modules\forms\entities\FormMessage;
use yii\grid\ActionColumn;
use yii\helpers\Html;
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use common\modules\forms\entities\Form;
/* @var $this yii\web\View */
/* @var $searchModel \common\modules\forms\forms\FormMessageSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('form', 'Messages');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="messages-index">
<div class="box">
<div class="box-body">
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'label' => Yii::t('form', 'Date'),
'attribute' => 'created_at',
'value' => function(FormMessage $model) {
return date('d.m.Y H:i', $model->created_at);
},
'options' => ['style' => 'width: 100px;'],
],
[
'label' => Yii::t('form', 'Form'),
'filter' => ArrayHelper::map(Form::find()->all(), 'id', 'name'),
'attribute' => 'form_id',
'value' => function (FormMessage $model) {
return Html::a(Html::encode($model->form->name), ['view', 'id' => $model->id]);
},
'format' => 'raw',
],
[
'class' => ActionColumn::class,
'options' => ['style' => 'width: 100px;'],
'contentOptions' => ['class' => 'text-center'],
],
],
]); ?>
</div>
</div>
</div>

69
common/modules/forms/views/manage/form-message/view.php

@ -0,0 +1,69 @@
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use common\modules\forms\entities\FormMessage;
use yii\helpers\Json;
/* @var $this yii\web\View */
/* @var $message FormMessage */
$this->title = $message->form->name . ': ' . date('d.m.Y H:i', $message->created_at);
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Messages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
$data = Json::decode($message->data, true);
?>
<div class="message-view">
<p>
<?= Html::a(Yii::t('form','Messages'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['delete', 'id' => $message->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]) ?>
</p>
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-body">
<table class="table">
<tbody>
<?php foreach ($data as $item): ?>
<tr>
<td>
<?= $item['key'] ?>
</td>
<td>
<?= Yii::$app->formatter->asNtext($item['value']) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- <div class="box">
<div class="box-header with-border">< ?= Yii::t('page', 'Complete Message') ?></div>
<div class="box-body">
< ?= Yii::$app->formatter->asHtml($form->complete_text, [
'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true,
'Output.FlashCompat' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
]) ?>
</div>
</div> -->
</div>
</div>
</div>

79
common/modules/forms/views/manage/form/_form.php

@ -0,0 +1,79 @@
<?php
use yii\helpers\Html;
use kartik\form\ActiveForm;
use common\modules\forms\helpers\FormHelper;
/* @var $this yii\web\View */
/* @var $model \common\modules\forms\forms\FormForm */
/* @var $form yii\widgets\ActiveForm */
$js2 = '
$(".hint-block").each(function () {
var $hint = $(this);
var label = $hint.parent().find("label");
label.html(label.html() + \' <i style="color:#3c8dbc" class="fa fa-question-circle" aria-hidden="true"></i>\');
label.addClass("help").popover({
html: true,
trigger: "hover",
placement: "bottom",
content: $hint.html()
});
$(this).hide();
});
';
$this->registerJs($js2);
?>
<div class="form-form">
<?php $form = ActiveForm::begin([
'id' => 'form_constructor'
]); ?>
<div class="row">
<div class="col-md-10">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Common') ?></div>
<div class="box-body">
<?= \yii\bootstrap\Tabs::widget([
'items' => [
[
'label' => Yii::t('form', 'Common'),
'content' => $this->render('_form/_form-items', ['model' => $model, 'form' => $form]),
'active' => true,
],
[
'label' => Yii::t('form', 'Form'),
'content' => $this->render('_form/_form-builder', ['model' => $model]),
]
],
]) ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton(Yii::t('buttons', 'Save'), ['class' => 'btn btn-success']) ?>
</div>
</div>
<div class="col-md-2">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Publish') ?></div>
<div class="box-body">
<?= $form->field($model, 'status')->radioList(FormHelper::statusList()) ?>
</div>
</div>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>

71
common/modules/forms/views/manage/form/_form/_form-builder.php

@ -0,0 +1,71 @@
<?php
/**
* Created by Error202
* Date: 29.07.2018
*/
use \yii\helpers\Json;
/**
* @var $this \yii\web\View
* @var $model \common\modules\forms\forms\FormForm
*/
\backend\components\form_builder\assets\FormBuilderAsset::register($this);
$lng = str_replace('_', '-', Yii::$app->language);
$data = $model->data ? Json::encode($model->data, JSON_UNESCAPED_UNICODE) : '[]';
$js = <<<JS
var options = {
controlOrder: [
'text',
'textarea',
'button'
],
disableFields: [
'number', 'autocomplete', 'date', 'file'
],
i18n: {
locale: '{$lng}'
},
showActionButtons: false,
formData: {$data},
fields: [{
label: 'E-mail',
type: 'text',
subtype: "email",
placeholder: 'name@email.com',
icon: '✉'
}]
};
var editor = document.getElementById('fb-editor');
var fb = $(editor).formBuilder(options);
//document.addEventListener('fieldAdded', function(e) { alert(JSON.stringify( fb.actions.getData('json'))); });
$('#form_constructor').on('beforeValidate', function (e) {
//var json = JSON.stringify( fb.actions.getData('json'));
var json = fb.actions.getData('json');
$("#formform-data").val(json);
//alert(json);
return true;
});
/*var init_data = '';
if (init_data) {
fb.actions.setData(init_data);
}*/
JS;
$this->registerJs($js, $this::POS_READY);
$css = <<<CSS
.stage-wrap .frmb {
height: 200px;
}
CSS;
$this->registerCss($css);
?>
<div class="form-builder-container" style="padding: 20px; overflow: auto">
<div id="fb-editor"></div>
</div>

61
common/modules/forms/views/manage/form/_form/_form-items.php

@ -0,0 +1,61 @@
<?php
/**
* Created by Error202
* Date: 29.07.2018
*/
use mihaildev\ckeditor\CKEditor;
use yii\web\JsExpression;
use yii\helpers\Url;
/**
* @var $this \yii\web\View
* @var $form \yii\widgets\ActiveForm
* @var $model \common\modules\forms\forms\FormForm
*/
$fetchUrl = Url::to( [ '/forms/manage/form/page-search' ] );
?>
<div class="forms-form">
<div class="row">
<div class="col-md-6"><?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?></div>
<div class="col-md-6"><?= $form->field($model, 'subject')->textInput(['maxlength' => true]) ?></div>
</div>
<div class="row">
<div class="col-md-4">
<?= $form->field($model, 'from')->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-4">
<?= $form->field($model, 'reply')->textInput(['maxlength' => true]) ?>
</div>
<div class="col-md-4">
<?= $form->field($model, 'return')->textInput(['maxlength' => true]) ?>
</div>
</div>
<?= $form->field($model, 'complete_text')->widget(CKEditor::class) ?>
<?= $form->field($model, 'complete_page_id')->widget(\kartik\widgets\Select2::class, [
'options' => [
'placeholder' => Yii::t('form', 'Select page...'),
'id' => 'page_select',
],
'pluginOptions' => [
'allowClear' => true,
'ajax' => [
'url' => $fetchUrl,
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }')
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(tag) { return tag.text; }'),
'templateSelection' => new JsExpression('function (tag) { return tag.text; }'),
],
]) ?>
<?= $form->field($model, 'data')->hiddenInput()->label(false) ?>
</div>

16
common/modules/forms/views/manage/form/create.php

@ -0,0 +1,16 @@
<?php
/* @var $this yii\web\View */
/* @var $model \common\modules\forms\forms\FormForm */
$this->title = Yii::t('form', 'Create Form');
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Forms'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="form-create">
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

44
common/modules/forms/views/manage/form/index.php

@ -0,0 +1,44 @@
<?php
use common\modules\forms\entities\Form;
use yii\grid\ActionColumn;
use yii\helpers\Html;
use yii\grid\GridView;
/* @var $this yii\web\View */
/* @var $searchModel \common\modules\forms\forms\FormSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = Yii::t('form', 'Forms');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="forms-index">
<p>
<?= Html::a(Yii::t('form','Create Form'), ['create'], ['class' => 'btn btn-success']) ?>
</p>
<div class="box">
<div class="box-body">
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'name',
'value' => function (Form $model) {
return Html::a(Html::encode($model->name), ['view', 'id' => $model->id]);
},
'format' => 'raw',
],
'subject',
[
'class' => ActionColumn::class,
'options' => ['style' => 'width: 100px;'],
'contentOptions' => ['class' => 'text-center'],
],
],
]); ?>
</div>
</div>
</div>

18
common/modules/forms/views/manage/form/update.php

@ -0,0 +1,18 @@
<?php
/* @var $this yii\web\View */
/* @var $form_model \common\modules\forms\entities\Form */
/* @var $model \common\modules\forms\forms\FormForm */
$this->title = Yii::t('form', 'Update Form: {name}', ['name' => $form_model->name]);
$this->params['breadcrumbs'][] = ['label' => Yii::t('page', 'Pages'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $form_model->name, 'url' => ['view', 'id' => $form_model->id]];
$this->params['breadcrumbs'][] = Yii::t('buttons', 'Editing');
?>
<div class="form-update">
<?= $this->render('_form', [
'model' => $model,
]) ?>
</div>

93
common/modules/forms/views/manage/form/view.php

@ -0,0 +1,93 @@
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
/* @var $this yii\web\View */
/* @var $form \common\modules\forms\entities\Form */
$this->title = $form->name;
$this->params['breadcrumbs'][] = ['label' => Yii::t('form', 'Forms'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="form-view">
<p>
<?= Html::a(Yii::t('form','Forms'), ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::a(Yii::t('buttons', 'Edit'), ['update', 'id' => $form->id], ['class' => 'btn btn-primary']) ?>
<?= Html::a(Yii::t('buttons', 'Delete'), ['delete', 'id' => $form->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => Yii::t('buttons', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]) ?>
</p>
<div class="row">
<div class="col-md-9">
<div class="box">
<div class="box-header with-border"><?= Yii::t('form', 'Common') ?></div>
<div class="box-body">
<?= DetailView::widget([
'model' => $form,
'attributes' => [
'id',
'name',
'subject',
'from',
'reply',
'return',
'status',
'captcha',
'complete_page_id'
],
]) ?>
</div>
</div>
<div class="box">
<div class="box-header with-border"><?= Yii::t('page', 'Complete Message') ?></div>
<div class="box-body">
<?= Yii::$app->formatter->asHtml($form->complete_text, [
'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true,
'Output.FlashCompat' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
]) ?>
</div>
</div>
</div>
<div class="col-md-3">
<div class="box box-default">
<div class="box-header with-border"><?= Yii::t('form', 'Insert Code') ?></div>
<div class="box-body">
<?php
$code = Html::encode(
"<?= \common\modules\\forms\widgets\FormWidget::widget([
'id' => ".$form->id.",
]) ?>");
?>
<p><?= Yii::t('form', 'For template') ?></p>
<pre><?= $code ?></pre>
<?php
$code = Html::encode(
"[? \common\modules\\forms\widgets\FormWidget::widget([
'id' => ".$form->id.",
]) ?]");
?>
<p><?= Yii::t('menu', 'For editor') ?></p>
<pre><?= $code ?></pre>
</div>
</div>
</div>
</div>
</div>

47
common/modules/forms/widgets/FormClassField.php

@ -0,0 +1,47 @@
<?php
/**
* Created by Error202
* Date: 02.08.2018
*/
namespace common\modules\forms\widgets;
class FormClassField
{
public function text(array $settings): string
{
if ($settings['subtype'] == 'email') {
return "['{$settings['name']}', 'email'],";
}
return "['{$settings['name']}', 'string'],";
}
public function textarea(array $settings): string
{
return "['{$settings['name']}', 'string'],";
}
public function hidden(array $settings): string
{
return "['{$settings['name']}', 'string'],";
}
public function checkboxGroup(array $settings): string
{
return "['{$settings['name']}', 'each', 'rule' => ['string']],";
}
public function radioGroup(array $settings): string
{
return "['{$settings['name']}', 'string'],";
}
public function select(array $settings): string
{
if (isset($settings['multiple']) && $settings['multiple'] == true) {
return "['{$settings['name']}', 'each', 'rule' => ['string']],";
}
return "['{$settings['name']}', 'string'],";
}
}

389
common/modules/forms/widgets/FormGenerator.php

@ -0,0 +1,389 @@
<?php
/**
* Created by Error202
* Date: 31.07.2018
*/
namespace common\modules\forms\widgets;
use yii\web\View;
class FormGenerator
{
public static function generateFormView($id, $json)
{
$viewName = 'DynaView' . $id;
$fields = [];
$fieldRender = new FormViewField();
//print_r($json); die;
foreach ($json as $item) {
if ( isset( $item['name'] ) ) {
$item['name'] = str_replace( '-', '_', $item['name'] );
}
switch ($item['type']) {
case 'text':
$fields[] = $fieldRender->text($item);
break;
case 'header':
$fields[] = $fieldRender->header($item);
break;
case 'paragraph':
$fields[] = $fieldRender->paragraph($item);
break;
case 'hidden':
$fields[] = $fieldRender->hidden($item);
break;
case 'radio-group':
$fields[] = $fieldRender->radioGroup($item);
break;
case 'checkbox-group':
$fields[] = $fieldRender->checkboxGroup($item);
break;
case 'select':
$fields[] = $fieldRender->select($item);
break;
case 'button':
$fields[] = $fieldRender->button($item);
break;
case 'textarea':
$fields[] = $fieldRender->textArea($item);
break;
}
}
$fields = implode("\n", $fields);
$tpl = file_get_contents(\Yii::getAlias('@common/modules/forms/widgets/templates/DynaView.tpl'));
$tpl = preg_replace([
'/\{\$fields\}/'
], [
$fields
], $tpl);
file_put_contents(\Yii::getAlias('@common/modules/forms/runtime/' . $viewName . '.php'), $tpl);
}
public static function generateFormView2($id, $json)
{
$viewName = 'DynaView' . $id;
$fields = [];
foreach ($json as $item) {
if (isset($item['name'])) {
$item['name'] = str_replace( '-', '_', $item['name'] );
}
if ($item['type'] == 'text') {
$options = [];
$options[] = isset($item['placeholder']) ? "'placeholder' => '{$item['placeholder']}'" : "";
$options[] = isset($item['value']) ? "'value' => '{$item['value']}'" : "";
$options[] = isset($item['maxlength']) ? "'maxlength' => true" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $item['description'] : '';
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')->textInput([{$options}])->hint('{$description}') ?>";
}
elseif ($item['type'] == 'header' || $item['type'] == 'paragraph') {
$fields[] = "<{$item['subtype']}>{$item['label']}</{$item['subtype']}>";
}
elseif ($item['type'] == 'textarea') {
$options = [];
$options[] = isset($item['rows']) ? "'rows' => {$item['rows']}" : "";
$options[] = isset($item['placeholder']) ? "'placeholder' => '{$item['placeholder']}'" : "";
$options[] = isset($item['value']) ? "'value' => '{$item['value']}'" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $item['description'] : '';
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')->textarea([{$options}])->hint('{$description}') ?>";
}
elseif ($item['type'] == 'hidden') {
$options = [];
$options[] = isset($item['value']) ? "'value' => '{$item['value']}'" : "";
$options = implode(',', array_filter($options));
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')->hiddenInput([{$options}])->label(false) ?>";
}
elseif ($item['type'] == 'radio-group') {
$values = [];
$selected = [];
foreach ($item['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
if ($selected) {
$fields[] = "<?php \$model->{$item['name']} = [{$selected}] ?>";
}
$options = [];
//$options[] = $selected ? "'value' => [{$selected}]" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $item['description'] : '';
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')
->radioList([
{$values}
], [{$options}])->hint('{$description}'); ?>";
}
elseif ($item['type'] == 'checkbox-group') {
$values = [];
$selected = [];
foreach ($item['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
if ($selected) {
$fields[] = "<?php \$model->{$item['name']} = [{$selected}] ?>";
}
$options = [];
//$options[] = $selected ? "'value' => [{$selected}]" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $item['description'] : '';
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')
->checkboxList([
{$values}
], [{$options}])->hint('{$description}'); ?>";
}
elseif ($item['type'] == 'select') {
$values = [];
$selected = [];
foreach ($item['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
$options = [];
$options[] = $selected ? "'value' => [{$selected}]" : "";
$options[] = isset($item['placeholder']) ? "'prompt' => '{$item['placeholder']}'" : "";
$options[] = isset($item['multiple']) && $item['multiple'] == true ? "'multiple' => 'multiple'" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $item['description'] : '';
$fields[] = "<?= \$form->field(\$model, '{$item['name']}')->dropDownList([{$values}], [{$options}])->hint('{$description}') ?>";
}
elseif ($item['type'] == 'button' && $item['subtype'] == 'submit') {
$fields[] = <<<BUTTON
<div class="form-group">
<?= Html::submitButton('{$item['label']}', [
'class' => 'btn btn-success',
]) ?>
</div>
BUTTON;
}
}
// prepare
$fields = implode("\n", $fields);
$view = <<<VIEW
<?php
use kartik\\form\\ActiveForm;
use yii\\helpers\\Html;
?>
<?php \$form = ActiveForm::begin([
'action' => ['/forms/form/send', 'id' => \$form_entity->id],
]); ?>
{$fields}
<?php ActiveForm::end(); ?>
VIEW;
file_put_contents(\Yii::getAlias('@common/modules/forms/runtime/' . $viewName . '.php'), $view);
}
public static function generateFormClass2($id, $json)
{
$className = 'DynaForm' . $id;
$publicVars = [];
$rule = [];
$labels = [];
$fieldClass = new FormClassField();
foreach ($json as $item) {
if (isset($item['name'])) {
$item['name'] = str_replace( '-', '_', $item['name'] );
}
if ($item['type'] == 'button') {continue;}
if ($item['type'] == 'paragraph') {continue;}
if ($item['type'] == 'header') {continue;}
// public
$publicVars[] = 'public $' . $item['name'] . ';';
// required
if (isset($item['required']) && $item['required'] == 1) {
$rule[] = "['{$item['name']}', 'required'],";
}
// rules
switch ($item['type']) {
case 'text':
$rule[] = $fieldClass->text($item);
break;
case 'textarea':
$rule[] = $fieldClass->textarea($item);
break;
case 'hidden':
$rule[] = $fieldClass->hidden($item);
break;
case 'select':
$rule[] = $fieldClass->select($item);
break;
case 'checkbox-group':
$rule[] = $fieldClass->checkboxGroup($item);
break;
case 'radio-group':
$rule[] = $fieldClass->radioGroup($item);
break;
}
if (isset($item['label'])) {
$labels[] = "'{$item['name']}' => '{$item['label']}',";
}
}
// prepare data
$publicVars = implode("\n", $publicVars);
$rule = implode("\n", $rule);
$labels = implode("\n", $labels);
$classData = <<<CLASS
<?php
namespace common\\modules\\forms\\runtime;
use yii\\base\\Model;
class {$className} extends Model
{
{$publicVars}
public function rules(): array
{
return [
{$rule}
];
}
public function attributeLabels() {
return [
{$labels}
];
}
}
CLASS;
file_put_contents(\Yii::getAlias('@common/modules/forms/runtime/' . $className . '.php'), $classData);
}
public static function generateFormClass($id, $json)
{
$className = 'DynaForm' . $id;
$publicVars = [];
$rule = [];
$labels = [];
foreach ($json as $item) {
if (isset($item['name'])) {
$item['name'] = str_replace( '-', '_', $item['name'] );
}
if ($item['type'] == 'button') {continue;}
if ($item['type'] == 'paragraph') {continue;}
if ($item['type'] == 'header') {continue;}
// public
$publicVars[] = 'public $' . $item['name'] . ';';
// rule
if (isset($item['required']) && $item['required'] == 1)
{
$rule[] = "['{$item['name']}', 'required'],";
}
if (
($item['type'] == 'text' && $item['subtype'] == 'text') ||
($item['type'] == 'textarea' && $item['subtype'] == 'textarea') ||
($item['type'] == 'hidden')
)
{
$rule[] = "['{$item['name']}', 'string'],";
}
if ($item['type'] == 'text' && $item['subtype'] == 'email') {
$rule[] = "['{$item['name']}', 'email'],";
}
if ($item['type'] == 'checkbox-group') {
$rule[] = "['{$item['name']}', 'each', 'rule' => ['string']],";
}
if ($item['type'] == 'radio-group') {
$rule[] = "['{$item['name']}', 'string'],";
}
if ($item['type'] == 'select' && isset($item['multiple']) && $item['multiple'] == true) {
$rule[] = "['{$item['name']}', 'each', 'rule' => ['string']],";
}
if ($item['type'] == 'select' && !isset($item['multiple'])) {
$rule[] = "['{$item['name']}', 'string'],";
}
if (isset($item['label'])) {
$labels[] = "'{$item['name']}' => '{$item['label']}',";
}
}
// prepare data
$publicVars = implode("\n", $publicVars);
$rule = implode("\n", $rule);
$labels = implode("\n", $labels);
$classData = <<<CLASS
<?php
namespace common\\modules\\forms\\runtime;
use yii\\base\\Model;
class {$className} extends Model
{
{$publicVars}
public function rules(): array
{
return [
{$rule}
];
}
public function attributeLabels() {
return [
{$labels}
];
}
}
CLASS;
file_put_contents(\Yii::getAlias('@common/modules/forms/runtime/' . $className . '.php'), $classData);
}
}

151
common/modules/forms/widgets/FormViewField.php

@ -0,0 +1,151 @@
<?php
/**
* Created by Error202
* Date: 02.08.2018
*/
namespace common\modules\forms\widgets;
class FormViewField
{
public function text(array $settings): string
{
$options = [];
$options[] = isset($item['placeholder']) ? "'placeholder' => '{$settings['placeholder']}'" : "";
$options[] = isset($item['value']) ? "'value' => '{$settings['value']}'" : "";
$options[] = isset($item['maxlength']) ? "'maxlength' => true" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $settings['description'] : '';
$field = "<?= \$form->field(\$model, '{$settings['name']}')->textInput([{$options}])->hint('{$description}') ?>";
return $field;
}
public function textArea(array $settings): string
{
$options = [];
$options[] = isset($item['rows']) ? "'rows' => {$settings['rows']}" : "";
$options[] = isset($item['placeholder']) ? "'placeholder' => '{$settings['placeholder']}'" : "";
$options[] = isset($item['value']) ? "'value' => '{$settings['value']}'" : "";
$options = implode(',', array_filter($options));
$description = isset($item['description']) ? $settings['description'] : '';
$field = "<?= \$form->field(\$model, '{$settings['name']}')->textarea([{$options}])->hint('{$description}') ?>";
return $field;
}
public function header(array $settings): string
{
$field = "<{$settings['subtype']}>{$settings['label']}</{$settings['subtype']}>";
return $field;
}
public function paragraph(array $settings): string
{
$field = "<{$settings['subtype']}>{$settings['label']}</{$settings['subtype']}>";
return $field;
}
public function hidden(array $settings): string
{
$options = [];
$options[] = isset($item['value']) ? "'value' => '{$settings['value']}'" : "";
$options = implode(',', array_filter($options));
$field = "<?= \$form->field(\$model, '{$settings['name']}')->hiddenInput([{$options}])->label(false) ?>";
return $field;
}
public function radioGroup(array $settings): string
{
$values = [];
$selected = [];
foreach ($settings['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
if ($selected) {
$fields[] = "<?php \$model->{$settings['name']} = [{$selected}] ?>";
}
$options = [];
$options = implode(',', array_filter($options));
$description = isset($settings['description']) ? $settings['description'] : '';
$field = "<?= \$form->field(\$model, '{$settings['name']}')
->radioList([
{$values}
], [{$options}])->hint('{$description}'); ?>";
return $field;
}
public function checkboxGroup(array $settings): string
{
$values = [];
$selected = [];
foreach ($settings['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
if ($selected) {
$fields[] = "<?php \$model->{$settings['name']} = [{$selected}] ?>";
}
$options = [];
$options = implode(',', array_filter($options));
$description = isset($settings['description']) ? $settings['description'] : '';
$field = "<?= \$form->field(\$model, '{$settings['name']}')
->checkboxList([
{$values}
], [{$options}])->hint('{$description}'); ?>";
return $field;
}
public function select(array $settings): string
{
$values = [];
$selected = [];
foreach ($settings['values'] as $value) {
$values[] = "'{$value['value']}' => '{$value['label']}'";
if (isset($value['selected']) && $value['selected'] == true) {
$selected[] = "'{$value['value']}'";
}
}
$values = implode(',', $values);
$selected = implode(',', $selected);
$options = [];
$options[] = $selected ? "'value' => [{$selected}]" : "";
$options[] = isset($settings['placeholder']) ? "'prompt' => '{$settings['placeholder']}'" : "";
$options[] = isset($settings['multiple']) && $settings['multiple'] == true ? "'multiple' => 'multiple'" : "";
$options = implode(',', array_filter($options));
$description = isset($settings['description']) ? $settings['description'] : '';
$field = "<?= \$form->field(\$model, '{$settings['name']}')->dropDownList([{$values}], [{$options}])->hint('{$description}') ?>";
return $field;
}
public function button(array $settings): string
{
$style = isset($settings['style']) ? $settings['style'] : 'default';
if ($settings['subtype'] == 'submit') {
$field = "<div class=\"form-group\"><?= Html::submitButton('{$settings['label']}', ['class' => 'btn btn-{$style}']) ?></div>";
return $field;
}
elseif ($settings['subtype'] == 'button') {
$field = "<div class=\"form-group\"><?= Html::button('{$settings['label']}', ['class' => 'btn btn-{$style}']) ?></div>";
return $field;
}
elseif ($settings['subtype'] == 'reset') {
$field = "<div class=\"form-group\"><?= Html::resetButton('{$settings['label']}', ['class' => 'btn btn-{$style}']) ?></div>";
return $field;
}
return '';
}
}

27
common/modules/forms/widgets/FormWidget.php

@ -0,0 +1,27 @@
<?php
/**
* Created by Error202
* Date: 31.07.2018
*/
namespace common\modules\forms\widgets;
use common\modules\forms\entities\Form;
use yii\base\Widget;
class FormWidget extends Widget
{
public $id;
public function run() {
$form = Form::findOne($this->id);
if (!$form) {
return 'Form is not found';
}
$className = 'DynaForm' . $this->id;
$classPath = '\\common\\modules\\forms\\runtime\\' . $className;
$dynaForm = new $classPath();
return $this->renderFile(\Yii::getAlias('@common/modules/forms/runtime/' . 'DynaView' . $this->id . '.php'), ['model' => $dynaForm, 'form_entity' => $form]);
}
}

31
common/modules/forms/widgets/templates/DynaForm.tpl

@ -0,0 +1,31 @@
<?php
namespace common\modules\forms\runtime;
use yii\base\Model;
class DynaForm1 extends Model
{
public $text_1533113814416;
public $text_1533058533530;
public $textarea_1533057466900;
public function rules(): array
{
return [
['text_1533113814416', 'required'],
['text_1533113814416', 'string'],
['text_1533058533530', 'required'],
['text_1533058533530', 'email'],
['textarea_1533057466900', 'required'],
['textarea_1533057466900', 'string'],
];
}
public function attributeLabels() {
return [
'text_1533113814416' => 'Ваше имя',
'text_1533058533530' => 'E-mail',
'textarea_1533057466900' => 'Сообщение',
];
}
}

13
common/modules/forms/widgets/templates/DynaView.tpl

@ -0,0 +1,13 @@
<?php
use kartik\form\ActiveForm;
use yii\helpers\Html;
?>
<?php $form = ActiveForm::begin([
'action' => ['/forms/form/send', 'id' => $form_entity->id],
]); ?>
{$fields}
<?php ActiveForm::end(); ?>

2
common/modules/pages/entities/Page.php

@ -17,7 +17,7 @@ use Yii;
* @property string $content * @property string $content
* @property int $created_at * @property int $created_at
* @property int $updated_at * @property int $updated_at
* @property string meta_json * @property string $meta_json
* @property int $tree * @property int $tree
* @property int $lft * @property int $lft
* @property int $rgt * @property int $rgt

15
common/modules/pages/views/page/view.php

@ -20,13 +20,22 @@ $this->params['breadcrumbs'][] = $page->title;
<article class="page-view"> <article class="page-view">
<h1><?= Html::encode($page->title) ?></h1> <h1><?= Html::encode($page->title) ?></h1>
<!--
<?= Yii::$app->formatter->asHtml($page->content, [ < ?= preg_replace('/[?= (*.) ?]/m', '', Yii::$app->formatter->asHtml($page->content, [
'Attr.AllowedRel' => array('nofollow'), 'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true, 'HTML.SafeObject' => true,
'Output.FlashCompat' => true, 'Output.FlashCompat' => true,
'HTML.SafeIframe' => true, 'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', 'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
]) ?> ])) ?> -->
<?= preg_replace_callback('/\[\?= (.*) \?\]/gm', function ($m) {
return $m[1];
}, Yii::$app->formatter->asHtml($page->content, [
'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true,
'Output.FlashCompat' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
])) ?>
</article> </article>

3
composer.json

@ -38,7 +38,8 @@
"yiisoft/yii2-imagine": "^2.1", "yiisoft/yii2-imagine": "^2.1",
"zertex/yii2-avatar-generator": "*", "zertex/yii2-avatar-generator": "*",
"paulzi/yii2-sortable": "^1.0", "paulzi/yii2-sortable": "^1.0",
"paulzi/yii2-adjacency-list" : "^2.1" "paulzi/yii2-adjacency-list" : "^2.1",
"yiisoft/yii2-jui": "^2.0"
}, },
"require-dev": { "require-dev": {
"yiisoft/yii2-debug": "~2.0.0", "yiisoft/yii2-debug": "~2.0.0",

2
frontend/web/themes/start/layouts/home.php

@ -43,6 +43,8 @@
<div class="container"> <div class="container">
<?= \common\modules\forms\widgets\FormWidget::widget(['id' => 1]) ?>
<h1 class="my-4">Welcome to Modern Business</h1> <h1 class="my-4">Welcome to Modern Business</h1>
<!-- Marketing Icons Section --> <!-- Marketing Icons Section -->

19
frontend/web/themes/start/modules/pages/views/page/view.php

@ -21,12 +21,17 @@ $this->params['breadcrumbs'][] = $page->title;
<h1><?= Html::encode($page->title) ?></h1> <h1><?= Html::encode($page->title) ?></h1>
<?= Yii::$app->formatter->asHtml($page->content, [ <?= preg_replace_callback('/\[\?= (.*)\((.*)\) \?\]/m', function ($m) {
'Attr.AllowedRel' => array('nofollow'), $array = [];
'HTML.SafeObject' => true, $string = Html::decode($m[2]);
'Output.FlashCompat' => true, eval("\$array = $string;");
'HTML.SafeIframe' => true, return $m[1]($array);
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%', }, Yii::$app->formatter->asHtml($page->content, [
]) ?> 'Attr.AllowedRel' => array('nofollow'),
'HTML.SafeObject' => true,
'Output.FlashCompat' => true,
'HTML.SafeIframe' => true,
'URI.SafeIframeRegexp'=>'%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%',
])) ?>
</article> </article>

Loading…
Cancel
Save