Перейти к публикации
View in the app

A better way to browse. Learn more.

Дизайн и модификация Invision Community

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

$form и \IPS\Patterns\ActiveRecord

Опубликовано:

Здравствуйте. Делаю новую форму для контроллеров, которые есть в админке и фронте. Класс реализован с помощью \IPS\Patterns\ActiveRecord, node здесь не нужен. Так как в node есть стандартно parent::form, а в ActiveRecord нету, в связи с этим у меня вопрос: если я просто реализую форму функцией public function formWizard() я смогу обращаться к ней из админки и фронта?

 

2. Спрошу тоже тут, так как вопрос касается этой формы. Сделал 3 шага, первый - указание данных, второй - их подтверждение, 3 - результат будет. При переходе на страницу app=wc3&module=players&controller=players&do=form шаги начинаются со 2, почему?

 

public function formWizard()
{
	return new \IPS\Helpers\Wizard(
		array(
			'wc3_gameplayers_connect_first_step' => function( $data )
			{
				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_first_step', 'wc3_gameplayers_connect_first_step_continue' );
				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connected_name', NULL, true, array('maxLength' => 15)));
				$form->add(new \IPS\Helpers\Form\Select('wc3_gameplayers_connected_realm', NULL, true, array(
					'options' => array(
						NULL => '',
						'server.wc3.info' => 'WC3.Info',
						'iccup.wc3.info' => 'Iccup',
						'rubattle.net' => 'RuBattle',
						'eurobattle.net' => 'EuroBattle'
					),
				)));
				$form->add( new \IPS\Helpers\Form\Select( 'wc3_gameplayers_connected_role', NULL, TRUE, array( 'options' => \IPS\wc3\Player\Role::roles(), 'parse' => 'normal' ) ) );

				if ( $values = $form->values() )
				{
					$count = \IPS\Db::i()->select( 'COUNT(*)', static::$databaseTable, array( 'name=? AND server=?', mb_strtolower($values['wc3_gameplayers_connected_name']), $values['wc3_gameplayers_connected_realm'] ) )->first();

					if ( $count > 0 )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connected_error_count' );
						return $form;
					}

					return $values;
				}

				return $form;
			},
			'wc3_gameplayers_connect_second_step' => function ( $data )
			{
				$players = array();

				foreach ( \IPS\Db::i()->select( 'name, spoofedrealm', 'wc3_gameplayers', array( 'name=?', mb_strtolower($data['wc3_gameplayers_connected_name']) ) ) as $player )
				{
					$players[ $player['name'] ] = $player['spoofedrealm'];
				}

				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_second_step', 'wc3_gameplayers_connected_add' );
				$form->addHeader('wc3_gameplayers_connect_second_step_desc');
				$form->addMessage( 'Мы нашли ' . \count($players) . ' игроков.', 'ipsMessage ipsMessage_warning', TRUE );

				if ( $values = $form->values() )
				{
					$count = \IPS\Db::i()->select( 'COUNT(*)', static::$databaseTable, array( 'name=? AND server=?', mb_strtolower($values['wc3_gameplayers_connected_name']), $values['wc3_gameplayers_connected_realm'] ) )->first();

					if ( $count > 0 )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connected_error_count' );
						return $form;
					}

					return $values;
				}

				return $form;
			},
			'wc3_gameplayers_connect_finish_step' => function ( $data )
			{
				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_finish_step', 'continue' );
				$form->addMessage( 'import_date_explain' );

				return $form;
			}
		),
		\IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' ), TRUE, NULL, TRUE, NULL
	);
}

 

3. Мне в форме в шагах 2 и 3 нужно будет использовать кастомный шаблон, для вывода тех или иных сообщений. Реализовывать его с помощью функций формы или же других?

 

4. На втором шаге мне нужно реализовать две кнопки, вернутся на предыдущий шаг и продолжить, как добавить вторую?

Изменено пользователем TemKa_SD

Рекомендованные сообщения

Опубликовано:
  • Автор

Остался пункт 3 и 4, но с 3 думаю сообщения формы НЕ использовать, лучше наверно IPS/output.

