You are here

class WebformAjax in Webform CiviCRM Integration 8.5

Class WebformAjax

Hierarchy

Expanded class hierarchy of WebformAjax

1 string reference to 'WebformAjax'
webform_civicrm.services.yml in ./webform_civicrm.services.yml
webform_civicrm.services.yml
1 service uses WebformAjax
webform_civicrm.webform_ajax in ./webform_civicrm.services.yml
Drupal\webform_civicrm\WebformAjax

File

src/WebformAjax.php, line 19
Front-end form ajax handler.

Namespace

Drupal\webform_civicrm
View source
class WebformAjax extends WebformCivicrmBase implements WebformAjaxInterface {
  private $requestStack;
  function __construct(RequestStack $requestStack) {
    $this->requestStack = $requestStack;
  }

  /**
   * Replacement of the reading of $_GET
   * @param $name
   *
   * @return mixed
   */
  private function getParameter($name) {
    return $this->requestStack
      ->getCurrentRequest()->query
      ->get($name);
  }

  /**
   * Load one or more contacts via ajax
   * @param $webformId
   * @param $fid
   */
  function contactAjax($webformId, $fid) {
    $contactComponent = \Drupal::service('webform_civicrm.contact_component');
    if (empty($this
      ->getParameter('str')) && (empty($this
      ->getParameter('load')) || empty($this
      ->getParameter('cid')))) {
      throw new AccessDeniedHttpException('Invalid parameters.');
    }
    $webform = Webform::load($webformId);
    if (!$webform instanceof \Drupal\webform\WebformInterface) {
      throw new AccessDeniedHttpException('Invalid form.');
    }
    $this->node = $webform;
    $this->settings = $webform
      ->getHandler('webform_civicrm')
      ->getConfiguration()['settings'];
    $this->data = $this->settings['data'];
    $element = $webform
      ->getElement($fid);
    if (!$this
      ->autocompleteAccess($webform, $fid)) {
      throw new AccessDeniedHttpException('Access not allowed');
    }
    $filters = $contactComponent
      ->wf_crm_search_filters($webform, $element);

    // Populate other contact ids for related data
    $this->ent += [
      'contact' => [],
    ];
    $query_params = $this->requestStack
      ->getCurrentRequest()->query
      ->all();
    foreach ($query_params as $k => $v) {
      if (substr($k, 0, 3) == 'cid' && $v && is_numeric($v)) {
        $this->ent['contact'][substr($k, 3)]['id'] = (int) $v;
      }
    }

    // Bypass filters when choosing contact on component edit form
    // TODO do something about the undefined function wf_crm_admin_access
    if (!empty($this
      ->getParameter('admin')) && wf_crm_admin_access($this->node)) {
      $filters = [
        'check_permissions' => 1,
        'is_deleted' => 0,
        'contact_type' => $filters['contact_type'],
      ];
      $component['extra']['allow_create'] = 0;
    }

    // Autocomplete contact names
    if (!empty($this
      ->getParameter('str'))) {
      if ($str = trim($this
        ->getParameter('str'))) {
        return $contactComponent
          ->wf_crm_contact_search($webform, $element, $filters, $this->ent['contact'], $str);
      }
      exit;
    }

    // Load contact by id
    $data = [];
    if ($name = $contactComponent
      ->wf_crm_contact_access($element, $filters, $this
      ->getParameter('cid'))) {
      if ($this
        ->getParameter('load') == 'name') {
        if ($this
          ->getParameter('cid')[0] === '-') {

          // HTML hack to get prompt to show up different than search results
          $data = '<em><i>' . Xss::filter($element['#none_prompt']) . '</i></em>';
        }
        else {
          $data = $name;
        }
      }

      // Fetch entire contact to populate form via ajax
      if ($this
        ->getParameter('load') == 'full') {
        $sp = \CRM_Core_DAO::VALUE_SEPARATOR;
        $utils = \Drupal::service('webform_civicrm.utils');
        $this->enabled = $utils
          ->wf_crm_enabled_fields($webform);
        list(, $c, ) = explode('_', $element['#form_key'], 3);
        $this->ent['contact'][$c]['id'] = (int) $_GET['cid'];

        // Redact fields if they are to be hidden unconditionally, otherwise they are needed on the client side
        $to_hide = [];
        if (!empty($element['#hide_fields']) && (wf_crm_aval($element, '#hide_method', 'hide') == 'hide' && !wf_crm_aval($element, '#no_hide_blank'))) {
          $to_hide = $element['#hide_fields'];
        }
        $contact = $this
          ->loadContact($c, $to_hide);
        $states = $countries = [];

        // Format as json array
        foreach ($this->enabled as $fid => $f) {
          list(, $i, $ent, $n, $table, $field) = explode('_', $fid, 6);
          if ($i == $c && $ent == 'contact' && isset($contact[$table][$n][$field])) {
            $type = $table == 'contact' && strpos($field, 'name') ? 'name' : $table;

            // Exclude blank and hidden fields
            if ($contact[$table][$n][$field] !== '' && $contact[$table][$n][$field] !== [] && !in_array($type, $to_hide)) {
              $dataType = wf_crm_aval($utils
                ->wf_crm_get_field("{$table}_{$field}"), 'data_type');
              $val = [
                'val' => $contact[$table][$n][$field],
              ];

              // Retrieve file info
              if ($dataType === 'File') {
                $val = $this
                  ->getFileInfo($field, $val['val'], $ent, $n);
              }
              elseif (is_string($val['val']) && strpos($val['val'], $sp) !== FALSE) {
                $val['val'] = $utils
                  ->wf_crm_explode_multivalue_str($val['val']);
              }
              $val['fid'] = $fid;
              if ($dataType) {
                $val['data_type'] = $dataType;
              }
              if ($field == 'state_province_id') {
                $states[] = $val;
              }
              elseif ($field == 'country_id') {
                $countries[] = $val;
              }
              else {
                $data[] = $val;
              }
            }
          }
          elseif ($i == 1 && strpos($field, 'billing_address_') !== false && isset($contact['contact'][$n]['contact_id'])) {
            $billingAddress = $this
              ->loadBillingAddress($contact['contact'][$n]['contact_id']);
            if (isset($billingAddress[$field])) {
              $data[] = [
                'val' => $billingAddress[$field],
                'fid' => $fid,
              ];
            }
          }
          elseif ($i > $c && $field == 'existing') {
            $related_component = $this
              ->getComponent($fid);
            if (isset($related_component['#default']) && $related_component['#default'] == 'relationship') {
              $old_related_cid = wf_crm_aval($this->ent, "contact:{$i}:id");

              // Don't be fooled by old data
              $related_component['extra']['allow_url_autofill'] = FALSE;
              unset($this->ent['contact'][$i]);
              $this
                ->findContact($related_component);
              $related_cid = wf_crm_aval($this->ent, "contact:{$i}:id");
              if ($related_cid && $related_cid != $old_related_cid) {
                $data[] = [
                  'fid' => $fid,
                  'val' => $related_cid,
                  'display' => $contactComponent
                    ->wf_crm_contact_access($related_component, $contactComponent
                    ->wf_crm_search_filters($this->node, $related_component), $related_cid),
                ];
              }
            }
          }
        }

        // We want counties, states and countries in that order to avoid race-conditions client-side
        $data = array_merge($data, $states, $countries);
      }
    }
    return $data;
  }

