<commit_before><?php
/*
 * Helpers to output form tags with Bootstrap 5 classes.
 *
 * Reference:  https://getbootstrap.com/docs/5.0/forms/overview/
 *
 *
 * COMMON OPTIONS
 *
 *   All helpers pass the $options array to the Symfony tag helpers,
 *   so you can add any custom attributes, eg:
 *
 *     ['class' => 'max-w-[100px] text-sm', 'data-userid' => '1007']
 *
 *
 * INPUT OPTIONS
 *
 *   'helptext' => 'message'     To add a Bootstrap .form-text element after the input
 *   'label'                     Adds label  NOTE! input name = id
 *   'optional'                  Add an (Optional) text next to the label
 *
 *
 * COMMON HELPERS
 *
 *   _bs_button()                  MUST add Bootstrap css as option 'class' => 'btn btn-success ...'
 *   _bs_button_with_icon()         DONT add 'btn btn-success' ... MUST add 'icon' => 'fa-icon-id'
 *
 *
 * FORM HELPERS
 *
 *  _bs_formgroup([array $options], ...)
 *
 *    $options (optional) ... passed to Symfony tag helpers
 *
 *      'validate'        ... add "has-error" class to the form-group if
 *                            this input has a matching error in Symfony Request
 *
 *    Example:
 *      _bs_formgroup(['validate' => 'username'], ...)
 *
 *  _bs_input_checkbox($name, $options = array())
 *
 *      OPTIONAL  'label' => 'Label text'
 *      NOTE!     The input's `value` is ALWAYS "1"
 *
 *  _bs_input_text    ($name, $options = array())
 *
 *  _bs_input_textarea($name, $options = array())
 *
 *  _bs_input_email   ($name, $options = array())
 *
 *  _bs_input_password($name, $options = array())
 *
 *  _bs_submit_tag    ($label, $options = array())
 *
 *
 *
 * FORM LAYOUT
 *
 *   Inline: add class "form-control-i" to children of _bs_formgroup()
 *
 *
 * SEE
 *
 *   https://getbootstrap.com/docs/3.3/css/#forms
 *
 */

/**
 * Returns html for a Bootstrap button.
 *
 * Uses 'btn btn-default' unless btn-success, btn-warning, etc specified.
 *
 * Additional options as per Symfony's link_to() helper: 'absolute', 'query_string', 'anchor', etc.
 *
 * @param string $name
 * @param string $internal_uri
 */
function _bs_button($name, $internal_uri, array $options = [])
{
  // TODO

  return link_to($name, $internal_uri, $options);
}

/**
 * another helper to help refactoring later.
 *
 * Options:
 *   icon    fontawesome icon id (eg. fa-file-o)
 *
 * @param mixed $name
 * @param mixed $internal_uri
 */
function _bs_button_with_icon($name, $internal_uri, array $options = [])
{
  $iconId = _get_option($options, 'icon');
  assert($iconId !== null);

  _bs_class_merge($options, 'btn btn-success');

  $name = "<i class=\"far {$iconId}\"></i>{$name}";

  return link_to($name, $internal_uri, $options);
}

// Classnames are appended to $options['class'] if present.
function _bs_class_merge(array &$options, $classnames)
{
  if (isset($options['class']))
  {
    if (!is_array($options['class']))
    {
      $classnames = $classnames.' '.$options['class'];
    }
    else
    {
      throw new sfException('_bs_class_merge() options["class"] must be a string');
    }
  }

  $options['class'] = $classnames;
}

/**
 * Optional first argument : array $options.
 *
 * Example:
 *
 *   _bs_form_group(
 *     array('style' => 'color:red'),
 *     '<span>Hello</span>',
 *     _bs_input_text('Label', 'name_and_id')
 *   )
 */
function _bs_form_group()
{
  if (func_num_args() < 1)
  {
    throw new sfException('_bs_form_group() has no content.');
  }

  $args = func_get_args();
  $input_name = false;
  $hasErrorMsg = '';

  // pull the optional first argument : array $options
  $options = is_array($args[0]) ? array_shift($args) : [];

  $merge_class = 'form-group';

  // add Bootstrap 'has-error' class
  if (false !== ($input_name = $options['validate'] ?? false))
  {
    unset($options['validate']);
    $request = sfContext::getInstance()->getRequest();
    if ($request->hasError($input_name))
    {
      $merge_class .= ' has-error';
      $hasErrorMsg = '<div class="has-error-msg">^ '.$request->getError($input_name).'</div>';
    }
  }

  _bs_class_merge($options, $merge_class);

  $html = "\n<div "._tag_options($options).'>'
        .implode($args)
        .$hasErrorMsg
        ."\n</div>";

  return $html;
}