Опубликовано:
  • Автор

Помогите пожалуйста, я часов 6 эту фигню копаю и не могу сделать. Вот финальная форма:

 

public function formWizard()
{
	\IPS\Output::i()->output = new \IPS\Helpers\Wizard(
		array(
			'wc3_gameplayers_connect_first_step' => function( $data )
			{
				$form = new \IPS\Helpers\Form;
				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connected_name', NULL, true, array('maxLength' => 15)));
				$form->add(new \IPS\Helpers\Form\Select('wc3_gameplayers_connected_realm', NULL, true, array(
					'options' => array(
						NULL => '',
						'server.wc3.info' => 'WC3.Info',
						'iccup.wc3.info' => 'Iccup',
						'rubattle.net' => 'RuBattle',
						'eurobattle.net' => 'EuroBattle'
					),
				)));
				$form->add( new \IPS\Helpers\Form\Select( 'wc3_gameplayers_connected_role', NULL, TRUE, array( 'options' => \IPS\wc3\Player\Role::roles(), 'parse' => 'normal' ) ) );

				if ( $values = $form->values() )
				{
					$count = \IPS\Db::i()->select( 'COUNT(*)', static::$databaseTable, array( 'name=? AND server=?', mb_strtolower($values['wc3_gameplayers_connected_name']), $values['wc3_gameplayers_connected_realm'] ) )->first();

					if ( $count > 0 )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connected_error_count' );
						return $form;
					}

					return $values;
				}

				return (string) $form;
			},
			'wc3_gameplayers_connect_second_step' => function ( $data )
			{
				$message = NULL;
				$class = NULL;

				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_second_step', 'wc3_gameplayers_connect_second_step_button' );
				$form->addHeader('wc3_gameplayers_connect_second_step_desc');

				foreach ( \IPS\Db::i()->select( 'name, spoofedrealm', 'wc3_gameplayers', array( 'name=?', $data['wc3_gameplayers_connected_name'] ), NULL, NULL, NULL, NULL, 1 ) as $player )
				{
					if ($player['spoofedrealm'] === $data['wc3_gameplayers_connected_realm']) {
						$message = 'wc3_gameplayers_connect_second_step_message_success';
						$class = 'ipsMessage_success';
					}
					else {
						$message = 'wc3_gameplayers_connect_second_step_message_warning';
						$class = 'ipsMessage_warning';
					}
				}

				if ($message) {
					$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack($message, NULL, array( 'sprintf' => array( NULL ) ) ), 'ipsMessage ' . $class, FALSE );
				}
				else {
					$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('wc3_gameplayers_connect_second_step_message_error', NULL, array( 'sprintf' => array( NULL ) ) ), 'ipsMessage ipsMessage_error', FALSE );
				}

				if ( /* ЧТО ЗДЕСЬ УКАЗАТЬ ЧТОБЫ ПРИ НАЖАТИИ НА КНОПКУ СОХРАНИЛИСЬ ДАННЫЕ И ПЕРЕШЛО НА ШАГ 3????????????? */ )
				{
					$conn = new static;

					$conn->name = mb_strtolower($data['wc3_gameplayers_connected_name']);
					$conn->server = $data['wc3_gameplayers_connected_realm'];
					$conn->member_id = \IPS\Member::loggedIn()->member_id;
					$conn->role_id = $data['wc3_gameplayers_connected_role'];
					$conn->save();

					$data['id'] = $conn->id;

					return $data;
				}

				return (string) $form;
			},
			'wc3_gameplayers_connect_finish_step' => function ( $data )
			{
				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_finish_step', 'wc3_gameplayers_connect_finish_step_button' );
				$form->addMessage( $data['wc3_gameplayers_connected_name'] );

				if ( /* ЧТО ЗДЕСЬ УКАЗАТЬ ЧТОБЫ ПРИ НАЖАТИИ НА КНОПКУ ПРОВЕРИЛСЬ УСЛОВИЯ НИЖЕ И ВЫПОЛНИЛСЯ РЕДИРЕКТ????????????? */ )
				{
					$conn = static::load($data['id']);

					if ( $conn->_data['status'] == 'pending' )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connect_finish_step_error_status' );
						return $form;
					}

					\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players' ) );

				}

				return (string) $form;
			}
		),
		\IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' ), TRUE, NULL, TRUE, NULL
	);
}

 