  /**
   * Access callback. Check if user has permission to view autocomplete results.
   *
   * @param Webform $webform
   * @param string $fid
   *   Webform component id
   *
   * @return bool
   */
  public function autocompleteAccess($webform, $fid) {
    $user = \Drupal::currentUser();
    if (!$fid || empty($webform
      ->getHandler('webform_civicrm'))) {
      return FALSE;
    }
    $element = $webform
      ->getElement($fid);
    if (empty($element) || !$webform
      ->access('submission_create')) {
      return FALSE;
    }
    if ($user
      ->id() === 1 || $user
      ->hasPermission('access all webform results') || $user
      ->hasPermission('access own webform results') && $webform
      ->uuid() == $user
      ->id()) {
      return TRUE;
    }

    /** @var \Drupal\webform\Plugin\WebformElementManagerInterface $element_manager */
    $element_manager = \Drupal::service('plugin.manager.webform.element');
    $element_instance = $element_manager
      ->getElementInstance($element);

    // @todo test after moving to getElementProperty.
    if (!empty($element_instance
      ->getElementProperty($element, 'private'))) {
      return FALSE;
    }

    /* TODO figure out what this means in Drupal 8
       if (\Drupal::state()->get('webform_submission_access_control', 1)) {
         $allowed_roles = array();
         foreach ($node->webform['roles'] as $rid) {
           $allowed_roles[$rid] = isset($user->roles[$rid]) ? TRUE : FALSE;
         }
         if (array_search(TRUE, $allowed_roles) === FALSE) {
           return FALSE;
         }
       }*/

    // ToDo - to be refactored -> it would be safer to return FALSE by default.
    return TRUE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
WebformAjax::$requestStack private property
WebformAjax::autocompleteAccess public function Access callback. Check if user has permission to view autocomplete results. Overrides WebformAjaxInterface::autocompleteAccess
WebformAjax::contactAjax function Load one or more contacts via ajax Overrides WebformAjaxInterface::contactAjax
WebformAjax::getParameter private function Replacement of the reading of $_GET
WebformAjax::__construct function
WebformCivicrmBase::$data protected property
WebformCivicrmBase::$enabled protected property
WebformCivicrmBase::$ent protected property
WebformCivicrmBase::$events protected property
WebformCivicrmBase::$line_items protected property
WebformCivicrmBase::$loadedContacts protected property
WebformCivicrmBase::$membership_types protected property
WebformCivicrmBase::$node protected property
WebformCivicrmBase::$settings protected property
WebformCivicrmBase::$_payment_processor private property
WebformCivicrmBase::$_tax_rate private property
WebformCivicrmBase::addPaymentJs function CiviCRM JS can't be attached to a drupal form so have to manually re-add this during validation
WebformCivicrmBase::add_user_select_field_placeholder protected function Add location_type_id = NULL for user-select fields for identification later
WebformCivicrmBase::findCaseForContact function Find a case matching criteria
WebformCivicrmBase::findContact protected function Find an existing contact based on matching criteria Used to populate a webform existing contact field
WebformCivicrmBase::findMemberships protected function Get memberships for a contact
WebformCivicrmBase::getAttachments public function FIXME: Use the api for this
WebformCivicrmBase::getComponent protected function Fetch a webform component given its civicrm field key
WebformCivicrmBase::getCustomData protected function Get custom data for an entity
WebformCivicrmBase::getData protected function
WebformCivicrmBase::getDefaults function Returns a default value for a component.
WebformCivicrmBase::getDrupalFileUrl function Fetch the public url of a file in the Drupal file system
WebformCivicrmBase::getExposedOptions protected function For a given field, find the options that are exposed to the webform.
WebformCivicrmBase::getFileInfo function Retrieve info needed for pre-filling a webform file field
WebformCivicrmBase::getMembershipTypeField protected function
WebformCivicrmBase::getQfKey public function Generate the quickform key needed to access a contribution form
WebformCivicrmBase::getRelationship protected function Fetch relationship for a pair of contacts
WebformCivicrmBase::handleRemainingValues protected function Put remaining values in 'user-select' fields
WebformCivicrmBase::loadBillingAddress protected function Load Billing Address for contact.
WebformCivicrmBase::loadContact protected function Fetch all relevant data for a given contact Used to load contacts for pre-filling a webform, and also to fill in a contact via ajax
WebformCivicrmBase::loadEvents protected function Fetch info and remaining spaces for events
WebformCivicrmBase::matchLocationTypes protected function Organize values according to location types
WebformCivicrmBase::matchWebsiteTypes protected function Organize values according to website types
WebformCivicrmBase::MULTIVALUE_FIELDSET_MODE_CREATE_OR_EDIT constant
WebformCivicrmBase::reorderByLocationType protected function Reorder returned results according to settings chosen in wf_civicrm backend
WebformCivicrmBase::saveDrupalFileToCivi public static function Copies a drupal file into the Civi file system
WebformCivicrmBase::__get function Magic method to retrieve otherwise inaccessible properties