function _bs_input($type, $name, $options = [])
{
  $html = [];
<commit_msg>(_BootstrapHelper): update to Bootstrap 5 's `invalid-feedback` class<commit_after><?php
/*
 * Helpers to output form tags with Bootstrap 5 classes.
 *
 * Reference:  https://getbootstrap.com/docs/5.0/forms/overview/
 *
 *
 * COMMON OPTIONS
 *
 *   All helpers pass the $options array to the Symfony tag helpers,
 *   so you can add any custom attributes, eg:
 *
 *     ['class' => 'max-w-[100px] text-sm', 'data-userid' => '1007']
 *
 *
 * INPUT OPTIONS
 *
 *   'helptext' => 'message'     To add a Bootstrap .form-text element after the input
 *   'label'                     Adds label  NOTE! input name = id
 *   'optional'                  Add an (Optional) text next to the label
 *
 *
 * COMMON HELPERS
 *
 *   _bs_button()                  MUST add Bootstrap css as option 'class' => 'btn btn-success ...'
 *   _bs_button_with_icon()         DONT add 'btn btn-success' ... MUST add 'icon' => 'fa-icon-id'
 *
 *
 * FORM HELPERS
 *
 *  _bs_formgroup([array $options], ...)
 *
 *    $options (optional) ... passed to Symfony tag helpers
 *
 *      'validate'        ... add "has-error" class to the form-group if
 *                            this input has a matching error in Symfony Request
 *
 *    Example:
 *      _bs_formgroup(['validate' => 'username'], ...)
 *
 *  _bs_input_checkbox($name, $options = array())
 *
 *      OPTIONAL  'label' => 'Label text'
 *      NOTE!     The input's `value` is ALWAYS "1"
 *
 *  _bs_input_text    ($name, $options = array())
 *
 *  _bs_input_textarea($name, $options = array())
 *
 *  _bs_input_email   ($name, $options = array())
 *
 *  _bs_input_password($name, $options = array())
 *
 *  _bs_submit_tag    ($label, $options = array())
 *
 *
 *
 * FORM LAYOUT
 *
 *   Inline: add class "form-control-i" to children of _bs_formgroup()
 *
 *
 * SEE
 *
 *   https://getbootstrap.com/docs/3.3/css/#forms
 *
 */

/**
 * Returns html for a Bootstrap button.
 *
 * Uses 'btn btn-default' unless btn-success, btn-warning, etc specified.
 *
 * Additional options as per Symfony's link_to() helper: 'absolute', 'query_string', 'anchor', etc.
 *
 * @param string $name
 * @param string $internal_uri
 */
function _bs_button($name, $internal_uri, array $options = [])
{
  // TODO

  return link_to($name, $internal_uri, $options);
}

/**
 * another helper to help refactoring later.
 *
 * Options:
 *   icon    fontawesome icon id (eg. fa-file-o)
 *
 * @param mixed $name
 * @param mixed $internal_uri
 */
function _bs_button_with_icon($name, $internal_uri, array $options = [])
{
  $iconId = _get_option($options, 'icon');
  assert($iconId !== null);

  _bs_class_merge($options, 'btn btn-success');

  $name = "<i class=\"far {$iconId}\"></i>{$name}";

  return link_to($name, $internal_uri, $options);
}

// Classnames are appended to $options['class'] if present.
function _bs_class_merge(array &$options, $classnames)
{
  if (isset($options['class']))
  {
    if (!is_array($options['class']))
    {
      $classnames = $classnames.' '.$options['class'];
    }
    else
    {
      throw new sfException('_bs_class_merge() options["class"] must be a string');
    }
  }

  $options['class'] = $classnames;
}

/**
 * Optional first argument : array $options.
 *
 * Example:
 *
 *   _bs_form_group(
 *     array('style' => 'color:red'),
 *     '<span>Hello</span>',
 *     _bs_input_text('Label', 'name_and_id')
 *   )
 */
function _bs_form_group()
{
  if (func_num_args() < 1)
  {
    throw new sfException('_bs_form_group() has no content.');
  }

  $args = func_get_args();
  $input_name = false;
  $hasErrorMsg = '';

  // pull the optional first argument : array $options
  $options = is_array($args[0]) ? array_shift($args) : [];

  $merge_class = 'form-group';

  // add Bootstrap 'has-error' class
  if (false !== ($input_name = $options['validate'] ?? false))
  {
    unset($options['validate']);
    $request = sfContext::getInstance()->getRequest();
    if ($request->hasError($input_name))
    {
      $hasErrorMsg = '<div class="invalid-feedback">^ '.$request->getError($input_name).'</div>';
    }
  }

  _bs_class_merge($options, $merge_class);

  $html = "\n<div "._tag_options($options).'>'
        .implode($args)
        .$hasErrorMsg
        ."\n</div>";

  return $html;
}

function _bs_input($type, $name, $options = [])
{
  $html = [];

{'fraction_non_alphanumeric': 0.1704929495396807, 'fraction_numerical': 0.0036126325603076563, 'mean_word_length': 2.973148148148148, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 41, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4546840', 'n_tokens_mistral': 2975, 'n_tokens_neox': 2894, 'n_words': 701}