Мне только осталось заменить в ней это:

 

/* ЧТО ЗДЕСЬ УКАЗАТЬ ЧТОБЫ ПРИ НАЖАТИИ НА КНОПКУ СОХРАНИЛИСЬ ДАННЫЕ И ПЕРЕШЛО НА ШАГ 3????????????? */

/* ЧТО ЗДЕСЬ УКАЗАТЬ ЧТОБЫ ПРИ НАЖАТИИ НА КНОПКУ ПРОВЕРИЛСЬ УСЛОВИЯ НИЖЕ И ВЫПОЛНИЛСЯ РЕДИРЕКТ????????????? */

Опубликовано:

Вопрос то в чем? Вот у вас в первом сообщение есть условие которое применяется при отправке формы - if ( $values = $form->values() )

Опубликовано:
  • Автор

Да, но в следующих нет формы, там работает уже $date, соответственно, если добавить это условие - оно не будет работать, так как в форме нет данных. Как мне при нажатии кнопки формы перейти на следующий шаг, со 2 на 3 и с 3 редирект, точнее какой условие создать в IF? Если делать что-то вроде $data или isset($data) или я пробовал вообще по разному, добавляя в форму &step2 и &step3 соответственно, ничего работать не хочет.

 

P.S.: hiddenvalue Работает только во 2 шаге, если его передать - обработает как форму, в 3 шаге это уже не работает, $form->values() - пустое.

Изменено пользователем TemKa_SD

Опубликовано:

P.S.: hiddenvalue Работает только во 2 шаге, если его передать - обработает как форму, в 3 шаге это уже не работает, $form->values() - пустое.

 

Так в 3-ем шаге тоже добавьте.

Опубликовано:
  • Автор

Я добавлял, сегодня добавил уже полноценные поля, они в принципе там нужны тоже, только без обновления, только для чтения. Я всё сделал правильно, но оно не хочет работать, я этот код вдоль и поперек перекопал, на 3 шаге, когда нажимаешь ЗАВЕРШИТЬ - оно переходит по этой ссылке:

 

\IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' )

 

Это не выполняет:

 

				if ( $values = $form->values() )
				{
					if ( $conn->_data['status'] == 'pending' )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connect_finish_step_error_status' );
						return $form;
					}

					\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players' ) );

				}

 

Потому что тут пустота:

 

$form->values()

 

 

