You are here

function content_lock_form_alter in Content locking (anti-concurrent editing) 7.2

Same name and namespace in other branches
  1. 8.2 content_lock.module \content_lock_form_alter()
  2. 8 content_lock.module \content_lock_form_alter()
  3. 6.2 content_lock.module \content_lock_form_alter()
  4. 6 content_lock.module \content_lock_form_alter()
  5. 7.3 content_lock.module \content_lock_form_alter()
  6. 7 content_lock.module \content_lock_form_alter()

Implements hook_form_alter().

File

./content_lock.module, line 272
Allows users to lock documents for modification.

Code

function content_lock_form_alter(&$form, &$form_state, $form_id) {
  global $user;
  $node = empty($form['#node']) ? NULL : $form['#node'];
  $nid = empty($form['nid']['#value']) ? NULL : $form['nid']['#value'];
  $destination = 'node/' . $nid;

  // Ensure user acquire a lock when reverting a node to an older revision.
  if (!empty($form['#node_revision'])) {
    $node = $form['#node_revision'];
    $nid = $node->nid;
    $destination = 'node/' . $nid . '/revisions';
  }

  // **************** Restore the node format ******************************
  // This _content_lock_is_lockable_node() needs to know the original
  // node format. We either dig up a stashed content_lock_old_format or
  // initialize it here.
  // Only touch node edit forms and then only if the form is `normal'
  // and has a body with a format (#1183678).
  if (is_object($node) && is_numeric($nid) && ($form_id == $node->type . '_node_form' || $form_id == 'node_revision_revert_confirm') && isset($node->body) && is_array($node->body) && !empty($node->body[$node->language][0]['format'])) {
    $old_format = $node->body[$node->language][0]['format'];
    if (!empty($node->content_lock_old_format)) {
      $old_format = $node->content_lock_old_format;
    }
    if (!empty($form_state['values']['content_lock_old_format'])) {
      $old_format = $form_state['values']['content_lock_old_format'];
    }

    // Needs to be manually set before first form submission.
    // We set this in the $node-> namespace because content_lock_nodeapi()
    // doesn't see $form_state['values'].
    $node->content_lock_old_format = $old_format;
    $form['content_lock_old_format'] = array(
      '#type' => 'hidden',
      '#value' => $node->content_lock_old_format,
    );
  }

  // General preconditions for locking.
  // Veto-API. Let other modules veto the locking - so force skipping out
  // of any conditions they want.
  // We will use || logic, so if any module denies locking then we
  // deny locking.
  // Be sure to notice that content_lock also implements this api
  // for his own vetos.
  $skip_lock = FALSE;
  $result = module_invoke_all('content_lock_skip_locking', $node, $form_id, $form, $form_state);
  foreach ($result as $bool) {
    if (is_bool($bool)) {
      $skip_lock = $skip_lock || $bool;
    }
  }
  if ($skip_lock == FALSE) {

    // Adding cancel button, if configured.
    if (variable_get('content_lock_admin_cancelbutton', TRUE)) {
      _content_lock_add_cancelbutton($form, $form_state, $form_id);
    }

    // If we are handling a preview, skip locking.
    if (!empty($form_state['rebuild']) && $form_state['rebuild'] == TRUE) {

      // Placeholder.
    }
    else {
      if ($form_state['submitted'] === FALSE) {

        // Refuse to lock if a token is not present. This prevents a CSRF attack
        // if a user is tricked into visiting pages that cause nodes to be
        // locked.
        // A CSRF token may be missing in these cases:
        // - A node add/edit form is displayed on a path that is not protected
        //   with a CSRF token. Please add the path to the list of protected
        //   paths by implementing hook_content_lock_path_protected().
        // - The CSRF token has not been added to the URL as a query parameter,
        //   for example because the user entered node/1/edit directly in the
        //   address bar of the browser. To avoid CSRF attacks we do not lock
        //   the node automatically, but still give the user the possibility to
        //   lock the node manually using an AJAX call with a proper CSRF token.
        $menu_item = menu_get_item();
        if (empty($_GET['content_lock_token']) || !drupal_valid_token($_GET['content_lock_token'], $menu_item['href'])) {
          drupal_set_message(t('The page you are editing could not be locked automatically. Please !link to make sure other people cannot accidentally overwrite your changes.', array(
            '!link' => l(t('lock the page'), 'nojs/content_lock/' . $nid . '/lock/' . drupal_get_token($nid), array(
              'attributes' => array(
                'class' => array(
                  'use-ajax',
                ),
              ),
            )),
          )), 'error');
          if (!content_lock_is_path_protected($menu_item['path'])) {
            watchdog('content_lock', 'Attempt to load the node_form form at menu path %path which is not protected from CSRF. Developers who want to create custom node editing pages and protect them with hook_content_lock_path_protected() or use protection_menu_token module to protect this path.', array(
              '%path' => $menu_item['path'],
            ), WATCHDOG_WARNING);
          }
        }
        else {

          // Finally set the lock if everything passed.
          if (content_lock_node($nid, $user->uid) == FALSE) {

            // Could not lock node, it's locked by someone else.
            drupal_goto($destination);
          }
          elseif (variable_get('content_lock_unload_js', TRUE)) {
            $form['#after_build'][] = '_content_lock_add_unload_js';
          }
        }
      }
    }
  }
}