You are here

function wsclient_service_form in Web service client 7

Provides a form to add, edit and clone web service descriptions.

File

wsclient_ui/wsclient_ui.inc, line 88
WSClient UI - implements service description management and configuration screens.

Code

function wsclient_service_form($form, &$form_state, $service, $op = 'edit') {
  if ($op == 'clone') {
    $service->label .= ' (cloned)';
    $service->name .= '_clone';
  }
  $type_info = wsclient_get_types();
  if (empty($type_info)) {
    drupal_set_message(t('No service types were found, please enable a module that provides a service type.'), 'warning');
  }
  $types = array();
  foreach ($type_info as $type => $info) {
    $types[$type] = $info['label'];
  }
  $form['label'] = array(
    '#type' => 'textfield',
    '#title' => t('Label'),
    '#default_value' => $service->label,
    '#required' => TRUE,
    '#description' => t('The human-readable name.'),
    '#weight' => 10,
  );
  $form['name'] = array(
    '#type' => 'machine_name',
    '#default_value' => isset($service->name) ? $service->name : '',
    '#maxlength' => 32,
    '#machine_name' => array(
      'exists' => 'wsclient_service_load',
      'source' => array(
        'label',
      ),
    ),
    '#required' => TRUE,
    '#description' => t('The machine-readable name of this service is used internally to identify the service. This name must contain only lowercase letters, numbers, and underscores and must be unique.'),
    '#element_validate' => array(
      'form_validate_machine_name',
      'entity_ui_validate_machine_name',
    ),
    '#weight' => 20,
  );
  $form['url'] = array(
    '#type' => 'textfield',
    '#title' => t('URL'),
    '#default_value' => $service->url,
    '#required' => TRUE,
    '#description' => t('The URL of the web service.'),
    '#element_validate' => array(
      'wsclient_ui_element_url_validate',
    ),
    '#weight' => 30,
  );
  $form['type'] = array(
    '#type' => 'select',
    '#title' => t('Type'),
    '#default_value' => $service->type,
    '#options' => $types,
    '#required' => TRUE,
    '#description' => t('The type of the web service.'),
    '#weight' => 40,
  );
  if ($op == 'edit') {

    // Operations of the web service in a table
    $rows = array();
    $operations = wsclient_ui_label_sort($service->operations);
    foreach ($operations as $name => $operation) {
      $row = array();
      $row[] = array(
        'data' => array(
          '#theme' => 'entity_ui_overview_item',
          '#label' => $operation['label'],
          '#name' => $name,
          '#url' => array(
            'path' => WSCLIENT_UI_PATH . '/manage/' . $service->name . '/operation/' . $name,
            'options' => array(),
          ),
        ),
      );
      $row[] = l(t('Edit'), WSCLIENT_UI_PATH . '/manage/' . $service->name . '/operation/' . $name);
      $row[] = l(t('Delete'), WSCLIENT_UI_PATH . '/manage/' . $service->name . '/operation/' . $name . '/delete');
      $rows[] = $row;
    }
    $header = array(
      t('Label'),
      array(
        'data' => t('Operations'),
        'colspan' => 3,
      ),
    );
    $add_operation = array(
      '#theme' => 'links__wsclient',
      '#links' => array(
        'add_op' => array(
          'title' => t('Add operation'),
          'href' => WSCLIENT_UI_PATH . '/manage/' . $service->name . '/add/operation',
        ),
      ),
    );
    $add_operation['#attributes']['class'][] = 'rules-operations-add';
    $add_operation['#attributes']['class'][] = 'action-links';
    $row = array();
    $row[] = array(
      'data' => $add_operation,
      'colspan' => 3,
    );
    $rows[] = array(
      'data' => $row,
      'class' => array(
        'rules-elements-add',
      ),
    );

    // @todo description help text for operations, data types
    $form['operations'] = array(
      '#access' => TRUE,
      '#tree' => TRUE,
      '#theme' => 'table',
      '#empty' => t('None'),
      '#caption' => t('Operations'),
      '#rows' => $rows,
      '#header' => $header,
      '#weight' => 65,
    );

    // Add some table styling from Rules.
    $form['operations']['#attributes']['class'][] = 'rules-elements-table';
    $form['operations']['#attached']['css'][] = drupal_get_path('module', 'rules') . '/ui/rules.ui.css';

    // Data types of the web service in a table
    $rows = array();
    $datatypes = wsclient_ui_label_sort($service->datatypes);
    foreach ($datatypes as $name => $datatype) {
      $row = array();
      $row[] = array(
        'data' => array(
          '#theme' => 'entity_ui_overview_item',
          '#label' => $datatype['label'],
          '#name' => $name,
          '#url' => array(
            'path' => WSCLIENT_UI_PATH . '/manage/' . $service->name . '/type/' . $name,
            'options' => array(),
          ),
        ),
      );
      $row[] = l(t('Edit'), WSCLIENT_UI_PATH . '/manage/' . $service->name . '/type/' . $name);
      $row[] = l(t('Delete'), WSCLIENT_UI_PATH . '/manage/' . $service->name . '/type/' . $name . '/delete');
      $rows[] = $row;
    }
    $header = array(
      t('Label'),
      array(
        'data' => t('Operations'),
        'colspan' => 3,
      ),
    );
    $add_type = array(
      '#theme' => 'links__wsclient',
      '#links' => array(
        'add_op' => array(
          'title' => t('Add data type'),
          'href' => WSCLIENT_UI_PATH . '/manage/' . $service->name . '/add/type',
        ),
      ),
    );
    $add_type['#attributes']['class'][] = 'rules-operations-add';
    $add_type['#attributes']['class'][] = 'action-links';
    $row = array();
    $row[] = array(
      'data' => $add_type,
      'colspan' => 3,
    );
    $rows[] = array(
      'data' => $row,
      'class' => array(
        'rules-elements-add',
      ),
    );
    $form['datatypes'] = array(
      '#access' => TRUE,
      '#tree' => TRUE,
      '#theme' => 'table',
      '#empty' => t('None'),
      '#caption' => t('Data types'),
      '#rows' => $rows,
      '#header' => $header,
      '#weight' => 70,
    );
    $settings = $service->settings;

    // Simply naming the settings here to reflect the internal entity
    // structure is enough to mean we don't need to worry about serializing
    // it ourself.
    $form['settings'] = array(
      '#tree' => TRUE,
      '#weight' => 45,
    );

    // Input for Authentication options.
    $form['settings']['authentication'] = array(
      '#type' => 'fieldset',
      '#title' => t('Authentication'),
      '#weight' => 60,
    );

    // @todo Remove authentication type once multiple authentications is implemented
    // @see WSClientRESTEndpoint::client() => Allow multiple authentications by implementing and using HttpClientCompositeAuth.
    $form['settings']['authentication']['type'] = array(
      '#type' => 'select',
      '#options' => array(
        'none' => t('None'),
        'basic' => t('Basic (htauth)'),
        'wss' => t('WSS (Web Service Security)'),
        'oauth2' => t('OAuth 2.0'),
      ),
      '#default_value' => isset($settings['authentication']['type']) ? $settings['authentication']['type'] : 'none',
    );
    $xpath = ':input[name="settings[authentication][type]"]';
    $basic_states = array(
      '#states' => array(
        'visible' => array(
          $xpath => array(
            'value' => 'basic',
          ),
        ),
      ),
    );
    $basic_settings = isset($settings['authentication']['basic']) ? $settings['authentication']['basic'] : array();
    $form['settings']['authentication']['basic'] = array(
      '#type' => 'fieldset',
      '#title' => t('Basic HTAuth'),
      '#description' => t('HTAuth requires http_client.module > 7.x-2.4'),
    ) + $basic_states;
    $form['settings']['authentication']['basic']['username'] = array(
      '#type' => 'textfield',
      '#title' => t('Username'),
      '#default_value' => isset($basic_settings['username']) ? $basic_settings['username'] : '',
    );
    $form['settings']['authentication']['basic']['password'] = array(
      '#type' => 'textfield',
      '#title' => t('Password'),
      '#default_value' => isset($basic_settings['password']) ? $basic_settings['password'] : '',
    );
    $wss_settings = isset($settings['authentication']['wss']) ? $settings['authentication']['wss'] : array();
    $form['settings']['authentication']['wss'] = array(
      '#type' => 'fieldset',
      '#title' => t('WSS (Web Services Security)'),
      '#states' => array(
        'visible' => array(
          $xpath => array(
            'value' => 'wss',
          ),
        ),
      ),
    );
    $form['settings']['authentication']['wss']['username'] = array(
      '#type' => 'textfield',
      '#title' => 'Username',
      '#default_value' => isset($wss_settings['username']) ? $wss_settings['username'] : '',
    );
    $form['settings']['authentication']['wss']['password'] = array(
      '#type' => 'textfield',
      '#title' => t('Password'),
      '#default_value' => isset($wss_settings['password']) ? $wss_settings['password'] : '',
    );
    $oauth2_states = array(
      '#states' => array(
        'visible' => array(
          $xpath => array(
            'value' => 'oauth2',
          ),
        ),
      ),
    );
    $xpath_auth_flow = ':input[name="settings[authentication][oauth2][auth_flow]"]';
    $oauth2_states_server_side = array(
      '#states' => array(
        'visible' => array(
          $xpath => array(
            'value' => 'oauth2',
          ),
          $xpath_auth_flow => array(
            'value' => 'server-side',
          ),
        ),
      ),
    );
    $oauth2_states_user_password = array(
      '#states' => array(
        'visible' => array(
          $xpath => array(
            'value' => 'oauth2',
          ),
          $xpath_auth_flow => array(
            'value' => 'user-password',
          ),
        ),
      ),
    );
    $form['settings']['authentication']['oauth2'] = array(
      '#type' => 'fieldset',
      '#title' => t('OAuth 2.0'),
    ) + $oauth2_states;
    $oauth_settings = isset($settings['authentication']['oauth2']) ? $settings['authentication']['oauth2'] : array();
    $form['settings']['authentication']['oauth2']['auth_flow'] = array(
      '#type' => 'select',
      '#title' => t('Auth flow'),
      '#options' => array(
        'client-credentials' => t('Client credentials'),
        'server-side' => t('Server side'),
        'user-password' => t('User password'),
      ),
      '#default_value' => isset($oauth_settings['auth_flow']) ? $oauth_settings['auth_flow'] : '',
    );
    $form['settings']['authentication']['oauth2']['token_endpoint'] = array(
      '#type' => 'textfield',
      '#title' => t('Token endpoint'),
      '#default_value' => isset($oauth_settings['token_endpoint']) ? $oauth_settings['token_endpoint'] : '',
      '#description' => t('E.g. https://server.org/oauth2/token.'),
    );
    $form['settings']['authentication']['oauth2']['client_id'] = array(
      '#type' => 'textfield',
      '#title' => t('Client ID'),
      '#default_value' => isset($oauth_settings['client_id']) ? $oauth_settings['client_id'] : '',
      '#description' => t('The client ID as registered on the OAuth 2.0 server.'),
    );
    $form['settings']['authentication']['oauth2']['client_secret'] = array(
      '#type' => 'textfield',
      '#title' => t('Client secret'),
      '#default_value' => isset($oauth_settings['client_secret']) ? $oauth_settings['client_secret'] : '',
      '#description' => t('The client secret as registered on the OAuth 2.0 server.'),
    );
    $form['settings']['authentication']['oauth2']['scope'] = array(
      '#type' => 'textfield',
      '#title' => t('Scope'),
      '#default_value' => isset($oauth_settings['scope']) ? $oauth_settings['scope'] : '',
      '#description' => t('Space separated list of scopes.'),
    );
    $form['settings']['authentication']['oauth2']['query_auth'] = array(
      '#type' => 'select',
      '#title' => t('Query auth'),
      '#options' => array(
        0 => t('No'),
        1 => t('Yes'),
      ),
      '#default_value' => isset($oauth_settings['query_auth']) ? $oauth_settings['query_auth'] : 0,
      '#description' => t("Yes will make the access token be set on the query, otherwise it'll be set on the headers."),
    );
    $form['settings']['authentication']['oauth2']['redirect_uri'] = array(
      '#type' => 'textfield',
      '#title' => t('Redirect URI'),
      '#default_value' => isset($oauth_settings['redirect_uri']) ? $oauth_settings['redirect_uri'] : '',
      '#description' => t('E.g. https://client.org/oauth2/authorized. Only needed for server-side auth flow.'),
    ) + $oauth2_states_server_side;
    $form['settings']['authentication']['oauth2']['authorization_endpoint'] = array(
      '#type' => 'textfield',
      '#title' => t('Authorization endpoint'),
      '#default_value' => isset($oauth_settings['authorization_endpoint']) ? $oauth_settings['authorization_endpoint'] : '',
      '#description' => t('E.g. https://server.org/oauth2/authorize. Only needed for server-side auth flow.'),
    ) + $oauth2_states_server_side;
    $form['settings']['authentication']['oauth2']['username'] = array(
      '#type' => 'textfield',
      '#title' => t('Username'),
      '#default_value' => isset($oauth_settings['username']) ? $oauth_settings['username'] : '',
      '#description' => t('Username of resource owner on the OAuth 2.0 server. Only needed for user-password auth flow.'),
    ) + $oauth2_states_user_password;
    $form['settings']['authentication']['oauth2']['password'] = array(
      '#type' => 'textfield',
      '#title' => t('Password'),
      '#default_value' => isset($oauth_settings['password']) ? $oauth_settings['password'] : '',
      '#description' => t('Password of resource owner on the OAuth 2.0 server. Only needed for user-password auth flow.'),
    ) + $oauth2_states_user_password;

    // Input for global service parameters.
    $form['global_parameters'] = array(
      '#tree' => TRUE,
      '#element_validate' => array(
        'wsclient_ui_validate_global_parameters',
      ),
      '#theme' => 'wsclient_ui_global_parameter_form',
      '#title' => t('Input for global service parameters'),
      '#description' => t('Specify the global parameters for the service. Global parameters will be used if the value of an operation parameter with the same name is empty.'),
      '#weight' => 70,
    );

    // Input for global SOAP service header parameters.
    $form['global_header_parameters'] = array(
      '#tree' => TRUE,
      '#theme' => 'wsclient_ui_global_header_parameter_form',
      '#title' => t('Input for global SOAP header parameters'),
      '#description' => t('Specify the global header parameters for the SOAP header. Global header parameters will be added to the SOAP header for all SOAP service operations.'),
      '#weight' => 71,
    );
    $weight = 0;
    foreach ($service->global_parameters as $name => $info) {
      $form['global_parameters']['items'][$name] = _wsclient_ui_global_parameter_row($service, $datatypes, $name, $info);
      $form['global_parameters']['items'][$name]['weight']['#default_value'] = $weight++;
    }

    // Always add three empty lines for global parameters input.
    $form_state['more'] = isset($form_state['more']) ? $form_state['more'] : 3;
    for ($i = 0; $i < $form_state['more']; $i++) {
      if (!isset($form['global_parameters']['items'][$i])) {
        $form['global_parameters']['items'][$i] = _wsclient_ui_global_parameter_row($service, $datatypes);
      }
    }
    $form['global_parameters']['more'] = array(
      '#type' => 'submit',
      '#value' => t('Add more'),
      '#limit_validation_errors' => array(
        array(
          'properties',
        ),
      ),
      '#submit' => array(
        'wsclient_ui_more_submit',
      ),
    );
    $types = array();
    foreach ($service->datatypes as $type_name => $item) {
      $types[$type_name] = $item['label'];
    }

    // Add rows to global header parameter rows.
    foreach ($service->global_header_parameters as $name => $info) {
      $form['global_header_parameters']['items'][$name] = _wsclient_ui_global_header_parameter_row($service, $types, $name, $info);
      $form['global_header_parameters']['items'][$name]['weight']['#default_value'] = $weight++;
    }

    // Always add three empty lines for global header parameters input.
    for ($i = 0; $i < $form_state['more']; $i++) {
      if (!isset($form['global_header_parameters']['items'][$i])) {
        $form['global_header_parameters']['items'][$i] = _wsclient_ui_global_header_parameter_row($service, $types);
      }
    }
    $form['global_header_parameters']['more'] = array(
      '#type' => 'submit',
      '#value' => t('Add more'),
      '#limit_validation_errors' => array(
        array(
          'properties',
        ),
      ),
      '#submit' => array(
        'wsclient_ui_more_submit',
      ),
    );

    // Add some table styling from Rules.
    $form['datatypes']['#attributes']['class'][] = 'rules-elements-table';
    $form['datatypes']['#attached']['css'][] = drupal_get_path('module', 'rules') . '/ui/rules.ui.css';
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#weight' => 80,
  );
  $form_state['service'] = $service;

  // Allow the endpoint to make alterations to the form.
  $form_state['form'] = 'main';
  if ($service->type) {
    $service
      ->endpoint()
      ->formAlter($form, $form_state);
  }
  $form['#submit'][] = 'wsclient_service_form_submit';
  return $form;
}