public function formWizard()
{
	\IPS\Output::i()->output = new \IPS\Helpers\Wizard(
		array(
			'wc3_gameplayers_connect_first_step' => function( $data )
			{
				$form = new \IPS\Helpers\Form;
				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connected_name', NULL, true, array('maxLength' => 15)));
				$form->add(new \IPS\Helpers\Form\Select('wc3_gameplayers_connected_realm', NULL, true, array(
					'options' => array(
						NULL => '',
						'server.wc3.info' => 'WC3.Info',
						'iccup.wc3.info' => 'Iccup',
						'rubattle.net' => 'RuBattle',
						'eurobattle.net' => 'EuroBattle'
					),
				)));
				$form->add( new \IPS\Helpers\Form\Select( 'wc3_gameplayers_connected_role', NULL, TRUE, array( 'options' => \IPS\wc3\Player\Role::roles(), 'parse' => 'normal' ) ) );

				if ( $values = $form->values() )
				{
					$count = \IPS\Db::i()->select( 'COUNT(*)', static::$databaseTable, array( 'name=? AND server=?', $values['wc3_gameplayers_connected_name'], $values['wc3_gameplayers_connected_realm'] ) )->first();

					if ( $count > 0 )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connected_error_count' );
						return $form;
					}

					return $values;
				}

				return (string) $form;
			},
			'wc3_gameplayers_connect_second_step' => function ( $data )
			{
				$message = NULL;
				$class = NULL;

				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_second_step', FALSE, \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form&_step=wc3_gameplayers_connect_second_step' ) );

				foreach ( \IPS\Db::i()->select( 'name, spoofedrealm', 'wc3_gameplayers', array( 'name=?', $data['wc3_gameplayers_connected_name'] ), NULL, NULL, NULL, NULL, 1 ) as $player )
				{
					if ($player['spoofedrealm'] === $data['wc3_gameplayers_connected_realm']) {
						$message = 'wc3_gameplayers_connect_second_step_message_success';
						$class = 'ipsMessage_success';
					}
					else {
						$message = 'wc3_gameplayers_connect_second_step_message_warning';
						$class = 'ipsMessage_warning';
					}
				}

				if ($message) {
					$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack($message, NULL, array( 'sprintf' => array( $data['wc3_gameplayers_connected_realm'] ) ) ), 'ipsMessage ' . $class, FALSE );
				}
				else {
					$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('wc3_gameplayers_connect_second_step_message_error', NULL, array( 'sprintf' => array( NULL ) ) ), 'ipsMessage ipsMessage_error', FALSE );
				}

				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connected_name', $data['wc3_gameplayers_connected_name'], true, array('maxLength' => 15, 'disabled' => TRUE)));
				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connected_realm', $data['wc3_gameplayers_connected_realm'], true, array('disabled' => TRUE)));

				$form->addButton( 'wc3_gameplayers_connect_second_step_button_prev', 'link', \IPS\Http\Url::internal( "app=wc3&module=players&controller=players&do=form&_step=wc3_gameplayers_connect_first_step")->csrf(), 'ipsButton ipsButton_primary' );
				$form->addButton( 'wc3_gameplayers_connect_second_step_button', 'submit', null, 'ipsButton ipsButton_primary', array( 'tabindex' => '2', 'accesskey' => 's' ) );

				if ( $values = $form->values() )
				{
					$conn = new static;

					$conn->name = mb_strtolower($data['wc3_gameplayers_connected_name']);
					$conn->server = $data['wc3_gameplayers_connected_realm'];
					$conn->member_id = \IPS\Member::loggedIn()->member_id;
					$conn->role_id = $data['wc3_gameplayers_connected_role'];
					$conn->save();

					$data['id'] = $conn->id;

					return $data;
				}

				return (string) $form;
			},
			'wc3_gameplayers_connect_finish_step' => function ( $data )
			{
				$form = new \IPS\Helpers\Form( 'wc3_gameplayers_connect_finish_step', FALSE, \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form&_step=wc3_gameplayers_connect_finish_step' ) );
				$form->addMessage( 'wc3_gameplayers_connect_finish_step_message' );

				$conn = static::load($data['id']);

				$form->add(new \IPS\Helpers\Form\Text('wc3_gameplayers_connect_finish_step_command', '!verify ' . $conn->_data['token'], true, array()));

				$form->addButton( 'wc3_gameplayers_connect_finish_step_button', 'submit', null, 'ipsButton ipsButton_primary', array( 'tabindex' => '2', 'accesskey' => 's' ) );

				if ( $values = $form->values() )
				{
					if ( $conn->_data['status'] == 'pending' )
					{
						$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'wc3_gameplayers_connect_finish_step_error_status' );
						return $form;
					}

					\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players' ) );

				}

				return (string) $form;
			}
		),
		\IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' ), TRUE, NULL, TRUE, NULL
	);
}

Опубликовано:
Потому что тут пустота:

Откуда Вы это знаете?

 

Я всё сделал правильно, но оно не хочет работать, я этот код вдоль и поперек перекопал,

