Using kirby builder to add new radio-button options from the panel?

Digging through the forum, something like this?

if(r::is('POST') && $data = get()) {
    $partners = $page->children()->visible()->filter(function($child) use($keys, $data) {

      foreach($data as $key => $value) {

        if($value && in_array($key, $keys)) {

          if(! $match = in_array($value, $child->$key()->split(','))) {

            return false;
          }
        }
      }

    return $child;

    });
  }

Let me ask the question differently: What do you expect your $data array to look like, can you give me an example?

Yes, sorry for my confusion and thanks for you constant patience.

So since it is a survey, I’d like to get an array that prints both the question and the answer below. Sometimes a question has another question inside it (based on the kind of answer given), so there should be a level 2 of depth, is that possible?

$data = array(
      'q-01' => (get('q-01')),
      'a-01'  => (get('a-01')),
      'q-02'   => (get('q-02')),
      'a-02'     => esc(get('a-02')), // input="text"
    );

YAML is fine. I was just thinking how it would be to have it in JSON (so to handle the indentation / nested level, but maybe unnecessary).

So far I was trying to get acquainted with $_POST and tried something rudimentary like this

$data = array();
    foreach($_POST as $key => $value) {
      $data[] = "$key => $value";
    }

and it was actually printing on a new file, but printing sometimes wrong values.

That’s exactly what I meant, loop through the $_POST array, but you should add the $key as key:

$data = array();
    foreach($_POST as $key => $value) {
      $data[$key] =  esc($value);
    };

However, if $value can be an array as well, you would have to check if it is an array within the foreach loop and then use a nested foreach loop to add those values to the $data array. Also, you don’t want the submit key in it nor probably a token, if you are using one.

1 Like

Great, it’s working now.

I went on and tried to replace the $rules and $messages array from this

$rules = array(
  'q_01'     => array('required'),
  //(...)
 );

$messages = array(
  'q_01' => 'Compila tutte le risposte?',
  //(...)
);

to this

$rules = array();
    foreach($_POST as $key => $value) {
      $rules[$key] = array('required');
    };

    $messages = array();
    foreach($_POST as $key => $value) {
      $messages[$key] = 'Compila tutte le risposte?';
    };

The page, when fully compiled, is “sent”, but what I get back is the error message set in the $messages array.

Instead, I would expect to receive this message when the form did not went through the sending process correctly and or when a field is not being answered? Although in the latter case, the browser is displaying an tooltip alert message saying the field should be filed out.

Well, from the little you gave me above, I can’t possibly make it out. Do you think you could be a bit more generous with your code :wink: ?

Sure! This is my full controller for the survey.

<?php

return function($site, $pages, $page) {

  $survey_item_number = $page->children()->count() + 1;
  //
  $alert = null;

  if(r::is('post') && get('survey_item')) {
    if(!empty(get('website'))) {
      // lets tell the bot that everything is ok
      go($page->url());
      exit;
    }

    $fill_timestamp = array(
      'title'    => 'Questionario #' . $survey_item_number,
      'data'     => date('Y-m-d, H:i:s'),
    );

    $fill_answers = array();
      foreach($_POST as $key => $value) {
        // tell not to pick honeypot values up
        if ($key != 'survey_item' && $key != 'website') {
            $fill_answers[$key] = esc($value);
        }
      };

    $fill = a::merge($fill_timestamp, $fill_answers);

   // $rules = array(
      // 'q_01'     => array('required'),
    // );
    $rules = array();
    foreach($_POST as $key => $value) {
      $rules[$key] = array('required');
    };

    $messages = array();
    foreach($_POST as $key => $value) {
      $messages[$key] = 'Compila tutte le risposte?';
    };
    // 'q_01' => 'Compila tutte le risposte?',

    // some of the data is invalid
    if($invalid = invalid($fill, $rules, $messages)) {
      $alert = $invalid;
    } else {

      // everything is ok, let's try to create a new survey_item
      try {

        // date_default_timezone_set('Europe/Rome');

        $new_survey_item = $page->children()->create(str::slug('questionario-' . $survey_item_number . '-' . date('Y-m-d')) , 'survey_item', $fill);

        $success = 'Il questionario è stato inviato!';
        $fill = array();

      } catch(Exception $e) {
        echo 'Il questionario non è stato inviato: ' . $e->getMessage();
      }
    }
  }

  return compact('alert', 'fill', 'success');
};

I don’t think this is the cause of the issue, but nevertheless it does not make sense to use the invalid helper on $fill. Instead, it should be used on $fill_answers.

Thanks for the tip, I replaced the above code in this way, using $fill_answers instead of $_POST

$fill_answers = array();
      foreach($_POST as $key => $value) {
        // tell not to pick honeypot values up
        if ($key != 'survey_item' && $key != 'website') {
            $fill_answers[$key] = esc($value);
        }
      };

$rules = array();
    foreach($fill_answers as $key => $value) {
      $rules[$key] = array('required');
    };

    $messages = array();
    foreach($fill_answers as $key => $value) {
      $messages[$key] = 'Compila tutte le risposte?';
    };

    // some of the data is invalid
    if($invalid = invalid($fill_answers, $rules, $messages)) {
      $alert = $invalid;
    } else { // (...)

It now works!

I now only need to understand how to print both questions and answers coming from the same page, when making a new survey_item.txt (which gathers the results of a completed, submitted survey form).

<input type="hidden" name="name-field" value="content-field" />

// name-field = name to use when saving this input text as a new field in a page.txt
//content-field = text to use in the new field we are creating