You are here

function fasttoggle_do_toggle_option in Fasttoggle 7

Handle a request to toggle an option.

Menu callback. Toggle options for an object if the action is confirmed via POST. Otherwise, display a confirmation form.

Parameters

string $object_type: The type of object being handled.

object $object: An instance of the object to be modified.

string $group: The group to which the setting being modified belongs.

string $option: The option being toggled.

string $view: (Optional) The view of the object to be rendered.

Return value

mixed If the access check fails, returns MENU_NOT_FOUND (=> 404). If submission is non-ajax and not confirmed, a confirmation form is displayed. If the link is ajax or the confirmation is provided via the form, the value is toggled to the next in the sequence and the function either returns the ajax for updating the link (and potentially replacing the body of the rendered object with updated content) or executes drupal_goto() in the case of the form submission.

1 string reference to 'fasttoggle_do_toggle_option'
fasttoggle_menu in ./fasttoggle.module
Implements hook_menu().

File

./fasttoggle.module, line 572
Enables fast toggling of binary or not so binary settings.

Code

function fasttoggle_do_toggle_option($object_type, $object, $group, $option, $view = NULL) {
  global $user;
  $options = fasttoggle_get_allowed_links($object_type, $object);
  $label_style = variable_get('fasttoggle_label_style', FASTTOGGLE_LABEL_STATUS);
  $id_field = $options['id_field'];
  $group_data = $options['fields'][$group];

  // Check if the action is valid. This is essential to ensure the user has
  // access to the action.
  if (!isset($group_data['instances'][$option]) || !isset($_GET['token']) || !drupal_valid_token($_GET['token'], $group . '_' . $option . '_' . $object->{$id_field}, TRUE)) {
    if (isset($_POST['js']) && $_POST['js']) {
      $ajax_commands = array(
        ajax_command_alert(t('Invalid ajax request')),
      );
      echo ajax_render($ajax_commands);
      exit;
    }
    else {
      return MENU_NOT_FOUND;
    }
  }

  // The action is confirmed: either via form submit or via AJAX/POST.
  if (isset($_POST['confirm']) && $_POST['confirm'] || isset($_POST['js']) && $_POST['js']) {
    $selectorClass = 'fasttoggle-status-' . $object_type . '-' . $object->{$id_field} . '-' . $group . '-' . $option;
    $label_data = $group_data['instances'][$option];
    if (isset($group_data['new_value_fn'])) {
      $value = $group_data['new_value_fn']($object, $label_data['value_key']);
    }
    else {
      $current_value = fasttoggle_get_object_value($options, $group, $option, $object);
      $labels = $label_data['labels'][$label_style];

      // Find the current value. We need to cast as strings to ensure
      // we stop at the right value.
      while ((string) key($labels) !== (string) $current_value) {
        next($labels);
      }
      do {

        // Get the next value and wrap back to the start if necessary.
        if (next($labels) === FALSE) {
          reset($labels);
        }

        // Don't stop on the 'unset' value if the field is required.
        if (key($labels) === '[unset]' && !$label_data['optional']) {
          if (next($labels) === FALSE) {
            reset($labels);
          }
        }

        // Go again if this value isn't allowed.
      } while (isset($label_data['allowed_values']) && !in_array((string) key($labels), $label_data['allowed_values']));

      // And get the new value we'll actually use.
      $value = key($labels);
    }

    // Save the new value.
    if (!empty($group_data['save_fn'])) {
      $group_data['save_fn']($options, $group, $option, $value, $object);
    }
    else {
      $options['save_fn']($options, $group, $option, $value, $object);
    }
    $label = $labels[$value];
    $object_label = entity_label($object_type, $object);
    $newClass = 'fasttoggle-status-' . $object_type . '-' . $group . '-' . $option . '-' . $value;
    watchdog('fasttoggle', '@type %title @option toggled to @value.', [
      '@type' => drupal_ucfirst($object_type),
      '%title' => $object_label,
      '@option' => $option == $group ? $option : $group . ' ' . $option,
      '@value' => $label,
    ]);

    // Let other modules respond.
    module_invoke_all('fasttoggle_toggle', $object_type, $object, $group, $option);

    // Output the new status for the updated link text on AJAX changes.
    if (isset($_POST['js']) && $_POST['js']) {
      drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8');

      // l() (invoked by fasttoggle()) adds the active class to our new link.
      // But the original link doesn't get it added, so clicking the link
      // results in an extra class being applied. Strip the active class here
      // (assuming it's added to the end of the classes, so we get apples for
      // apples.
      $new_link = fasttoggle($options, $group, $option, $object, FASTTOGGLE_FORMAT_HTML, $view);
      $new_link = preg_replace('/class="(.*) active"/', 'class="$1"', $new_link);
      $ajax_commands = array(
        ajax_command_replace('.' . $selectorClass, $new_link),
        ajax_command_invoke('body', 'trigger', [
          'FasttoggleTrigger',
          $newClass,
        ]),
      );
      $params = array(
        'group' => $group,
        'option' => $option,
        'view' => $view,
      );
      drupal_alter('fasttoggle_ajax', $ajax_commands, $object_type, $object, $params);
      echo ajax_render($ajax_commands);
      exit;
    }
    else {
      drupal_goto();
    }
  }
  else {

    // The action is not confirmed. The user came here through a regular link;
    // no AJAX was involved. That means, we need a confirmation form so that
    // we get a POST form.
    return drupal_get_form('fasttoggle_do_option_confirm', $object_type, $object->{$options['title_field']}, $options['fields'][$group]['instances'][$option]['labels'][$label_style][intval(!$object->{$option})]);
  }
}