TemKa_SD 9 05/13/2019 07:24 AM (edited) Здравствуйте. Делаю новую форму для контроллеров, которые есть в админке и фронте. Класс реализован с помощью \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. На втором шаге мне нужно реализовать две кнопки, вернутся на предыдущий шаг и продолжить, как добавить вторую? Edited May 13, 2019 by TemKa_SD Share this post Link to post
TemKa_SD 9 05/13/2019 09:24 AM Остался пункт 3 и 4, но с 3 думаю сообщения формы НЕ использовать, лучше наверно IPS/output. Share this post Link to post
TemKa_SD 9 05/13/2019 03:21 PM Помогите пожалуйста, я часов 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????????????? *//* ЧТО ЗДЕСЬ УКАЗАТЬ ЧТОБЫ ПРИ НАЖАТИИ НА КНОПКУ ПРОВЕРИЛСЬ УСЛОВИЯ НИЖЕ И ВЫПОЛНИЛСЯ РЕДИРЕКТ????????????? */ 1 Share this post Link to post
siv1987 2,629 05/13/2019 06:03 PM Вопрос то в чем? Вот у вас в первом сообщение есть условие которое применяется при отправке формы - if ( $values = $form->values() ) Share this post Link to post
TemKa_SD 9 05/13/2019 10:53 PM (edited) Да, но в следующих нет формы, там работает уже $date, соответственно, если добавить это условие - оно не будет работать, так как в форме нет данных. Как мне при нажатии кнопки формы перейти на следующий шаг, со 2 на 3 и с 3 редирект, точнее какой условие создать в IF? Если делать что-то вроде $data или isset($data) или я пробовал вообще по разному, добавляя в форму &step2 и &step3 соответственно, ничего работать не хочет. P.S.: hiddenvalue Работает только во 2 шаге, если его передать - обработает как форму, в 3 шаге это уже не работает, $form->values() - пустое. Edited May 13, 2019 by TemKa_SD Share this post Link to post
newbie 1,723 05/14/2019 06:41 AM P.S.: hiddenvalue Работает только во 2 шаге, если его передать - обработает как форму, в 3 шаге это уже не работает, $form->values() - пустое. Так в 3-ем шаге тоже добавьте. Share this post Link to post
TemKa_SD 9 05/14/2019 08:24 AM Я добавлял, сегодня добавил уже полноценные поля, они в принципе там нужны тоже, только без обновления, только для чтения. Я всё сделал правильно, но оно не хочет работать, я этот код вдоль и поперек перекопал, на 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 ); } Share this post Link to post
newbie 1,723 05/14/2019 11:34 AM Потому что тут пустота:Откуда Вы это знаете? Я всё сделал правильно, но оно не хочет работать, я этот код вдоль и поперек перекопал,Нужно не копать, а смотреть, как работает 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' ] ); }На последнем шаге визард обнуляется Share this post Link to post
TemKa_SD 9 05/14/2019 11:38 AM (edited) $resetWhenDone - это я специально установил, чтобы сессии не кешировались в базу. Спасибо, заработало. У меня вопрос короткий, вот так это сейчас выглядит: http://prntscr.com/nodkdr я думаю как лучше вывести на фронте, в виде контроллера или может в настройках аккаунта, где loginhandler, но классов не нашел для переопределения этого метода. Что посоветуете? Edited May 14, 2019 by TemKa_SD Share this post Link to post
TemKa_SD 9 05/14/2019 01:59 PM (edited) 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' ]); В функцию удаления тоже добавил. Edited May 14, 2019 by TemKa_SD Share this post Link to post
Dmitriy427 198 05/14/2019 03:28 PM А я вообще не понимаю - зачем тут визард используется, все эти проверки, запросы, сохранение и сообщения об ошибке прекрасно реализуются в одной первой форме. Класс \IPS\Helpers\Wizard нужен если вы хотите выводить разные формы, в зависимости от выбора на предыдущем шаге или для формирования и обработки внешнего запроса, типа проверки телефонного номера посредством API СМС-сервиса, для ввода полученного по СМС ключа. Здесь же ничего такого не вижу в упор. Share this post Link to post
TemKa_SD 9 05/14/2019 03:47 PM Он симпотичней, на втором шаге пользователю выводятся данные которые он указал с form text disabled, на последнем шаге выводится код после сохранения данных уже в БД, этот код нужно ввести на сервере чтобы изменился статус подтверждения. Share this post Link to post
TemKa_SD 9 05/16/2019 08:57 PM Скажите еще вот что, здесь в форме указана ссылка: \IPS\Http\Url::internal( 'app=wc3&module=players&controller=players&do=form' ) я вывожу эту форму сейчас еще и во front, в принципе контроллеры и модули одинаковые, проблем не будет с этим? Или лучше использовать IPS\реквест > сетквери стринг? Ну чтобы адрес брался из запроса и добавлялось к нему просто form? Share this post Link to post