Нужно не копать, а смотреть, как работает wizard.

	/**
 * Constructor
 *
 * @param	array			$steps			An array of callback functions. Each function should return either a string to output or (if the step is done) an array (which can be blank) of arbitrary data to retain between steps (which will be passed to each callback function). The keys should be langauge keys for the title of the step.
 * @param	\IPS\Http\Url	$baseUrl		The base URL (used when moving between steps)
 * @param	bool			$showSteps		Whether or not to show the step bar
 * @param	array|NULL		$initialData	The initial data, if any
 * @param	bool			$resetWhenDone	Whether or not to reset the session data when the wizard completes
 * @param	string|array|null $ignoreQueryParams	String or array of URL params to ignore. For example, the base URL may be /submit/ but your userland code adds params /submit/?foo=bar, this changes the baseUrl and creates a new wizard session
 * @return	void
 */

У Вас $resetWhenDone = TRUE

Смотрим дальше

				/* Last step? */
			if ( $this->resetWhenDone and ( $lastStep === $activeStep ) )
			{
				/* Wipe session data */
				unset( $_SESSION[ 'wizard-' . md5( $this->baseUrl ) . '-step' ] );
				unset( $_SESSION[ 'wizard-' . md5( $this->baseUrl ) . '-data' ] );
			}

На последнем шаге визард обнуляется

Опубликовано:
  • Автор

$resetWhenDone - это я специально установил, чтобы сессии не кешировались в базу.

 

Спасибо, заработало. У меня вопрос короткий, вот так это сейчас выглядит: http://prntscr.com/nodkdr я думаю как лучше вывести на фронте, в виде контроллера или может в настройках аккаунта, где loginhandler, но классов не нашел для переопределения этого метода. Что посоветуете?

Изменено пользователем TemKa_SD

Опубликовано:

Делайте, где хотите.

Опубликовано:
  • Автор

http://prntscr.com/nofvmi Я уже всё завершил пол часа назад, сейчас вернулся другой аккаунт добавить - осталось на последнем шаге, хотя я его проходил уже и меня редиректило с формы.

 

Еще если удалить запись - её всё равно будет пытаться грузить, и ошибка 500. Что-то почистить надо наверно на финальном шаге, сейчас копаю.

 

Похоже, это условие не срабатывает: http://prntscr.com/nogc41

 

Ага, разобрался с сессиями, я так понимаю, оно автоматически не чистит, так как после выполнения шага не возвращает ничего, происходит только редирект, в таких случаях в ручную надо?

 

					unset($_SESSION[ 'wizard-' . md5( \IPS\Http\Url::internal( 'app=wc3&module=gameplayers&controller=connected&do=form' ) ) . '-step' ]);
					unset($_SESSION[ 'wizard-' . md5( \IPS\Http\Url::internal( 'app=wc3&module=gameplayers&controller=connected&do=form' ) ) . '-data' ]);

 

В функцию удаления тоже добавил.

Изменено пользователем TemKa_SD

Опубликовано:

А я вообще не понимаю - зачем тут визард используется, все эти проверки, запросы, сохранение и сообщения об ошибке прекрасно реализуются в одной первой форме.

 

Класс \IPS\Helpers\Wizard нужен если вы хотите выводить разные формы, в зависимости от выбора на предыдущем шаге или для формирования и обработки внешнего запроса, типа проверки телефонного номера посредством API СМС-сервиса, для ввода полученного по СМС ключа. Здесь же ничего такого не вижу в упор.

Опубликовано:
  • Автор

Он симпотичней, на втором шаге пользователю выводятся данные которые он указал с form text disabled, на последнем шаге выводится код после сохранения данных уже в БД, этот код нужно ввести на сервере чтобы изменился статус подтверждения.

Опубликовано:
  • Автор

Скажите еще вот что, здесь в форме указана ссылка: \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' ) я вывожу эту форму сейчас еще и во front, в принципе контроллеры и модули одинаковые, проблем не будет с этим? Или лучше использовать IPS\реквест > сетквери стринг? Ну чтобы адрес брался из запроса и добавлялось к нему просто form?

Опубликовано:

Если адреса одинаковые то не будет.

Опубликовано:
  • Автор

Есть у меня тут небольшой конфликт, можно как-то условие отобразить, если это админ панель, отображать один код, иначе другой?

Создайте аккаунт или войдите в него для комментирования

Сейчас на странице 0

  • Нет пользователей, просматривающих эту страницу.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.