Merge pull request #17443 from eileenmcnaughton/renew
authorSeamus Lee <seamuslee001@gmail.com>
Tue, 2 Jun 2020 06:03:25 +0000 (16:03 +1000)
committerGitHub <noreply@github.com>
Tue, 2 Jun 2020 06:03:25 +0000 (16:03 +1000)
[REF] Minor simplification

33 files changed:
CRM/Activity/BAO/Activity.php
CRM/Contact/BAO/ContactType.php
CRM/Contact/Form/Search/Custom/DateAdded.php
CRM/Contact/Form/Task/EmailTrait.php
CRM/Contribute/Form/CancelSubscription.php
CRM/Core/I18n/SchemaStructure.php
CRM/Core/Payment.php
CRM/Core/Payment/AuthorizeNet.php
CRM/Core/Payment/Manual.php
CRM/Member/BAO/Membership.php
CRM/Member/DAO/MembershipType.php
CRM/Member/Page/Tab.php
CRM/Utils/Address/USPS.php
CRM/Utils/Geocode/Google.php
Civi/Api4/Action/Entity/GetLinks.php
Civi/Api4/Query/Api4SelectQuery.php
Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
Civi/Api4/Service/Schema/SchemaMapBuilder.php
Civi/Payment/PropertyBag.php
Civi/Test/GuzzleTestTrait.php [new file with mode: 0644]
composer.json
composer.lock
package-lock.json
package.json
release-notes.md
release-notes/5.26.0.md [new file with mode: 0644]
templates/CRM/Contribute/Form/CancelSubscription.tpl
tests/phpunit/CRM/Activity/BAO/ActivityTest.php
tests/phpunit/CRM/Activity/Form/ActivityTest.php
tests/phpunit/CRM/Contact/Form/Task/DeleteTest.php [new file with mode: 0644]
tests/phpunit/CRM/Core/Payment/AuthorizeNetTest.php
tests/phpunit/api/v3/FinancialTypeACLTest.php
xml/schema/Member/MembershipType.xml

index 20d2f0e072fc2972af0bbc4bedaf931af61adf5d..1efa8202448fde0067d7347565f84e571a285b2a 100644 (file)
@@ -182,6 +182,8 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
         // CRM-13994 delete activity entity_tag
         $query = "DELETE FROM civicrm_entity_tag WHERE entity_table = 'civicrm_activity' AND entity_id = %1";
         $dao = CRM_Core_DAO::executeQuery($query, [1 => [$activity->id, 'Positive']]);
+
+        CRM_Core_BAO_File::deleteEntityFile('civicrm_activity', $activity->id);
       }
     }
     else {
index 8a2e811c5720762c57c03f63158ebdd0eb9d2dd0..42fb2ba54dfba4508c01424c1c0732aa5d14fee3 100644 (file)
@@ -603,7 +603,7 @@ WHERE name = %1';
 
     if (!empty($params['id'])) {
       $newParams = [
-        'label' => "New $contact",
+        'label' => ts("New %1", [1 => $contact]),
         'is_active' => $active,
       ];
       CRM_Core_BAO_Navigation::processUpdate(['name' => "New $contactName"], $newParams);
@@ -616,7 +616,7 @@ WHERE name = %1';
       $value = ['name' => "New $name"];
       CRM_Core_BAO_Navigation::retrieve($value, $navinfo);
       $navigation = [
-        'label' => "New $contact",
+        'label' => ts("New %1", [1 => $contact]),
         'name' => "New $contactName",
         'url' => "civicrm/contact/add?ct=$name&cst=$contactName&reset=1",
         'permission' => 'add contacts',
index 695d98b426b25cf5f0b2330c5e7e9bb68e74053e..8fca291f52b2822e877caebc0dd4c3d06a682d20 100644 (file)
@@ -383,19 +383,6 @@ class CRM_Contact_Form_Search_Custom_DateAdded extends CRM_Contact_Form_Search_C
     return $dao->N;
   }
 
-  public function __destruct() {
-    //drop the temp. tables if they exist
-    if ($this->_igTable && !empty($this->_includeGroups)) {
-      $sql = "DROP TEMPORARY TABLE IF EXISTS {$this->_igTable}";
-      CRM_Core_DAO::executeQuery($sql);
-    }
-
-    if ($this->_xgTable && !empty($this->_excludeGroups)) {
-      $sql = "DROP TEMPORARY TABLE IF EXISTS {$this->_xgTable}";
-      CRM_Core_DAO::executeQuery($sql);
-    }
-  }
-
   /**
    * @param string $tableAlias
    */
index 97b4347027224aab94e0c12cee6c716f122fdc23..c2ba6c1194e695aac29380bfa436c2e94d1403cb 100644 (file)
@@ -397,7 +397,6 @@ trait CRM_Contact_Form_Task_EmailTrait {
     // If we have had a contact email used here the value returned from the line above will be the
     // numerical key where as $from for use in the sendEmail in Activity needs to be of format of "To Name" <toemailaddress>
     $from = CRM_Utils_Mail::formatFromAddress($from);
-    $subject = $formValues['subject'];
 
     $ccArray = $formValues['cc_id'] ? explode(',', $formValues['cc_id']) : [];
     $cc = $this->getEmailString($ccArray);
@@ -407,12 +406,6 @@ trait CRM_Contact_Form_Task_EmailTrait {
     $bcc = $this->getEmailString($bccArray);
     $additionalDetails .= empty($bccArray) ? '' : "\nbcc : " . $this->getEmailUrlString($bccArray);
 
-    // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
-    if (isset($this->_caseId) && is_numeric($this->_caseId)) {
-      $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7);
-      $subject = "[case #$hash] $subject";
-    }
-
     // format contact details array to handle multiple emails from same contact
     $formattedContactDetails = [];
     foreach ($this->_contactIds as $key => $contactId) {
@@ -430,15 +423,10 @@ trait CRM_Contact_Form_Task_EmailTrait {
       $formattedContactDetails["{$contactId}::{$email}"] = $details;
     }
 
-    $contributionIds = [];
-    if ($this->getVar('_contributionIds')) {
-      $contributionIds = $this->getVar('_contributionIds');
-    }
-
     // send the mail
     list($sent, $activityId) = CRM_Activity_BAO_Activity::sendEmail(
       $formattedContactDetails,
-      $subject,
+      $this->getSubject($formValues['subject']),
       $formValues['text_message'],
       $formValues['html_message'],
       NULL,
@@ -449,7 +437,7 @@ trait CRM_Contact_Form_Task_EmailTrait {
       $bcc,
       array_keys($this->_toContactDetails),
       $additionalDetails,
-      $contributionIds,
+      $this->getVar('_contributionIds') ?? [],
       CRM_Utils_Array::value('campaign_id', $formValues),
       $this->getVar('_caseId')
     );
@@ -643,4 +631,22 @@ trait CRM_Contact_Form_Task_EmailTrait {
     return $attachments;
   }
 
+  /**
+   * Get the subject for the message.
+   *
+   * The case handling should possibly be on the case form.....
+   *
+   * @param string $subject
+   *
+   * @return string
+   */
+  protected function getSubject(string $subject):string {
+    // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
+    if (isset($this->_caseId) && is_numeric($this->_caseId)) {
+      $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7);
+      $subject = "[case #$hash] $subject";
+    }
+    return $subject;
+  }
+
 }
index 831b5e9b551960e24e1ada70ca21bbc3e1574781..ec7cd0fc957144b23cc1d5fa669d4b1a52eb6636 100644 (file)
@@ -133,8 +133,7 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
   public function buildQuickForm() {
     $this->buildQuickEntityForm();
     // Determine if we can cancel recurring contribution via API with this processor
-    $cancelSupported = $this->_paymentProcessorObj->supports('CancelRecurring');
-    if ($cancelSupported) {
+    if ($this->_paymentProcessorObj->supports('CancelRecurringNotifyOptional')) {
       $searchRange = [];
       $searchRange[] = $this->createElement('radio', NULL, NULL, ts('Yes'), '1');
       $searchRange[] = $this->createElement('radio', NULL, NULL, ts('No'), '0');
@@ -149,7 +148,6 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
     else {
       $this->assign('cancelRecurNotSupportedText', $this->_paymentProcessorObj->getText('cancelRecurNotSupportedText', []));
     }
-    $this->assign('cancelSupported', $cancelSupported);
 
     if (!empty($this->_donorEmail)) {
       $this->add('checkbox', 'is_notify', ts('Notify Contributor?') . " ({$this->_donorEmail})");
@@ -195,6 +193,8 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
 
   /**
    * Process the form submission.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function postProcess() {
     $message = NULL;
@@ -212,16 +212,17 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
       }
     }
 
-    if (CRM_Utils_Array::value('send_cancel_request', $params) == 1) {
-      try {
-        $propertyBag = new PropertyBag();
-        $propertyBag->setContributionRecurID($this->getSubscriptionDetails()->recur_id);
-        $propertyBag->setRecurProcessorID($this->getSubscriptionDetails()->subscription_id);
-        $message = $this->_paymentProcessorObj->doCancelRecurring($propertyBag)['message'];
-      }
-      catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
-        CRM_Core_Error::statusBounce($e->getMessage());
+    try {
+      $propertyBag = new PropertyBag();
+      if (isset($params['send_cancel_request'])) {
+        $propertyBag->setIsNotifyProcessorOnCancelRecur(!empty($params['send_cancel_request']));
       }
+      $propertyBag->setContributionRecurID($this->getSubscriptionDetails()->recur_id);
+      $propertyBag->setRecurProcessorID($this->getSubscriptionDetails()->subscription_id);
+      $message = $this->_paymentProcessorObj->doCancelRecurring($propertyBag)['message'];
+    }
+    catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
+      CRM_Core_Error::statusBounce($e->getMessage());
     }
 
     if ($cancelSubscription) {
index 0c7cebdb80c1073d28175fc89d465afe606f6c6f..ecadf83929c92afe8751d3ef86a9ba1f984827ae 100644 (file)
@@ -118,7 +118,7 @@ class CRM_Core_I18n_SchemaStructure {
           'title' => "varchar(127) COMMENT 'Payment Processor Descriptive Name.'",
         ],
         'civicrm_membership_type' => [
-          'name' => "varchar(128) COMMENT 'Name of Membership Type'",
+          'name' => "varchar(128) NOT NULL COMMENT 'Name of Membership Type'",
           'description' => "varchar(255) COMMENT 'Description of Membership Type'",
         ],
         'civicrm_membership_block' => [
@@ -486,6 +486,7 @@ class CRM_Core_I18n_SchemaStructure {
           'name' => [
             'type' => "Text",
             'label' => "Name",
+            'required' => "true",
           ],
           'description' => [
             'type' => "TextArea",
index 288359d4e5e5e710820932c2c676b8bbe3eae040..aec1fadf7832dbb9d82c01ab95a614c9ef7c0c8f 100644 (file)
@@ -399,6 +399,19 @@ abstract class CRM_Core_Payment {
     return method_exists(CRM_Utils_System::getClassName($this), 'cancelSubscription');
   }
 
+  /**
+   * Does the processor support the user having a choice as to whether to cancel the recurring with the processor?
+   *
+   * If this returns TRUE then there will be an option to send a cancellation request in the cancellation form.
+   *
+   * This would normally be false for processors where CiviCRM maintains the schedule.
+   *
+   * @return bool
+   */
+  protected function supportsCancelRecurringNotifyOptional() {
+    return $this->supportsCancelRecurring();
+  }
+
   /**
    * Does this processor support pre-approval.
    *
@@ -615,7 +628,10 @@ abstract class CRM_Core_Payment {
         }
 
       case 'cancelRecurNotSupportedText':
-        return ts('Automatic cancellation is not supported for this payment processor. You or the contributor will need to manually cancel this recurring contribution using the payment processor website.');
+        if (!$this->supportsCancelRecurring()) {
+          return ts('Automatic cancellation is not supported for this payment processor. You or the contributor will need to manually cancel this recurring contribution using the payment processor website.');
+        }
+        return '';
 
     }
     CRM_Core_Error::deprecatedFunctionWarning('Calls to getText must use a supported method');
@@ -1375,6 +1391,11 @@ abstract class CRM_Core_Payment {
    * proceed. Note the form layer will only call this after calling
    * $processor->supports('cancelRecurring');
    *
+   * A payment processor can control whether to notify the actual payment provider or just
+   * cancel in CiviCRM by setting the `isNotifyProcessorOnCancelRecur` property on PropertyBag.
+   * If supportsCancelRecurringNotifyOptional() is TRUE this will be automatically set based on
+   * the user selection on the form. If FALSE you need to set it yourself.
+   *
    * @param \Civi\Payment\PropertyBag $propertyBag
    *
    * @return array
@@ -1382,7 +1403,8 @@ abstract class CRM_Core_Payment {
    * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
   public function doCancelRecurring(PropertyBag $propertyBag) {
-    if (method_exists($this, 'cancelSubscription')) {
+    if (method_exists($this, 'cancelSubscription')
+    && ($propertyBag->has('isNotifyProcessorOnCancelRecur') && $propertyBag->getIsNotifyProcessorOnCancelRecur())) {
       $message = NULL;
       if ($this->cancelSubscription($message, $propertyBag)) {
         return ['message' => $message];
index 52657cf22117d8a59c44579100f28bfaa5f54bcf..7f0c4f4fd2aece9b2ae0dcbc3be4f7fdd4092205 100644 (file)
@@ -32,6 +32,25 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
 
   protected $_params = [];
 
+  /**
+   * @var GuzzleHttp\Client
+   */
+  protected $guzzleClient;
+
+  /**
+   * @return \GuzzleHttp\Client
+   */
+  public function getGuzzleClient(): \GuzzleHttp\Client {
+    return $this->guzzleClient ?? new \GuzzleHttp\Client();
+  }
+
+  /**
+   * @param \GuzzleHttp\Client $guzzleClient
+   */
+  public function setGuzzleClient(\GuzzleHttp\Client $guzzleClient) {
+    $this->guzzleClient = $guzzleClient;
+  }
+
   /**
    * We only need one instance of this object. So we use the singleton
    * pattern and cache the instance in this variable
@@ -98,6 +117,8 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
    *
    * @return array
    *   the result in a nice formatted array (or an error object)
+   *
+   * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
   public function doDirectPayment(&$params) {
     if (!defined('CURLOPT_SSLCERT')) {
@@ -316,30 +337,22 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
     $template->assign('billingCountry', $this->_getParam('country'));
 
     $arbXML = $template->fetch('CRM/Contribute/Form/Contribution/AuthorizeNetARB.tpl');
-    // submit to authorize.net
 
-    $submit = curl_init($this->_paymentProcessor['url_recur']);
-    if (!$submit) {
-      return self::error(9002, 'Could not initiate connection to payment gateway');
-    }
-    curl_setopt($submit, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($submit, CURLOPT_HTTPHEADER, ["Content-Type: text/xml"]);
-    curl_setopt($submit, CURLOPT_HEADER, 1);
-    curl_setopt($submit, CURLOPT_POSTFIELDS, $arbXML);
-    curl_setopt($submit, CURLOPT_POST, 1);
-    curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, Civi::settings()->get('verifySSL'));
-
-    $response = curl_exec($submit);
-
-    if (!$response) {
-      return self::error(curl_errno($submit), curl_error($submit));
-    }
-
-    curl_close($submit);
-    $responseFields = $this->_ParseArbReturn($response);
-
-    if ($responseFields['resultCode'] == 'Error') {
-      return self::error($responseFields['code'], $responseFields['text']);
+    // Submit to authorize.net
+    $response = $this->getGuzzleClient()->post($this->_paymentProcessor['url_recur'], [
+      'headers' => [
+        'Content-Type' => 'text/xml; charset=UTF8',
+      ],
+      'body' => $arbXML,
+      'curl' => [
+        CURLOPT_RETURNTRANSFER => TRUE,
+        CURLOPT_SSL_VERIFYPEER => Civi::settings()->get('verifySSL'),
+      ],
+    ]);
+    $responseFields = $this->_ParseArbReturn((string) $response->getBody());
+
+    if ($responseFields['resultCode'] === 'Error') {
+      throw new PaymentProcessorException($responseFields['code'], $responseFields['text']);
     }
 
     // update recur processor_id with subscriptionId
index 302756419984b8573571d58a2806f67496ccba16..0a311b48da916fbfd04420dec9c98312f15e220f 100644 (file)
@@ -196,6 +196,19 @@ class CRM_Core_Payment_Manual extends CRM_Core_Payment {
     return TRUE;
   }
 
+  /**
+   * Does the processor support the user having a choice as to whether to cancel the recurring with the processor?
+   *
+   * If this returns TRUE then there will be an option to send a cancellation request in the cancellation form.
+   *
+   * This would normally be false for processors where CiviCRM maintains the schedule.
+   *
+   * @return bool
+   */
+  protected function supportsCancelRecurringNotifyOptional() {
+    return FALSE;
+  }
+
   /**
    * Are back office payments supported.
    *
index 90e68000ee0ad2dd91485636b5d845c73ada3744..df5e17a48d3cd6e45c4d338f5531315dd2cc3a96 100644 (file)
@@ -1579,6 +1579,11 @@ WHERE  civicrm_membership.contact_id = civicrm_contact.id
    * @return null|string
    */
   public static function getContactMembershipCount($contactID, $activeOnly = FALSE) {
+    CRM_Financial_BAO_FinancialType::getAvailableMembershipTypes($membershipTypes);
+    $addWhere = " AND membership_type_id IN (0)";
+    if (!empty($membershipTypes)) {
+      $addWhere = " AND membership_type_id IN (" . implode(',', array_keys($membershipTypes)) . ")";
+    }
     $select = "SELECT count(*) FROM civicrm_membership ";
     $where = "WHERE civicrm_membership.contact_id = {$contactID} AND civicrm_membership.is_test = 0 ";
 
@@ -1588,7 +1593,7 @@ WHERE  civicrm_membership.contact_id = civicrm_contact.id
       $where .= " and civicrm_membership_status.is_current_member = 1";
     }
 
-    $query = $select . $where;
+    $query = $select . $where . $addWhere;
     return CRM_Core_DAO::singleValueQuery($query);
   }
 
index 58c07d9bd7a753d53a94835fbf32ea245ac91fbf..9e51fd1fcc3c2bf6fde34de7da47c6d7989b93f3 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Member/MembershipType.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:c188b3772bd7ba843454e591a1fb0fd6)
+ * (GenCodeChecksum:c75161ef1844cf9a3977d458f0cb515b)
  */
 
 /**
@@ -237,6 +237,7 @@ class CRM_Member_DAO_MembershipType extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_STRING,
           'title' => ts('Membership Type'),
           'description' => ts('Name of Membership Type'),
+          'required' => TRUE,
           'maxlength' => 128,
           'size' => CRM_Utils_Type::HUGE,
           'import' => TRUE,
index 7c4ad24d143ac0f18572ff28cba266b88e0a7206..6818490f1784aa640fea28f2aa75d84234cb15e1 100644 (file)
@@ -33,9 +33,17 @@ class CRM_Member_Page_Tab extends CRM_Core_Page {
    * called when action is browse.
    */
   public function browse() {
+    $links = self::links('all', $this->_isPaymentProcessor, $this->_accessContribution);
+    CRM_Financial_BAO_FinancialType::getAvailableMembershipTypes($membershipTypes);
+    $addWhere = "membership_type_id IN (0)";
+    if (!empty($membershipTypes)) {
+      $addWhere = "membership_type_id IN (" . implode(',', array_keys($membershipTypes)) . ")";
+    }
+
     $membership = [];
     $dao = new CRM_Member_DAO_Membership();
     $dao->contact_id = $this->_contactId;
+    $dao->whereAdd($addWhere);
     $dao->find();
 
     //CRM--4418, check for view, edit, delete
index bba6d337a9bc3e2fd2a03a60804f0135c169deec..721b2e70e079b5bccf6e0875048ab165da95489a 100644 (file)
@@ -68,19 +68,17 @@ class CRM_Utils_Address_USPS {
 
     $XMLQuery = '<AddressValidateRequest USERID="' . $userID . '"><Address ID="0"><Address1>' . CRM_Utils_Array::value('supplemental_address_1', $values, '') . '</Address1><Address2>' . $address2 . '</Address2><City>' . $values['city'] . '</City><State>' . $values['state_province'] . '</State><Zip5>' . $values['postal_code'] . '</Zip5><Zip4>' . CRM_Utils_Array::value('postal_code_suffix', $values, '') . '</Zip4></Address></AddressValidateRequest>';
 
-    require_once 'HTTP/Request.php';
-    $request = new HTTP_Request();
-
-    $request->setURL($url);
-
-    $request->addQueryString('API', 'Verify');
-    $request->addQueryString('XML', $XMLQuery);
-
-    $response = $request->sendRequest();
+    $client = new GuzzleHttp\Client();
+    $request = $client->request('GET', $url, [
+      'query' => [
+        'API' => 'Verify',
+        'XML' => $XMLQuery,
+      ],
+    ]);
 
     $session = CRM_Core_Session::singleton();
 
-    $code = $request->getResponseCode();
+    $code = $request->getStatusCode();
     if ($code != 200) {
       $session->setStatus(ts('USPS Address Lookup Failed with HTTP status code: %1',
         [1 => $code]
@@ -88,7 +86,7 @@ class CRM_Utils_Address_USPS {
       return FALSE;
     }
 
-    $responseBody = $request->getResponseBody();
+    $responseBody = $request->getBody();
 
     $xml = simplexml_load_string($responseBody);
 
index 1cb0c847ca5610ab83b7885dcf5ca717742853a5..6ab1397fea8d8be13c67b0ca51c570f4dff30798 100644 (file)
@@ -105,10 +105,9 @@ class CRM_Utils_Geocode_Google {
 
     $query = 'https://' . self::$_server . self::$_uri . $add;
 
-    require_once 'HTTP/Request.php';
-    $request = new HTTP_Request($query);
-    $request->sendRequest();
-    $string = $request->getResponseBody();
+    $client = new GuzzleHttp\Client();
+    $request = $client->request('GET', $query);
+    $string = $request->getBody();
 
     libxml_use_internal_errors(TRUE);
     $xml = @simplexml_load_string($string);
index e841c566aca2ebb0d541681b29047add928aac4c..5a4bc69785b2cda6c3ef6b95d37f505a6b2e3d7e 100644 (file)
@@ -40,9 +40,7 @@ class GetLinks extends \Civi\Api4\Generic\BasicGetAction {
           'links' => [],
         ];
         foreach ($table->getTableLinks() as $link) {
-          $link = $link->toArray();
-          $link['entity'] = CoreUtil::getApiNameFromTableName($link['targetTable']);
-          $item['links'][] = $link;
+          $item['links'][] = $link->toArray();
         }
         $result[] = $item;
       }
index 9dffe7a734959810dd1e817973aa6aa884e7f8e6..5378454474eecb40b022e83fd8e0fde41df2a290 100644 (file)
@@ -518,9 +518,8 @@ class Api4SelectQuery extends SelectQuery {
     }
     $prefix = $pathArray ? implode('.', $pathArray) . '.' : '';
     // Cache field info for retrieval by $this->getField()
-    $joinEntity = $lastLink->getEntity();
     foreach ($lastLink->getEntityFields() as $fieldObject) {
-      $fieldArray = ['entity' => $joinEntity] + $fieldObject->toArray();
+      $fieldArray = $fieldObject->toArray();
       $fieldArray['sql_name'] = '`' . $lastLink->getAlias() . '`.`' . $fieldArray['column_name'] . '`';
       $fieldArray['is_custom'] = $isCustom;
       $fieldArray['is_join'] = TRUE;
index fd5ab30f9ddf9652bec69dfab6b2758422c730e2..464cd911f431dd8fbf5f772bf008f21affe50003 100644 (file)
@@ -41,15 +41,17 @@ class CustomGroupJoinable extends Joinable {
    * @param $targetTable
    * @param $alias
    * @param bool $isMultiRecord
-   * @param string $entity
    * @param string $columns
    */
-  public function __construct($targetTable, $alias, $isMultiRecord, $entity, $columns) {
-    $this->entity = $entity;
+  public function __construct($targetTable, $alias, $isMultiRecord, $columns) {
     $this->columns = $columns;
     parent::__construct($targetTable, 'entity_id', $alias);
     $this->joinType = $isMultiRecord ?
       self::JOIN_TYPE_ONE_TO_MANY : self::JOIN_TYPE_ONE_TO_ONE;
+    // Only multi-record groups are considered an api "entity"
+    if (!$isMultiRecord) {
+      $this->entity = NULL;
+    }
   }
 
   /**
@@ -59,11 +61,11 @@ class CustomGroupJoinable extends Joinable {
     if (!$this->entityFields) {
       $fields = CustomField::get()
         ->setCheckPermissions(FALSE)
-        ->setSelect(['custom_group.name', '*'])
+        ->setSelect(['custom_group.name', 'custom_group.extends', '*'])
         ->addWhere('custom_group.table_name', '=', $this->getTargetTable())
         ->execute();
       foreach ($fields as $field) {
-        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntity());
+        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntityFromExtends($field['custom_group.extends']));
       }
     }
     return $this->entityFields;
@@ -92,4 +94,25 @@ class CustomGroupJoinable extends Joinable {
     return $this->columns[$fieldName];
   }
 
+  /**
+   * Translate custom_group.extends to entity name.
+   *
+   * Custom_group.extends pretty much maps 1-1 with entity names, except for a couple oddballs.
+   * @see \CRM_Core_SelectValues::customGroupExtends
+   *
+   * @param $extends
+   * @return string
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  private function getEntityFromExtends($extends) {
+    if (strpos($extends, 'Participant') === 0) {
+      return 'Participant';
+    }
+    if ($extends === 'Contact' || in_array($extends, \CRM_Contact_BAO_ContactType::basicTypes(TRUE))) {
+      return 'Contact';
+    }
+    return $extends;
+  }
+
 }
index b6393755e0ae6bf0c85a760737b0de05f0399a4c..afecc01056ade66658293062293a826477856fba 100644 (file)
@@ -111,7 +111,7 @@ class SchemaMapBuilder {
         $target = $map->getTableByName($link->getTargetTable());
         $tableName = $link->getBaseTable();
         // Exclude custom field tables
-        if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0) {
+        if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0 && strpos($link->getBaseTable(), 'civicrm_value_') !== 0) {
           $plural = str_replace('civicrm_', '', $this->getPlural($tableName));
           $joinable = new Joinable($tableName, $link->getBaseColumn(), $plural);
           $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
@@ -190,7 +190,7 @@ class SchemaMapBuilder {
     }
 
     foreach ($links as $alias => $link) {
-      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $entity, $link['columns']);
+      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $link['columns']);
       $baseTable->addTableLink('id', $joinable);
     }
   }
index 4423fce5eca8d4d89e6b3c81b70859652a604207..3fc564183fdd2aa6b83dd3f1cede4d634a44e9a4 100644 (file)
@@ -72,6 +72,7 @@ class PropertyBag implements \ArrayAccess {
     'transactionID'               => TRUE,
     'transaction_id'              => 'transactionID',
     'trxnResultCode'              => TRUE,
+    'isNotifyProcessorOnCancelRecur' => TRUE,
   ];
 
   /**
@@ -480,6 +481,8 @@ class PropertyBag implements \ArrayAccess {
    *
    * @param string $input
    * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
    */
   public function setBillingCity($input, $label = 'default') {
     return $this->set('billingCity', $label, (string) $input);
@@ -794,6 +797,35 @@ class PropertyBag implements \ArrayAccess {
     return $this->set('isRecur', $label, (bool) $isRecur);
   }
 
+  /**
+   * Set whether the user has selected to notify the processor of a cancellation request.
+   *
+   * When cancelling the user may be presented with an option to notify the processor. The payment
+   * processor can take their response, if present, into account.
+   *
+   * @param bool $value
+   * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
+   */
+  public function setIsNotifyProcessorOnCancelRecur($value, $label = 'default') {
+    return $this->set('isNotifyProcessorOnCancelRecur', $label, (bool) $value);
+  }
+
+  /**
+   * Get whether the user has selected to notify the processor of a cancellation request.
+   *
+   * When cancelling the user may be presented with an option to notify the processor. The payment
+   * processor can take their response, if present, into account.
+   *
+   * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
+   */
+  public function getIsNotifyProcessorOnCancelRecur($label = 'default') {
+    return $this->get('isNotifyProcessorOnCancelRecur', $label);
+  }
+
   /**
    * Last name
    *
diff --git a/Civi/Test/GuzzleTestTrait.php b/Civi/Test/GuzzleTestTrait.php
new file mode 100644 (file)
index 0000000..c372d3e
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+
+namespace Civi\Test;
+
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Middleware;
+use GuzzleHttp\Client;
+
+/**
+ * Class GuzzleTestTrait
+ *
+ * This trait defines a number of helper functions for testing guzzle.
+ */
+trait GuzzleTestTrait {
+  /**
+   * @var \GuzzleHttp\Client
+   */
+  protected $guzzleClient;
+
+  /**
+   * Array containing guzzle history of requests and responses.
+   *
+   * @var array
+   */
+  protected $container;
+
+  /**
+   * Mockhandler to simulate guzzle requests.
+   *
+   * @var \GuzzleHttp\Handler\MockHandler
+   */
+  protected $mockHandler;
+
+  /**
+   * The url to mock-interact with.
+   *
+   * @var string
+   */
+  protected $baseUri;
+
+  /**
+   * @return \GuzzleHttp\Client
+   */
+  public function getGuzzleClient() {
+    return $this->guzzleClient;
+  }
+
+  /**
+   * @param \GuzzleHttp\Client $guzzleClient
+   */
+  public function setGuzzleClient($guzzleClient) {
+    $this->guzzleClient = $guzzleClient;
+  }
+
+  /**
+   * @return array
+   */
+  public function getContainer() {
+    return $this->container;
+  }
+
+  /**
+   * @param array $container
+   */
+  public function setContainer($container) {
+    $this->container = $container;
+  }
+
+  /**
+   * @return mixed
+   */
+  public function getBaseUri() {
+    return $this->baseUri;
+  }
+
+  /**
+   * @param mixed $baseUri
+   */
+  public function setBaseUri($baseUri) {
+    $this->baseUri = $baseUri;
+  }
+
+  /**
+   * @return \GuzzleHttp\Handler\MockHandler
+   */
+  public function getMockHandler() {
+    return $this->mockHandler;
+  }
+
+  /**
+   * @param \GuzzleHttp\Handler\MockHandler $mockHandler
+   */
+  public function setMockHandler($mockHandler) {
+    $this->mockHandler = $mockHandler;
+  }
+
+  /**
+   * @param $responses
+   */
+  protected function createMockHandler($responses) {
+    $mocks = [];
+    foreach ($responses as $response) {
+      $mocks[] = new Response(200, [], $response);
+    }
+    $this->setMockHandler(new MockHandler($mocks));
+  }
+
+  /**
+   * @param $files
+   */
+  protected function createMockHandlerForFiles($files) {
+    $body = [];
+    foreach ($files as $file) {
+      $body[] = trim(file_get_contents(__DIR__ . $file));
+    }
+    $this->createMockHandler($body);
+  }
+
+  /**
+   * Set up a guzzle client with a history container.
+   *
+   * After you have run the requests you can inspect $this->container
+   * for the outgoing requests and incoming responses.
+   *
+   * If $this->mock is defined then no outgoing http calls will be made
+   * and the responses configured on the handler will be returned instead
+   * of replies from a remote provider.
+   */
+  protected function setUpClientWithHistoryContainer() {
+    $this->container = [];
+    $history = Middleware::history($this->container);
+    $handler = HandlerStack::create($this->getMockHandler());
+    $handler->push($history);
+    $this->guzzleClient = new Client(['base_uri' => $this->baseUri, 'handler' => $handler]);
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestBodies() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = (string) $guzzle['request']->getBody();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestHeaders() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = $guzzle['request']->getHeaders();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestUrls() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = (string) $guzzle['request']->getUri();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the responses returned via Guzzle.
+   *
+   * @return array
+   */
+  protected function getResponseBodies() {
+    $responses = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $responses[] = (string) $guzzle['response']->getBody();
+    }
+    return $responses;
+  }
+
+}
index 0587ec55f469d9306d1d33250e9df9cc8a20f8ba..f7226e719a3e087bc27ea0e2872b7ae281e78c98 100644 (file)
@@ -69,7 +69,7 @@
     "guzzlehttp/guzzle": "^6.3",
     "psr/simple-cache": "~1.0.1",
     "cweagans/composer-patches": "~1.0",
-    "pear/log": "1.13.1",
+    "pear/log": "1.13.2",
     "adrienrn/php-mimetyper": "0.2.2",
     "civicrm/composer-downloads-plugin": "^2.0",
     "league/csv": "^9.2",
index d846ce1b03667457c3117c74ead37965db53c174..d2b5f94261dd7e5ffae6954fa036f55461233769 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "2c878584eb2dc9da8a1b13e2db07361f",
+    "content-hash": "f547e4d1ac65fa8044d302f46a7e7267",
     "packages": [
         {
             "name": "adrienrn/php-mimetyper",
         },
         {
             "name": "pear/log",
-            "version": "1.13.1",
+            "version": "1.13.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pear/Log.git",
-                "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803"
+                "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pear/Log/zipball/c4be9ded2353c7c231d4c35cc3da75b209453803",
-                "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803",
+                "url": "https://api.github.com/repos/pear/Log/zipball/d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
+                "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
                 "shasum": ""
             },
             "require": {
-                "pear/pear_exception": "1.0.0",
+                "pear/pear_exception": "1.0.1",
                 "php": ">5.2"
             },
             "require-dev": {
                 "log",
                 "logging"
             ],
-            "time": "2016-04-16T00:49:33+00:00"
+            "time": "2020-06-02T00:04:03+00:00"
         },
         {
             "name": "pear/mail",
         },
         {
             "name": "pear/pear_exception",
-            "version": "v1.0.0",
+            "version": "v1.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pear/PEAR_Exception.git",
-                "reference": "8c18719fdae000b690e3912be401c76e406dd13b"
+                "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b",
-                "reference": "8c18719fdae000b690e3912be401c76e406dd13b",
+                "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
+                "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
                 "shasum": ""
             },
             "require": {
                 }
             },
             "autoload": {
-                "psr-0": {
-                    "PEAR": ""
-                }
+                "classmap": [
+                    "PEAR/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "include-path": [
             "keywords": [
                 "exception"
             ],
-            "time": "2015-02-10T20:07:52+00:00"
+            "time": "2019-12-10T10:24:42+00:00"
         },
         {
             "name": "pear/validate_finance_creditcard",
             "version": "3.0.0+php53",
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/tplaner/When/archive/c1ec099f421bff354cc5c929f83b94031423fc80.zip",
-                "reference": null,
-                "shasum": null
+                "url": "https://github.com/tplaner/When/archive/c1ec099f421bff354cc5c929f83b94031423fc80.zip"
             },
             "require": {
                 "php": ">=5.3.0"
     "platform-dev": [],
     "platform-overrides": {
         "php": "7.1"
-    }
+    },
+    "plugin-api-version": "1.1.0"
 }
index fe14bab525fb0503e3d1b2b82340707db551aee7..a44154e130ca1b3c8c933ca047ef1b731200d34e 100644 (file)
@@ -4,14 +4,37 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
+    },
     "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
       "dev": true,
       "requires": {
-        "mime-types": "~2.1.18",
-        "negotiator": "0.6.1"
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
+      },
+      "dependencies": {
+        "mime-db": {
+          "version": "1.44.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+          "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
+          "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.27",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+          "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+          "dev": true,
+          "requires": {
+            "mime-db": "1.44.0"
+          }
+        }
       }
     },
     "after": {
         "uri-js": "^4.2.2"
       }
     },
-    "anymatch": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
-      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+    "ansi-regex": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+      "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
       "dev": true,
       "requires": {
-        "micromatch": "^3.1.4",
-        "normalize-path": "^2.1.1"
-      },
-      "dependencies": {
-        "normalize-path": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-          "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
-          "dev": true,
-          "requires": {
-            "remove-trailing-separator": "^1.0.1"
-          }
-        }
+        "@types/color-name": "^1.1.1",
+        "color-convert": "^2.0.1"
       }
     },
-    "arr-diff": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-      "dev": true
-    },
-    "arr-flatten": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
-      "dev": true
-    },
-    "arr-union": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
-      "dev": true
-    },
-    "array-unique": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-      "dev": true
+    "anymatch": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
     },
     "arraybuffer.slice": {
       "version": "0.0.7",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
       "dev": true
     },
-    "assign-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
-      "dev": true
-    },
-    "async": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
-      "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.11"
-      }
-    },
-    "async-each": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
-      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
-      "dev": true
-    },
     "async-limiter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
-      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
       "dev": true
     },
     "asynckit": {
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
       "dev": true
     },
-    "atob": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
-      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
-      "dev": true
-    },
     "aws-sign2": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
       "dev": true
     },
-    "base": {
-      "version": "0.11.2",
-      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
-      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
-      "dev": true,
-      "requires": {
-        "cache-base": "^1.0.1",
-        "class-utils": "^0.3.5",
-        "component-emitter": "^1.2.1",
-        "define-property": "^1.0.0",
-        "isobject": "^3.0.1",
-        "mixin-deep": "^1.2.0",
-        "pascalcase": "^0.1.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.0"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
     "base64-arraybuffer": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
       "dev": true
     },
     "base64id": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
-      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+      "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
       "dev": true
     },
     "bcrypt-pbkdf": {
       }
     },
     "binary-extensions": {
-      "version": "1.13.1",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
-      "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+      "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
       "dev": true
     },
     "blob": {
       "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
       "dev": true
     },
-    "bluebird": {
-      "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz",
-      "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
-      "dev": true
-    },
     "body-parser": {
-      "version": "1.18.3",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
-      "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
       "dev": true,
       "requires": {
-        "bytes": "3.0.0",
+        "bytes": "3.1.0",
         "content-type": "~1.0.4",
         "debug": "2.6.9",
         "depd": "~1.1.2",
-        "http-errors": "~1.6.3",
-        "iconv-lite": "0.4.23",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
         "on-finished": "~2.3.0",
-        "qs": "6.5.2",
-        "raw-body": "2.3.3",
-        "type-is": "~1.6.16"
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.7.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+          "dev": true
+        }
       }
     },
     "bower": {
       }
     },
     "braces": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-      "dev": true,
-      "requires": {
-        "arr-flatten": "^1.1.0",
-        "array-unique": "^0.3.2",
-        "extend-shallow": "^2.0.1",
-        "fill-range": "^4.0.0",
-        "isobject": "^3.0.1",
-        "repeat-element": "^1.1.2",
-        "snapdragon": "^0.8.1",
-        "snapdragon-node": "^2.0.1",
-        "split-string": "^3.0.2",
-        "to-regex": "^3.0.1"
-      }
-    },
-    "buffer-alloc": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
-      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
       "dev": true,
       "requires": {
-        "buffer-alloc-unsafe": "^1.1.0",
-        "buffer-fill": "^1.0.0"
+        "fill-range": "^7.0.1"
       }
     },
-    "buffer-alloc-unsafe": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
-      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
-      "dev": true
-    },
-    "buffer-fill": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
-      "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
-      "dev": true
-    },
     "bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
       "dev": true
     },
-    "cache-base": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
-      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
-      "dev": true,
-      "requires": {
-        "collection-visit": "^1.0.0",
-        "component-emitter": "^1.2.1",
-        "get-value": "^2.0.6",
-        "has-value": "^1.0.0",
-        "isobject": "^3.0.1",
-        "set-value": "^2.0.0",
-        "to-object-path": "^0.3.0",
-        "union-value": "^1.0.0",
-        "unset-value": "^1.0.0"
-      }
-    },
     "callsite": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
       "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
       "dev": true
     },
+    "camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true
+    },
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
       }
     },
     "chokidar": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz",
-      "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==",
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
+      "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
       "dev": true,
       "requires": {
-        "anymatch": "^2.0.0",
-        "async-each": "^1.0.1",
-        "braces": "^2.3.2",
-        "fsevents": "^1.2.7",
-        "glob-parent": "^3.1.0",
-        "inherits": "^2.0.3",
-        "is-binary-path": "^1.0.0",
-        "is-glob": "^4.0.0",
-        "normalize-path": "^3.0.0",
-        "path-is-absolute": "^1.0.0",
-        "readdirp": "^2.2.1",
-        "upath": "^1.1.1"
+        "anymatch": "~3.1.1",
+        "braces": "~3.0.2",
+        "fsevents": "~2.1.2",
+        "glob-parent": "~5.1.0",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.4.0"
       }
     },
     "civicrm-cv": {
         "child-process-promise": "^2.1.3"
       }
     },
-    "class-utils": {
-      "version": "0.3.6",
-      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
-      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+    "cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
       "dev": true,
       "requires": {
-        "arr-union": "^3.1.0",
-        "define-property": "^0.2.5",
-        "isobject": "^3.0.0",
-        "static-extend": "^0.1.1"
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
       }
     },
-    "collection-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
       "dev": true,
       "requires": {
-        "map-visit": "^1.0.0",
-        "object-visit": "^1.0.0"
+        "color-name": "~1.1.4"
       }
     },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
     "colors": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
-      "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
       "dev": true
     },
     "combined-stream": {
       "dev": true
     },
     "component-emitter": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
-      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
       "dev": true
     },
     "component-inherit": {
       }
     },
     "connect": {
-      "version": "3.6.6",
-      "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
-      "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
       "dev": true,
       "requires": {
         "debug": "2.6.9",
-        "finalhandler": "1.1.0",
-        "parseurl": "~1.3.2",
+        "finalhandler": "1.1.2",
+        "parseurl": "~1.3.3",
         "utils-merge": "1.0.1"
       }
     },
       "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
       "dev": true
     },
-    "copy-descriptor": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
-      "dev": true
-    },
-    "core-js": {
-      "version": "2.6.5",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
-      "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==",
-      "dev": true
-    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
       }
     },
     "date-format": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz",
-      "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
+      "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==",
       "dev": true
     },
     "debug": {
         "ms": "2.0.0"
       }
     },
-    "decode-uri-component": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
-      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
       "dev": true
     },
-    "define-property": {
-      "version": "0.2.5",
-      "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-      "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-      "dev": true,
-      "requires": {
-        "is-descriptor": "^0.1.0"
-      }
-    },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
       "dev": true
     },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
     "encodeurl": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "dev": true
     },
     "engine.io": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
-      "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz",
+      "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==",
       "dev": true,
       "requires": {
         "accepts": "~1.3.4",
-        "base64id": "1.0.0",
+        "base64id": "2.0.0",
         "cookie": "0.3.1",
-        "debug": "~3.1.0",
-        "engine.io-parser": "~2.1.0",
-        "ws": "~3.3.1"
+        "debug": "~4.1.0",
+        "engine.io-parser": "~2.2.0",
+        "ws": "^7.1.2"
       },
       "dependencies": {
         "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
           }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
         }
       }
     },
     "engine.io-client": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
-      "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.2.tgz",
+      "integrity": "sha512-AWjc1Xg06a6UPFOBAzJf48W1UR/qKYmv/ubgSCumo9GXgvL/xGIvo05dXoBL+2NTLMipDI7in8xK61C17L25xg==",
       "dev": true,
       "requires": {
-        "component-emitter": "1.2.1",
+        "component-emitter": "~1.3.0",
         "component-inherit": "0.0.3",
-        "debug": "~3.1.0",
-        "engine.io-parser": "~2.1.1",
+        "debug": "~4.1.0",
+        "engine.io-parser": "~2.2.0",
         "has-cors": "1.1.0",
         "indexof": "0.0.1",
         "parseqs": "0.0.5",
         "parseuri": "0.0.5",
-        "ws": "~3.3.1",
+        "ws": "~6.1.0",
         "xmlhttprequest-ssl": "~1.5.4",
         "yeast": "0.1.2"
       },
       "dependencies": {
         "component-emitter": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+          "version": "1.3.0",
+          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+          "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
           "dev": true
         },
         "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
+        "ws": {
+          "version": "6.1.4",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
+          "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
+          "dev": true,
+          "requires": {
+            "async-limiter": "~1.0.0"
           }
         }
       }
     },
     "engine.io-parser": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
-      "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz",
+      "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==",
       "dev": true,
       "requires": {
         "after": "0.8.2",
       "dev": true
     },
     "eventemitter3": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
-      "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
+      "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
       "dev": true
     },
-    "expand-brackets": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-      "dev": true,
-      "requires": {
-        "debug": "^2.3.3",
-        "define-property": "^0.2.5",
-        "extend-shallow": "^2.0.1",
-        "posix-character-classes": "^0.1.0",
-        "regex-not": "^1.0.0",
-        "snapdragon": "^0.8.1",
-        "to-regex": "^3.0.1"
-      }
-    },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
       "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
       "dev": true
     },
-    "extend-shallow": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-      "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-      "dev": true,
-      "requires": {
-        "is-extendable": "^0.1.0"
-      }
-    },
-    "extglob": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-      "dev": true,
-      "requires": {
-        "array-unique": "^0.3.2",
-        "define-property": "^1.0.0",
-        "expand-brackets": "^2.1.4",
-        "extend-shallow": "^2.0.1",
-        "fragment-cache": "^0.2.1",
-        "regex-not": "^1.0.0",
-        "snapdragon": "^0.8.1",
-        "to-regex": "^3.0.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.0"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
     "extract-zip": {
       "version": "1.6.6",
       "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz",
       }
     },
     "fill-range": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-      "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
       "dev": true,
       "requires": {
-        "extend-shallow": "^2.0.1",
-        "is-number": "^3.0.0",
-        "repeat-string": "^1.6.1",
-        "to-regex-range": "^2.1.0"
+        "to-regex-range": "^5.0.1"
       }
     },
     "finalhandler": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
-      "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
       "dev": true,
       "requires": {
         "debug": "2.6.9",
-        "encodeurl": "~1.0.1",
+        "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "on-finished": "~2.3.0",
-        "parseurl": "~1.3.2",
-        "statuses": "~1.3.1",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
         "unpipe": "~1.0.0"
-      },
-      "dependencies": {
-        "statuses": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
-          "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
-          "dev": true
-        }
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
       }
     },
     "flatted": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
-      "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
+      "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
       "dev": true
     },
     "follow-redirects": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
-      "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz",
+      "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==",
       "dev": true,
       "requires": {
-        "debug": "^3.2.6"
+        "debug": "^3.0.0"
       },
       "dependencies": {
         "debug": {
           }
         },
         "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         }
       }
     },
-    "for-in": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
-      "dev": true
-    },
     "forever-agent": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
         "mime-types": "^2.1.12"
       }
     },
-    "fragment-cache": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
-      "dev": true,
-      "requires": {
-        "map-cache": "^0.2.2"
-      }
-    },
     "fs-extra": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
       "dev": true
     },
     "fsevents": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.8.tgz",
-      "integrity": "sha512-tPvHgPGB7m40CZ68xqFGkKuzN+RnpGmSV+hgeKxhRpbxdqKXUFJGC3yonBOLzQBcJyGpdZFDfCsdOC2KFsXzeA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "nan": "^2.12.1",
-        "node-pre-gyp": "^0.12.0"
-      },
-      "dependencies": {
-        "abbrev": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "ansi-regex": {
-          "version": "2.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "aproba": {
-          "version": "1.2.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "are-we-there-yet": {
-          "version": "1.1.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "delegates": "^1.0.0",
-            "readable-stream": "^2.0.6"
-          }
-        },
-        "balanced-match": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "brace-expansion": {
-          "version": "1.1.11",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "balanced-match": "^1.0.0",
-            "concat-map": "0.0.1"
-          }
-        },
-        "chownr": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "code-point-at": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "concat-map": {
-          "version": "0.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "console-control-strings": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "core-util-is": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "debug": {
-          "version": "4.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "deep-extend": {
-          "version": "0.6.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "delegates": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "detect-libc": {
-          "version": "1.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "fs-minipass": {
-          "version": "1.2.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "^2.2.1"
-          }
-        },
-        "fs.realpath": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "gauge": {
-          "version": "2.7.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "aproba": "^1.0.3",
-            "console-control-strings": "^1.0.0",
-            "has-unicode": "^2.0.0",
-            "object-assign": "^4.1.0",
-            "signal-exit": "^3.0.0",
-            "string-width": "^1.0.1",
-            "strip-ansi": "^3.0.1",
-            "wide-align": "^1.1.0"
-          }
-        },
-        "glob": {
-          "version": "7.1.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "has-unicode": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "iconv-lite": {
-          "version": "0.4.24",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safer-buffer": ">= 2.1.2 < 3"
-          }
-        },
-        "ignore-walk": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimatch": "^3.0.4"
-          }
-        },
-        "inflight": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "once": "^1.3.0",
-            "wrappy": "1"
-          }
-        },
-        "inherits": {
-          "version": "2.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "ini": {
-          "version": "1.3.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "number-is-nan": "^1.0.0"
-          }
-        },
-        "isarray": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "minimatch": {
-          "version": "3.0.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        },
-        "minimist": {
-          "version": "0.0.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "minipass": {
-          "version": "2.3.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.0"
-          }
-        },
-        "minizlib": {
-          "version": "1.2.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "^2.2.1"
-          }
-        },
-        "mkdirp": {
-          "version": "0.5.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimist": "0.0.8"
-          }
-        },
-        "ms": {
-          "version": "2.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "needle": {
-          "version": "2.3.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "debug": "^4.1.0",
-            "iconv-lite": "^0.4.4",
-            "sax": "^1.2.4"
-          }
-        },
-        "node-pre-gyp": {
-          "version": "0.12.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "detect-libc": "^1.0.2",
-            "mkdirp": "^0.5.1",
-            "needle": "^2.2.1",
-            "nopt": "^4.0.1",
-            "npm-packlist": "^1.1.6",
-            "npmlog": "^4.0.2",
-            "rc": "^1.2.7",
-            "rimraf": "^2.6.1",
-            "semver": "^5.3.0",
-            "tar": "^4"
-          }
-        },
-        "nopt": {
-          "version": "4.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "abbrev": "1",
-            "osenv": "^0.1.4"
-          }
-        },
-        "npm-bundled": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "npm-packlist": {
-          "version": "1.4.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ignore-walk": "^3.0.1",
-            "npm-bundled": "^1.0.1"
-          }
-        },
-        "npmlog": {
-          "version": "4.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "are-we-there-yet": "~1.1.2",
-            "console-control-strings": "~1.1.0",
-            "gauge": "~2.7.3",
-            "set-blocking": "~2.0.0"
-          }
-        },
-        "number-is-nan": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "once": {
-          "version": "1.4.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "wrappy": "1"
-          }
-        },
-        "os-homedir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "os-tmpdir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "osenv": {
-          "version": "0.1.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "os-homedir": "^1.0.0",
-            "os-tmpdir": "^1.0.0"
-          }
-        },
-        "path-is-absolute": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "process-nextick-args": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "rc": {
-          "version": "1.2.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "deep-extend": "^0.6.0",
-            "ini": "~1.3.0",
-            "minimist": "^1.2.0",
-            "strip-json-comments": "~2.0.1"
-          },
-          "dependencies": {
-            "minimist": {
-              "version": "1.2.0",
-              "bundled": true,
-              "dev": true,
-              "optional": true
-            }
-          }
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "rimraf": {
-          "version": "2.6.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
-        "safe-buffer": {
-          "version": "5.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "safer-buffer": {
-          "version": "2.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "sax": {
-          "version": "1.2.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "semver": {
-          "version": "5.7.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "set-blocking": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "signal-exit": {
-          "version": "3.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "string-width": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "code-point-at": "^1.0.0",
-            "is-fullwidth-code-point": "^1.0.0",
-            "strip-ansi": "^3.0.0"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "strip-json-comments": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "tar": {
-          "version": "4.4.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chownr": "^1.1.1",
-            "fs-minipass": "^1.2.5",
-            "minipass": "^2.3.4",
-            "minizlib": "^1.1.1",
-            "mkdirp": "^0.5.0",
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.2"
-          }
-        },
-        "util-deprecate": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "wide-align": {
-          "version": "1.1.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "string-width": "^1.0.2 || 2"
-          }
-        },
-        "wrappy": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "yallist": {
-          "version": "3.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        }
-      }
-    },
-    "get-value": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
-      "dev": true
-    },
-    "getpass": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+      "dev": true,
+      "optional": true
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
       "dev": true,
       "requires": {
         "assert-plus": "^1.0.0"
       }
     },
     "glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "version": "7.1.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
       }
     },
     "glob-parent": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+      "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
       "dev": true,
       "requires": {
-        "is-glob": "^3.1.0",
-        "path-dirname": "^1.0.0"
-      },
-      "dependencies": {
-        "is-glob": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^2.1.0"
-          }
-        }
+        "is-glob": "^4.0.1"
       }
     },
     "graceful-fs": {
-      "version": "4.1.15",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
-      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+      "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
       "dev": true
     },
     "har-schema": {
       "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
       "dev": true
     },
-    "has-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
-      "dev": true,
-      "requires": {
-        "get-value": "^2.0.6",
-        "has-values": "^1.0.0",
-        "isobject": "^3.0.0"
-      }
-    },
-    "has-values": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
-      "dev": true,
-      "requires": {
-        "is-number": "^3.0.0",
-        "kind-of": "^4.0.0"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        }
-      }
-    },
     "hasha": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz",
       }
     },
     "http-errors": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
       "dev": true,
       "requires": {
         "depd": "~1.1.2",
         "inherits": "2.0.3",
-        "setprototypeof": "1.1.0",
-        "statuses": ">= 1.4.0 < 2"
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
       }
     },
     "http-proxy": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
-      "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+      "version": "1.18.1",
+      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+      "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
       "dev": true,
       "requires": {
-        "eventemitter3": "^3.0.0",
+        "eventemitter3": "^4.0.0",
         "follow-redirects": "^1.0.0",
         "requires-port": "^1.0.0"
       }
       }
     },
     "iconv-lite": {
-      "version": "0.4.23",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
-      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
       "dev": true,
       "requires": {
         "safer-buffer": ">= 2.1.2 < 3"
       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
       "dev": true
     },
-    "is-accessor-descriptor": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^3.0.2"
-      }
-    },
     "is-binary-path": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "^1.0.0"
-      }
-    },
-    "is-buffer": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
-      "dev": true
-    },
-    "is-data-descriptor": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^3.0.2"
-      }
-    },
-    "is-descriptor": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
       "dev": true,
       "requires": {
-        "is-accessor-descriptor": "^0.1.6",
-        "is-data-descriptor": "^0.1.4",
-        "kind-of": "^5.0.0"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-          "dev": true
-        }
+        "binary-extensions": "^2.0.0"
       }
     },
-    "is-extendable": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-      "dev": true
-    },
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
       "dev": true
     },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
+    },
     "is-glob": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
       "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
       "dev": true,
       "requires": {
-        "is-extglob": "^2.1.1"
-      }
-    },
-    "is-number": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-      "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^3.0.2"
-      }
-    },
-    "is-plain-object": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
-      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
-      "dev": true,
-      "requires": {
-        "isobject": "^3.0.1"
+        "is-extglob": "^2.1.1"
       }
     },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true
+    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
       "dev": true
     },
-    "is-windows": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
-      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
-      "dev": true
-    },
     "isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
       "dev": true
     },
     "isbinaryfile": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
-      "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
-      "dev": true,
-      "requires": {
-        "buffer-alloc": "^1.2.0"
-      }
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz",
+      "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==",
+      "dev": true
     },
     "isexe": {
       "version": "2.0.0",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
-    "isobject": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-      "dev": true
-    },
     "isstream": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
       }
     },
     "karma": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz",
-      "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==",
+      "version": "5.0.9",
+      "resolved": "https://registry.npmjs.org/karma/-/karma-5.0.9.tgz",
+      "integrity": "sha512-dUA5z7Lo7G4FRSe1ZAXqOINEEWxmCjDBbfRBmU/wYlSMwxUQJP/tEEP90yJt3Uqo03s9rCgVnxtlfq+uDhxSPg==",
       "dev": true,
       "requires": {
-        "bluebird": "^3.3.0",
-        "body-parser": "^1.16.1",
-        "braces": "^2.3.2",
-        "chokidar": "^2.0.3",
-        "colors": "^1.1.0",
-        "connect": "^3.6.0",
-        "core-js": "^2.2.0",
+        "body-parser": "^1.19.0",
+        "braces": "^3.0.2",
+        "chokidar": "^3.0.0",
+        "colors": "^1.4.0",
+        "connect": "^3.7.0",
         "di": "^0.0.1",
-        "dom-serialize": "^2.2.0",
-        "flatted": "^2.0.0",
-        "glob": "^7.1.1",
-        "graceful-fs": "^4.1.2",
-        "http-proxy": "^1.13.0",
-        "isbinaryfile": "^3.0.0",
-        "lodash": "^4.17.11",
-        "log4js": "^4.0.0",
-        "mime": "^2.3.1",
-        "minimatch": "^3.0.2",
-        "optimist": "^0.6.1",
-        "qjobs": "^1.1.4",
-        "range-parser": "^1.2.0",
-        "rimraf": "^2.6.0",
-        "safe-buffer": "^5.0.1",
-        "socket.io": "2.1.1",
+        "dom-serialize": "^2.2.1",
+        "flatted": "^2.0.2",
+        "glob": "^7.1.6",
+        "graceful-fs": "^4.2.4",
+        "http-proxy": "^1.18.1",
+        "isbinaryfile": "^4.0.6",
+        "lodash": "^4.17.15",
+        "log4js": "^6.2.1",
+        "mime": "^2.4.5",
+        "minimatch": "^3.0.4",
+        "qjobs": "^1.2.0",
+        "range-parser": "^1.2.1",
+        "rimraf": "^3.0.2",
+        "socket.io": "^2.3.0",
         "source-map": "^0.6.1",
-        "tmp": "0.0.33",
-        "useragent": "2.3.0"
+        "tmp": "0.2.1",
+        "ua-parser-js": "0.7.21",
+        "yargs": "^15.3.1"
       }
     },
     "karma-jasmine": {
       "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=",
       "dev": true
     },
-    "kind-of": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-      "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-      "dev": true,
-      "requires": {
-        "is-buffer": "^1.1.5"
-      }
-    },
     "klaw": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
         }
       }
     },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
     "lodash": {
       "version": "4.17.15",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
       "dev": true
     },
     "log4js": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.1.0.tgz",
-      "integrity": "sha512-eDa+zZPeVEeK6QGJAePyXM6pg4P3n3TO5rX9iZMVY48JshsTyLJZLIL5HipI1kQ2qLsSyOpUqNND/C5H4WhhiA==",
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz",
+      "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==",
       "dev": true,
       "requires": {
-        "date-format": "^2.0.0",
+        "date-format": "^3.0.0",
         "debug": "^4.1.1",
-        "flatted": "^2.0.0",
-        "rfdc": "^1.1.2",
-        "streamroller": "^1.0.4"
+        "flatted": "^2.0.1",
+        "rfdc": "^1.1.4",
+        "streamroller": "^2.2.4"
       },
       "dependencies": {
         "debug": {
           }
         },
         "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         }
       }
         "yallist": "^2.1.2"
       }
     },
-    "map-cache": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
-      "dev": true
-    },
-    "map-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
-      "dev": true,
-      "requires": {
-        "object-visit": "^1.0.0"
-      }
-    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
       "dev": true
     },
-    "micromatch": {
-      "version": "3.1.10",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-      "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-      "dev": true,
-      "requires": {
-        "arr-diff": "^4.0.0",
-        "array-unique": "^0.3.2",
-        "braces": "^2.3.1",
-        "define-property": "^2.0.2",
-        "extend-shallow": "^3.0.2",
-        "extglob": "^2.0.4",
-        "fragment-cache": "^0.2.1",
-        "kind-of": "^6.0.2",
-        "nanomatch": "^1.2.9",
-        "object.pick": "^1.3.0",
-        "regex-not": "^1.0.0",
-        "snapdragon": "^0.8.1",
-        "to-regex": "^3.0.2"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
-          "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.2",
-            "isobject": "^3.0.1"
-          }
-        },
-        "extend-shallow": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-          "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-          "dev": true,
-          "requires": {
-            "assign-symbols": "^1.0.0",
-            "is-extendable": "^1.0.1"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
     "mime": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz",
-      "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==",
+      "version": "2.4.6",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
+      "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==",
       "dev": true
     },
     "mime-db": {
         "brace-expansion": "^1.1.7"
       }
     },
-    "minimist": {
-      "version": "0.0.10",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
-      "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
-      "dev": true
-    },
-    "mixin-deep": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
-      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
-      "dev": true,
-      "requires": {
-        "for-in": "^1.0.2",
-        "is-extendable": "^1.0.1"
-      },
-      "dependencies": {
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        }
-      }
-    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
       "dev": true
     },
-    "nan": {
-      "version": "2.13.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
-      "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
-      "dev": true,
-      "optional": true
-    },
-    "nanomatch": {
-      "version": "1.2.13",
-      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
-      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
-      "dev": true,
-      "requires": {
-        "arr-diff": "^4.0.0",
-        "array-unique": "^0.3.2",
-        "define-property": "^2.0.2",
-        "extend-shallow": "^3.0.2",
-        "fragment-cache": "^0.2.1",
-        "is-windows": "^1.0.2",
-        "kind-of": "^6.0.2",
-        "object.pick": "^1.3.0",
-        "regex-not": "^1.0.0",
-        "snapdragon": "^0.8.1",
-        "to-regex": "^3.0.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
-          "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.2",
-            "isobject": "^3.0.1"
-          }
-        },
-        "extend-shallow": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-          "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-          "dev": true,
-          "requires": {
-            "assign-symbols": "^1.0.0",
-            "is-extendable": "^1.0.1"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
     "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
       "dev": true
     },
     "node-version": {
       "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
       "dev": true
     },
-    "object-copy": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
-      "dev": true,
-      "requires": {
-        "copy-descriptor": "^0.1.0",
-        "define-property": "^0.2.5",
-        "kind-of": "^3.0.3"
-      }
-    },
-    "object-visit": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
-      "dev": true,
-      "requires": {
-        "isobject": "^3.0.0"
-      }
-    },
-    "object.pick": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
-      "dev": true,
-      "requires": {
-        "isobject": "^3.0.1"
-      }
-    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
         "wrappy": "1"
       }
     },
-    "optimist": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
-      "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
       "dev": true,
       "requires": {
-        "minimist": "~0.0.1",
-        "wordwrap": "~0.0.2"
+        "p-try": "^2.0.0"
       }
     },
-    "os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
       "dev": true
     },
     "parseqs": {
       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
       "dev": true
     },
-    "pascalcase": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
-      "dev": true
-    },
-    "path-dirname": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
       "dev": true
     },
     "path-is-absolute": {
         "which": "^1.2.10"
       }
     },
+    "picomatch": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "dev": true
+    },
     "pinkie": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
         "pinkie": "^2.0.0"
       }
     },
-    "posix-character-classes": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
-      "dev": true
-    },
     "process-nextick-args": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
       "dev": true
     },
     "range-parser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
       "dev": true
     },
     "raw-body": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
-      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
       "dev": true,
       "requires": {
-        "bytes": "3.0.0",
-        "http-errors": "1.6.3",
-        "iconv-lite": "0.4.23",
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
         "unpipe": "1.0.0"
       }
     },
       }
     },
     "readdirp": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
-      "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.11",
-        "micromatch": "^3.1.10",
-        "readable-stream": "^2.0.2"
-      }
-    },
-    "regex-not": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
-      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+      "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
       "dev": true,
       "requires": {
-        "extend-shallow": "^3.0.2",
-        "safe-regex": "^1.1.0"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-          "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-          "dev": true,
-          "requires": {
-            "assign-symbols": "^1.0.0",
-            "is-extendable": "^1.0.1"
-          }
-        },
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        }
+        "picomatch": "^2.2.1"
       }
     },
-    "remove-trailing-separator": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
-      "dev": true
-    },
-    "repeat-element": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
-      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
-      "dev": true
-    },
-    "repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
-      "dev": true
-    },
     "request": {
       "version": "2.88.0",
       "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
     },
     "request-progress": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz",
-      "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=",
-      "dev": true,
-      "requires": {
-        "throttleit": "^1.0.0"
-      }
-    },
-    "requires-port": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
-      "dev": true
-    },
-    "resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
-      "dev": true
-    },
-    "ret": {
-      "version": "0.1.15",
-      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
-      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
-      "dev": true
-    },
-    "rfdc": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz",
-      "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==",
-      "dev": true
-    },
-    "rimraf": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
-      "dev": true,
-      "requires": {
-        "glob": "^7.1.3"
-      }
-    },
-    "safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
-    },
-    "safe-regex": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
-      "dev": true,
-      "requires": {
-        "ret": "~0.1.10"
-      }
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
-    },
-    "set-value": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
-      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "^2.0.1",
-        "is-extendable": "^0.1.1",
-        "is-plain-object": "^2.0.3",
-        "split-string": "^3.0.1"
-      }
-    },
-    "setprototypeof": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
-      "dev": true
-    },
-    "snapdragon": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
-      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
-      "dev": true,
-      "requires": {
-        "base": "^0.11.1",
-        "debug": "^2.2.0",
-        "define-property": "^0.2.5",
-        "extend-shallow": "^2.0.1",
-        "map-cache": "^0.2.2",
-        "source-map": "^0.5.6",
-        "source-map-resolve": "^0.5.0",
-        "use": "^3.1.0"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
-      }
-    },
-    "snapdragon-node": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
-      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
-      "dev": true,
-      "requires": {
-        "define-property": "^1.0.0",
-        "isobject": "^3.0.0",
-        "snapdragon-util": "^3.0.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.0"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
+      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz",
+      "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=",
+      "dev": true,
+      "requires": {
+        "throttleit": "^1.0.0"
       }
     },
-    "snapdragon-util": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
-      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
+    },
+    "require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "dev": true
+    },
+    "requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "dev": true
+    },
+    "rfdc": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
+      "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+      "dev": true
+    },
+    "rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
       "dev": true,
       "requires": {
-        "kind-of": "^3.2.0"
+        "glob": "^7.1.3"
       }
     },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
+    },
+    "setprototypeof": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+      "dev": true
+    },
     "socket.io": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
-      "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz",
+      "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==",
       "dev": true,
       "requires": {
-        "debug": "~3.1.0",
-        "engine.io": "~3.2.0",
+        "debug": "~4.1.0",
+        "engine.io": "~3.4.0",
         "has-binary2": "~1.0.2",
         "socket.io-adapter": "~1.1.0",
-        "socket.io-client": "2.1.1",
-        "socket.io-parser": "~3.2.0"
+        "socket.io-client": "2.3.0",
+        "socket.io-parser": "~3.4.0"
       },
       "dependencies": {
         "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
           }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
         }
       }
     },
     "socket.io-adapter": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
-      "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+      "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==",
       "dev": true
     },
     "socket.io-client": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
-      "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz",
+      "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==",
       "dev": true,
       "requires": {
         "backo2": "1.0.2",
         "base64-arraybuffer": "0.1.5",
         "component-bind": "1.0.0",
         "component-emitter": "1.2.1",
-        "debug": "~3.1.0",
-        "engine.io-client": "~3.2.0",
+        "debug": "~4.1.0",
+        "engine.io-client": "~3.4.0",
         "has-binary2": "~1.0.2",
         "has-cors": "1.1.0",
         "indexof": "0.0.1",
         "object-component": "0.0.3",
         "parseqs": "0.0.5",
         "parseuri": "0.0.5",
-        "socket.io-parser": "~3.2.0",
+        "socket.io-parser": "~3.3.0",
         "to-array": "0.1.4"
       },
       "dependencies": {
-        "component-emitter": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+        "debug": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "isarray": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+          "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
           "dev": true
         },
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        },
+        "socket.io-parser": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
+          "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "component-emitter": "1.2.1",
+            "debug": "~3.1.0",
+            "isarray": "2.0.1"
+          },
+          "dependencies": {
+            "debug": {
+              "version": "3.1.0",
+              "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+              "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+              "dev": true,
+              "requires": {
+                "ms": "2.0.0"
+              }
+            },
+            "ms": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+              "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+              "dev": true
+            }
           }
         }
       }
     },
     "socket.io-parser": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
-      "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz",
+      "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==",
       "dev": true,
       "requires": {
         "component-emitter": "1.2.1",
-        "debug": "~3.1.0",
+        "debug": "~4.1.0",
         "isarray": "2.0.1"
       },
       "dependencies": {
-        "component-emitter": {
-          "version": "1.2.1",
-          "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-          "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
-          "dev": true
-        },
         "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
-            "ms": "2.0.0"
+            "ms": "^2.1.1"
           }
         },
         "isarray": {
           "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
           "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
           "dev": true
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
         }
       }
     },
       "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
       "dev": true
     },
-    "source-map-resolve": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
-      "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
-      "dev": true,
-      "requires": {
-        "atob": "^2.1.1",
-        "decode-uri-component": "^0.2.0",
-        "resolve-url": "^0.2.1",
-        "source-map-url": "^0.4.0",
-        "urix": "^0.1.0"
-      }
-    },
-    "source-map-url": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
-      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
-      "dev": true
-    },
-    "split-string": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
-      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "^3.0.0"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-          "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-          "dev": true,
-          "requires": {
-            "assign-symbols": "^1.0.0",
-            "is-extendable": "^1.0.1"
-          }
-        },
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        }
-      }
-    },
     "sshpk": {
       "version": "1.15.2",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
         "tweetnacl": "~0.14.0"
       }
     },
-    "static-extend": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
-      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
-      "dev": true,
-      "requires": {
-        "define-property": "^0.2.5",
-        "object-copy": "^0.1.0"
-      }
-    },
     "statuses": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
       "dev": true
     },
     "streamroller": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.4.tgz",
-      "integrity": "sha512-Wc2Gm5ygjSX8ZpW9J7Y9FwiSzTlKSvcl0FTTMd3rn7RoxDXpBW+xD9TY5sWL2n0UR61COB0LG1BQvN6nTUQbLQ==",
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz",
+      "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==",
       "dev": true,
       "requires": {
-        "async": "^2.6.1",
-        "date-format": "^2.0.0",
-        "debug": "^3.1.0",
-        "fs-extra": "^7.0.0",
-        "lodash": "^4.17.10"
+        "date-format": "^2.1.0",
+        "debug": "^4.1.1",
+        "fs-extra": "^8.1.0"
       },
       "dependencies": {
+        "date-format": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
+          "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
+          "dev": true
+        },
         "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "dev": true,
           "requires": {
             "ms": "^2.1.1"
           }
         },
         "fs-extra": {
-          "version": "7.0.1",
-          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
-          "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+          "version": "8.1.0",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+          "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
           "dev": true,
           "requires": {
-            "graceful-fs": "^4.1.2",
+            "graceful-fs": "^4.2.0",
             "jsonfile": "^4.0.0",
             "universalify": "^0.1.0"
           }
           }
         },
         "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
           "dev": true
         }
       }
     },
+    "string-width": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+      "dev": true,
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
     "string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
         "safe-buffer": "~5.1.0"
       }
     },
+    "strip-ansi": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^5.0.0"
+      }
+    },
     "throttleit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
       "dev": true
     },
     "tmp": {
-      "version": "0.0.33",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+      "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
       "dev": true,
       "requires": {
-        "os-tmpdir": "~1.0.2"
+        "rimraf": "^3.0.0"
       }
     },
     "to-array": {
       "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
       "dev": true
     },
-    "to-object-path": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
-      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^3.0.2"
-      }
-    },
-    "to-regex": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
-      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
-      "dev": true,
-      "requires": {
-        "define-property": "^2.0.2",
-        "extend-shallow": "^3.0.2",
-        "regex-not": "^1.0.2",
-        "safe-regex": "^1.1.0"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "2.0.2",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
-          "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "^1.0.2",
-            "isobject": "^3.0.1"
-          }
-        },
-        "extend-shallow": {
-          "version": "3.0.2",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-          "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
-          "dev": true,
-          "requires": {
-            "assign-symbols": "^1.0.0",
-            "is-extendable": "^1.0.1"
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-extendable": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
-          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
-          "dev": true,
-          "requires": {
-            "is-plain-object": "^2.0.4"
-          }
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
     "to-regex-range": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
-      "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
       "dev": true,
       "requires": {
-        "is-number": "^3.0.0",
-        "repeat-string": "^1.6.1"
+        "is-number": "^7.0.0"
       }
     },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+      "dev": true
+    },
     "tough-cookie": {
       "version": "2.4.3",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
       "dev": true
     },
     "type-is": {
-      "version": "1.6.16",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
-      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
       "dev": true,
       "requires": {
         "media-typer": "0.3.0",
-        "mime-types": "~2.1.18"
+        "mime-types": "~2.1.24"
+      },
+      "dependencies": {
+        "mime-db": {
+          "version": "1.44.0",
+          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+          "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
+          "dev": true
+        },
+        "mime-types": {
+          "version": "2.1.27",
+          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+          "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+          "dev": true,
+          "requires": {
+            "mime-db": "1.44.0"
+          }
+        }
       }
     },
     "typedarray": {
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
-    "ultron": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
-      "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+    "ua-parser-js": {
+      "version": "0.7.21",
+      "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
+      "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==",
       "dev": true
     },
-    "union-value": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
-      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
-      "dev": true,
-      "requires": {
-        "arr-union": "^3.1.0",
-        "get-value": "^2.0.6",
-        "is-extendable": "^0.1.1",
-        "set-value": "^2.0.1"
-      }
-    },
     "universalify": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
       "dev": true
     },
-    "unset-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
-      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
-      "dev": true,
-      "requires": {
-        "has-value": "^0.3.1",
-        "isobject": "^3.0.0"
-      },
-      "dependencies": {
-        "has-value": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
-          "dev": true,
-          "requires": {
-            "get-value": "^2.0.3",
-            "has-values": "^0.1.4",
-            "isobject": "^2.0.0"
-          },
-          "dependencies": {
-            "isobject": {
-              "version": "2.1.0",
-              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-              "dev": true,
-              "requires": {
-                "isarray": "1.0.0"
-              }
-            }
-          }
-        },
-        "has-values": {
-          "version": "0.1.4",
-          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
-          "dev": true
-        }
-      }
-    },
-    "upath": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
-      "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
-      "dev": true
-    },
     "uri-js": {
       "version": "4.2.2",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
         "punycode": "^2.1.0"
       }
     },
-    "urix": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
-      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
-      "dev": true
-    },
-    "use": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
-      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
-      "dev": true
-    },
-    "useragent": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
-      "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
-      "dev": true,
-      "requires": {
-        "lru-cache": "4.1.x",
-        "tmp": "0.0.x"
-      }
-    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
         "isexe": "^2.0.0"
       }
     },
-    "wordwrap": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
-      "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+    "which-module": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
       "dev": true
     },
+    "wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "dev": true
     },
     "ws": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
-      "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
-      "dev": true,
-      "requires": {
-        "async-limiter": "~1.0.0",
-        "safe-buffer": "~5.1.0",
-        "ultron": "~1.1.0"
-      }
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
+      "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==",
+      "dev": true
     },
     "xmlhttprequest-ssl": {
       "version": "1.5.5",
       "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
       "dev": true
     },
+    "y18n": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+      "dev": true
+    },
     "yallist": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
       "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
       "dev": true
     },
+    "yargs": {
+      "version": "15.3.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
+      "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
+      "dev": true,
+      "requires": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.1"
+      }
+    },
+    "yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dev": true,
+      "requires": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      }
+    },
     "yauzl": {
       "version": "2.4.1",
       "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
index f3abb57f5282386ce243dae0e67c6ada01e53810..0dffff7c40da0bc0639d66a2164f6ef73b58e234 100644 (file)
@@ -12,7 +12,7 @@
     "bower": "^1.8.8",
     "civicrm-cv": "^0.1.2",
     "jasmine-core": "~3.3.0",
-    "karma": "^4.1.0",
+    "karma": "^5.0.9",
     "karma-jasmine": "~2.0.1",
     "karma-ng-html2js-preprocessor": "^1.0.0",
     "karma-phantomjs-launcher": "^1.0.4"
index a8dc3579860b2e9571e33c2ffa12b253a7684de6..f9e14af53c7b7e99d8ceea39bda8d3d004c0d770 100644 (file)
@@ -15,6 +15,17 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 5.26.0
+
+Released June 3, 2020
+
+- **[Synopsis](release-notes/5.26.0.md#synopsis)**
+- **[Features](release-notes/5.26.0.md#features)**
+- **[Bugs resolved](release-notes/5.26.0.md#bugs)**
+- **[Miscellany](release-notes/5.26.0.md#misc)**
+- **[Credits](release-notes/5.26.0.md#credits)**
+- **[Feedback](release-notes/5.26.0.md#feedback)**
+
 ## CiviCRM 5.25.0
 
 Released May 6, 2020
diff --git a/release-notes/5.26.0.md b/release-notes/5.26.0.md
new file mode 100644 (file)
index 0000000..b49dc57
--- /dev/null
@@ -0,0 +1,459 @@
+# CiviCRM 5.26.0
+
+Released June 3, 2020
+
+- **[Synopsis](#synopsis)**
+- **[Features](#features)**
+- **[Bugs resolved](#bugs)**
+- **[Miscellany](#misc)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="features"></a>Features
+
+## <a name="bugs"></a>Bugs resolved
+
+### Core CiviCRM
+
+- **dev/core#1784 fix regression on restore contacts button not working. ([17418](https://github.com/civicrm/civicrm-core/pull/17418))**
+
+- **Fixes a regression when cancelling a recurring with no processor_id ([17292](https://github.com/civicrm/civicrm-core/pull/17292))**
+
+- **Remove "page=CiviCRM" query string from WordPress front-end (5.26) ([17352](https://github.com/civicrm/civicrm-core/pull/17352))**
+
+- **Revert "[REF] Code readability changes on activity tokens." ([17365](https://github.com/civicrm/civicrm-core/pull/17365))**
+
+- **[REF] Fix install on Drupal 8 using new setup code ([17334](https://github.com/civicrm/civicrm-core/pull/17334))**
+
+- **dev/core#1681 Add in deprecation notice for Systems using MySQL versions before 5.7 and require 5.5 for install ([17261](https://github.com/civicrm/civicrm-core/pull/17261))**
+
+- **[regression] Fix error on no MIME type ([17265](https://github.com/civicrm/civicrm-core/pull/17265))**
+
+- **SyntaxConformanceTest::testSqlOperators - Fix failure on MySQL 8 ([17262](https://github.com/civicrm/civicrm-core/pull/17262))**
+
+- **Add workflow_name column to civicrm_msg_template, deprecate workflow_id ([17227](https://github.com/civicrm/civicrm-core/pull/17227))**
+
+- **[NFC/Test] - Fix typo in `if` statement that seems intended as a workaround ([17258](https://github.com/civicrm/civicrm-core/pull/17258))**
+
+- **5.25 ([17252](https://github.com/civicrm/civicrm-core/pull/17252))**
+
+- **E2E_Core_HookTest - Fix test failure due to leak ([17251](https://github.com/civicrm/civicrm-core/pull/17251))**
+
+- **5.25 ([17248](https://github.com/civicrm/civicrm-core/pull/17248))**
+
+- **5.25 ([17243](https://github.com/civicrm/civicrm-core/pull/17243))**
+
+- **dev/core#1739 Enable Longitude on Address editing by default (option 12) ([17238](https://github.com/civicrm/civicrm-core/pull/17238))**
+
+- **APIv4 - Fix schema map to use canonical field names ([17239](https://github.com/civicrm/civicrm-core/pull/17239))**
+
+- **(REF) dev/core#1744 - Cleanup event naming ([17240](https://github.com/civicrm/civicrm-core/pull/17240))**
+
+- **5.25 ([17236](https://github.com/civicrm/civicrm-core/pull/17236))**
+
+- **dev/core#1742 Expose CiviCRM Database details for views configuration… ([17232](https://github.com/civicrm/civicrm-core/pull/17232))**
+
+- **[REF] [Test] IDE cleanup on ReportTemplateTest ([17197](https://github.com/civicrm/civicrm-core/pull/17197))**
+
+- **Reporting #20 - correct stats when force=1 on Contribution Detail Report ([17234](https://github.com/civicrm/civicrm-core/pull/17234))**
+
+- **[REF] Simplify non-creditcard participant.create ([16584](https://github.com/civicrm/civicrm-core/pull/16584))**
+
+- **dev/core#57 On Behalf Of fails to populate in Email Receipt ([17026](https://github.com/civicrm/civicrm-core/pull/17026))**
+
+- **APIv4 - Deprecate option_value joins and display notices in Explorer ([17235](https://github.com/civicrm/civicrm-core/pull/17235))**
+
+- **(REF,NFC) TokenProcessor - Minor DX improvements ([17231](https://github.com/civicrm/civicrm-core/pull/17231))**
+
+- **[REF] Permit domain tokens being used within Thank You letters ([17230](https://github.com/civicrm/civicrm-core/pull/17230))**
+
+- **Convert fatals to statusBounces in case forms ([17212](https://github.com/civicrm/civicrm-core/pull/17212))**
+
+- **(REF) CRM_Utils_Hook - Remove deprecated formulations of `invoke(int,…)` ([17124](https://github.com/civicrm/civicrm-core/pull/17124))**
+
+- **dev/core#1460, dev/core#1713 - Categorical fix for upgrade<=>hook issues ([17126](https://github.com/civicrm/civicrm-core/pull/17126))**
+
+- **Allow override of inherited CMS language when in CiviCRM ([17006](https://github.com/civicrm/civicrm-core/pull/17006))**
+
+- **dev/mail#62 - Mailing Error when civicrm_mailing_group has duplicate … ([17130](https://github.com/civicrm/civicrm-core/pull/17130))**
+
+- **[REF] Switch CRM_Utils_Array::value to empty in conditionals ([17091](https://github.com/civicrm/civicrm-core/pull/17091))**
+
+- **Further removal of long-deprecated skipCleanMoney ([17175](https://github.com/civicrm/civicrm-core/pull/17175))**
+
+- **[REF] Minor code cleanup ([17225](https://github.com/civicrm/civicrm-core/pull/17225))**
+
+- **APIv4 - Deprecate old way of retrieving activityType/optionValue ids ([17219](https://github.com/civicrm/civicrm-core/pull/17219))**
+
+- **[REF] Minor code cleanup. ([17222](https://github.com/civicrm/civicrm-core/pull/17222))**
+
+- **[NFC] Test cleanup ([17224](https://github.com/civicrm/civicrm-core/pull/17224))**
+
+- **Fix admin page url for "conference slots" option values ([17223](https://github.com/civicrm/civicrm-core/pull/17223))**
+
+- **5.25 ([17221](https://github.com/civicrm/civicrm-core/pull/17221))**
+
+- **dev/core#1460 - Small cleanups in CiviEventDispatcher{,Test} ([17216](https://github.com/civicrm/civicrm-core/pull/17216))**
+
+- **5.25 ([17217](https://github.com/civicrm/civicrm-core/pull/17217))**
+
+- **[REF] Reduce boilerplate code in BAO add/create functions ([17172](https://github.com/civicrm/civicrm-core/pull/17172))**
+
+- **[REF] Minor cleanup around action schedule code. ([17151](https://github.com/civicrm/civicrm-core/pull/17151))**
+
+- **[NFC][Test] Preliminary cleanup ([17213](https://github.com/civicrm/civicrm-core/pull/17213))**
+
+- **Cleanup and throw exceptions in OpenCase form ([17184](https://github.com/civicrm/civicrm-core/pull/17184))**
+
+- **(NFC) Remove $Id$ artifacts from old SCM ([17211](https://github.com/civicrm/civicrm-core/pull/17211))**
+
+- **Cleanup core pseudoconstant buildOptions ([17122](https://github.com/civicrm/civicrm-core/pull/17122))**
+
+- **APIv4 - Allow field options to be returned in multiple formats ([17167](https://github.com/civicrm/civicrm-core/pull/17167))**
+
+- **[REF] Cleanup a few instances where we use old call to get loggedInUserID ([17196](https://github.com/civicrm/civicrm-core/pull/17196))**
+
+- **5.25 ([17209](https://github.com/civicrm/civicrm-core/pull/17209))**
+
+- **5.25 ([17207](https://github.com/civicrm/civicrm-core/pull/17207))**
+
+- **5.25 ([17201](https://github.com/civicrm/civicrm-core/pull/17201))**
+
+- **Move batch-form support code back to the form ([17176](https://github.com/civicrm/civicrm-core/pull/17176))**
+
+- **[REF] Simplify determination of enabled components ([17195](https://github.com/civicrm/civicrm-core/pull/17195))**
+
+- **5.25 ([17199](https://github.com/civicrm/civicrm-core/pull/17199))**
+
+- **[REF] stop overriding postProcess function in activity report detail ([17194](https://github.com/civicrm/civicrm-core/pull/17194))**
+
+- **[REF] Reconcile CRM_Utils_System::getUrlPath and CRM_Utils_System::currentPath ([17068](https://github.com/civicrm/civicrm-core/pull/17068))**
+
+- **Fix Dedupe entity_tag mangling bug ([17125](https://github.com/civicrm/civicrm-core/pull/17125))**
+
+- **Add contribution source to recurring contribution report ([17187](https://github.com/civicrm/civicrm-core/pull/17187))**
+
+- **Gitlab issue template - Ask for link to stackexchange or chat conversations ([17186](https://github.com/civicrm/civicrm-core/pull/17186))**
+
+- **Remove deprecated calls to optionValueQuery and no-longer-need param ([17182](https://github.com/civicrm/civicrm-core/pull/17182))**
+
+- **Show email receipt status on view recurring contribution ([17177](https://github.com/civicrm/civicrm-core/pull/17177))**
+
+- **dev/core#1460 - CiviEventDispatcher - Add policy options ([17127](https://github.com/civicrm/civicrm-core/pull/17127))**
+
+- **Switch cc field on emailTrait to use entity reference ([17129](https://github.com/civicrm/civicrm-core/pull/17129))**
+
+- **show title on status message instead machine name ([17174](https://github.com/civicrm/civicrm-core/pull/17174))**
+
+- **dev/wp#46 - Remove styling that attempts to make inputs match select2 ([16882](https://github.com/civicrm/civicrm-core/pull/16882))**
+
+- **Refactor api3 Payment.Get API to support options + most fields in civicrm_financial_trxn ([17071](https://github.com/civicrm/civicrm-core/pull/17071))**
+
+- **5.25 to master ([17173](https://github.com/civicrm/civicrm-core/pull/17173))**
+
+- **Remove unused parameter, immediately overwritten parameter ([17131](https://github.com/civicrm/civicrm-core/pull/17131))**
+
+- **Do not create smarty cached templates for processed greetings ([16733](https://github.com/civicrm/civicrm-core/pull/16733))**
+
+- **5.25 ([17171](https://github.com/civicrm/civicrm-core/pull/17171))**
+
+- **OptionValue - Use DB defaults instead of setting them in BAO::add ([17170](https://github.com/civicrm/civicrm-core/pull/17170))**
+
+- **[REF] APIv4 - Enforce contact field permissions via metadata ([17168](https://github.com/civicrm/civicrm-core/pull/17168))**
+
+- **Add contribution id as activity source record when downloading or emailing invoice ([17165](https://github.com/civicrm/civicrm-core/pull/17165))**
+
+- **Correct option_group pseudoconstant and regenerate dao ([17166](https://github.com/civicrm/civicrm-core/pull/17166))**
+
+- **[REF] Code readability changes on activity tokens. ([17161](https://github.com/civicrm/civicrm-core/pull/17161))**
+
+- **Less svn ([17159](https://github.com/civicrm/civicrm-core/pull/17159))**
+
+- **[REF] Minor extraction ([17160](https://github.com/civicrm/civicrm-core/pull/17160))**
+
+- **OptionValues - Munge custom value names and return names in validate context ([17158](https://github.com/civicrm/civicrm-core/pull/17158))**
+
+- **[NFC] Superficial code clean up ([17155](https://github.com/civicrm/civicrm-core/pull/17155))**
+
+- **[NFC] A bit less svn in our code ([17157](https://github.com/civicrm/civicrm-core/pull/17157))**
+
+- **[REF] Consistently lookup dispatcher via `Civi::dispatcher()` ([17154](https://github.com/civicrm/civicrm-core/pull/17154))**
+
+- **Convert test to use APIV4 in setup for cleaner code ([17153](https://github.com/civicrm/civicrm-core/pull/17153))**
+
+- **[NFC] [Test] minor code cleanup ([17152](https://github.com/civicrm/civicrm-core/pull/17152))**
+
+- **dev/core#1705 APIv4 - Support pseudoconstant lookups ([17138](https://github.com/civicrm/civicrm-core/pull/17138))**
+
+- **5.25 ([17150](https://github.com/civicrm/civicrm-core/pull/17150))**
+
+- **[NFC] Cleanup CRM_Report_Form ([17141](https://github.com/civicrm/civicrm-core/pull/17141))**
+
+- **Update more Portugal provinces ([17136](https://github.com/civicrm/civicrm-core/pull/17136))**
+
+- **5.25 ([17139](https://github.com/civicrm/civicrm-core/pull/17139))**
+
+- **(NFC) Comment clarification in test class ([17133](https://github.com/civicrm/civicrm-core/pull/17133))**
+
+- **dev/core#1684 - Use PSR-4 autoloader instead of PSR-0 for "Civi" namespace ([17105](https://github.com/civicrm/civicrm-core/pull/17105))**
+
+- **Add contributor email address to cancelSubscription form so it is cle… ([16716](https://github.com/civicrm/civicrm-core/pull/16716))**
+
+- **dev/user-interface#19 - Remove leftover description text on contribution form mistakenly left in ([17135](https://github.com/civicrm/civicrm-core/pull/17135))**
+
+- **5.25 ([17123](https://github.com/civicrm/civicrm-core/pull/17123))**
+
+- **dev/core#1718 membership batch entry join date fix ([17099](https://github.com/civicrm/civicrm-core/pull/17099))**
+
+- **Convert bcc field to use an entity reference. ([17064](https://github.com/civicrm/civicrm-core/pull/17064))**
+
+- **[REF] Minor var simplification ([17121](https://github.com/civicrm/civicrm-core/pull/17121))**
+
+- **Update Colmbra state/province to Coimbra ([17106](https://github.com/civicrm/civicrm-core/pull/17106))**
+
+- **APIv4 - Prevent field alias conflicts. ([17109](https://github.com/civicrm/civicrm-core/pull/17109))**
+
+- **Restore #16947 - APIv4 support for sql functions and grouping ([17113](https://github.com/civicrm/civicrm-core/pull/17113))**
+
+- **5.25 ([17111](https://github.com/civicrm/civicrm-core/pull/17111))**
+
+- **[NFC] Remove calculation of unused parameter ([17093](https://github.com/civicrm/civicrm-core/pull/17093))**
+
+- **[REF] Remove duplicate checks for an array key existing ([17069](https://github.com/civicrm/civicrm-core/pull/17069))**
+
+- **[REF] Import - extract duplicate code to function ([17080](https://github.com/civicrm/civicrm-core/pull/17080))**
+
+- **(NFC) Gitlab Template - Request more detail about upgrade problems ([17101](https://github.com/civicrm/civicrm-core/pull/17101))**
+
+- **Replace CaseType's own XML encoding function ([17100](https://github.com/civicrm/civicrm-core/pull/17100))**
+
+- **Remove unused parameter from function ([17098](https://github.com/civicrm/civicrm-core/pull/17098))**
+
+- **Remove outputHeader as a param for writeCSVFile as it is always true ([17051](https://github.com/civicrm/civicrm-core/pull/17051))**
+
+- **Remove var that is defined on parent ([17102](https://github.com/civicrm/civicrm-core/pull/17102))**
+
+- **[REF] Stop passing ids to membership::create from createRelatedMemberships ([17087](https://github.com/civicrm/civicrm-core/pull/17087))**
+
+- **Don't pass empty ids parameter, fix fatal ([17086](https://github.com/civicrm/civicrm-core/pull/17086))**
+
+- **[REF] get rid of variable variable structure ([17089](https://github.com/civicrm/civicrm-core/pull/17089))**
+
+- **Introduce "civi.dao.preUpdate" and "civi.dao.preInsert" events ([16714](https://github.com/civicrm/civicrm-core/pull/16714))**
+
+- **5.25 ([17095](https://github.com/civicrm/civicrm-core/pull/17095))**
+
+- **5.25 ([17092](https://github.com/civicrm/civicrm-core/pull/17092))**
+
+- **[REF] SavedSearch - additional cleanup & bugfixes ([17090](https://github.com/civicrm/civicrm-core/pull/17090))**
+
+- **[NFC] Remove all the places where tests unnecessarily pass  to Membership::create ([17088](https://github.com/civicrm/civicrm-core/pull/17088))**
+
+- **Add MessageTemplate api to v4 ([17073](https://github.com/civicrm/civicrm-core/pull/17073))**
+
+- **Archive text ([17074](https://github.com/civicrm/civicrm-core/pull/17074))**
+
+- **[REF] APIv4 Explorer - improve performance ([17062](https://github.com/civicrm/civicrm-core/pull/17062))**
+
+- **5.25 ([17083](https://github.com/civicrm/civicrm-core/pull/17083))**
+
+- **Fix 'selectedChild' parameter for pages with tabs ([17066](https://github.com/civicrm/civicrm-core/pull/17066))**
+
+- **Add ID to custom group/field admin forms ([17055](https://github.com/civicrm/civicrm-core/pull/17055))**
+
+- **Export: use X icon `fa-times` for closing things ([17076](https://github.com/civicrm/civicrm-core/pull/17076))**
+
+- **[NFC] Improve cleanup on membershipStatus to cope with undeleted memberships ([16756](https://github.com/civicrm/civicrm-core/pull/16756))**
+
+- **Follow up fix on change to merge sqls ([17077](https://github.com/civicrm/civicrm-core/pull/17077))**
+
+- **dev/core#1693 inline text title override ([16998](https://github.com/civicrm/civicrm-core/pull/16998))**
+
+- **[NFC] Remove a handful of legacy svn notations ([17070](https://github.com/civicrm/civicrm-core/pull/17070))**
+
+- **Dupe improve custom data handling ([17060](https://github.com/civicrm/civicrm-core/pull/17060))**
+
+- **APIv4 - Fix setting offset with no limit ([17063](https://github.com/civicrm/civicrm-core/pull/17063))**
+
+- **[REF] move all functions associated with  the submit function onto the Trait ([17057](https://github.com/civicrm/civicrm-core/pull/17057))**
+
+- **[NFC] Code cleanup around comments, strict comparison, formatting ([17058](https://github.com/civicrm/civicrm-core/pull/17058))**
+
+- **Improve AngularJS performance with one-time binding for static strings ([17050](https://github.com/civicrm/civicrm-core/pull/17050))**
+
+- **Duplicate EmailCommon::buildQuickForm onto the trait ([17052](https://github.com/civicrm/civicrm-core/pull/17052))**
+
+- **Make transaction param optional in completeOrder ([17053](https://github.com/civicrm/civicrm-core/pull/17053))**
+
+- **[Test] Extend custom field test trait & some related tests ([17037](https://github.com/civicrm/civicrm-core/pull/17037))**
+
+- **fixed mapping when using custom field for contact sub type ([16957](https://github.com/civicrm/civicrm-core/pull/16957))**
+
+- **[NFC] Fix use of pattern-hated-by-Coleman ([17049](https://github.com/civicrm/civicrm-core/pull/17049))**
+
+- **add filter for receipt date in contribution reports ([17044](https://github.com/civicrm/civicrm-core/pull/17044))**
+
+- **dev/translation#4 - Refine upgrade steps for modifying nl_NL ([17048](https://github.com/civicrm/civicrm-core/pull/17048))**
+
+- **Fix bug where tax_amount is miscalculated on membership renewals ([16772](https://github.com/civicrm/civicrm-core/pull/16772))**
+
+- **dev/report#31 - Api4 Explorer: Support SQL functions and HAVING clause ([17047](https://github.com/civicrm/civicrm-core/pull/17047))**
+
+- **Update 5.24.2.md - Fix version number in title. ([17043](https://github.com/civicrm/civicrm-core/pull/17043))**
+
+- **core#1700 - Fix Financial ACL Report check ([17046](https://github.com/civicrm/civicrm-core/pull/17046))**
+
+- **dev/translation#4 - Upgrade script for nl_BE ([17027](https://github.com/civicrm/civicrm-core/pull/17027))**
+
+- **Simplify groupContactCache - remove redundant query ([17011](https://github.com/civicrm/civicrm-core/pull/17011))**
+
+- **Add missing translations to case activity revisions ([16987](https://github.com/civicrm/civicrm-core/pull/16987))**
+
+- **dev/core#1696 - Update attachment message on mailing form. ([17024](https://github.com/civicrm/civicrm-core/pull/17024))**
+
+- **set is_deceased to not null in schema and upgrade script dev/core#1697 ([17025](https://github.com/civicrm/civicrm-core/pull/17025))**
+
+- **Mitigate flaky test failure about "CRM_Utils_Check_Component_Env->checkVersion()" ([17038](https://github.com/civicrm/civicrm-core/pull/17038))**
+
+- **Allow adding variables to CRM.vars in any region ([16888](https://github.com/civicrm/civicrm-core/pull/16888))**
+
+- **5.25 ([17042](https://github.com/civicrm/civicrm-core/pull/17042))**
+
+- **[REF] Extract transferParticipantRegistration function ([16976](https://github.com/civicrm/civicrm-core/pull/16976))**
+
+- **Allow setting metadata to use the `table` option. Update example setting `default_invoice_page`. ([16903](https://github.com/civicrm/civicrm-core/pull/16903))**
+
+- **Add / make fit for purpose email.getlist api call ([16993](https://github.com/civicrm/civicrm-core/pull/16993))**
+
+- **REF Remove redundant param from completeOrder ([17034](https://github.com/civicrm/civicrm-core/pull/17034))**
+
+- **[REF] Update Contact email form to use the trait for EmailCommon functions ([17031](https://github.com/civicrm/civicrm-core/pull/17031))**
+
+- **5.25 ([17035](https://github.com/civicrm/civicrm-core/pull/17035))**
+
+- **APIv4 - Add support for HAVING clause ([17015](https://github.com/civicrm/civicrm-core/pull/17015))**
+
+- **[REF] Move generic instances of listTokens to trait ([17029](https://github.com/civicrm/civicrm-core/pull/17029))**
+
+- **Add email link in case summary ([16959](https://github.com/civicrm/civicrm-core/pull/16959))**
+
+- **Start using apiv4 in test setup ([17020](https://github.com/civicrm/civicrm-core/pull/17020))**
+
+- **Mailing Report: hide the HTML preview ([16899](https://github.com/civicrm/civicrm-core/pull/16899))**
+
+- **[NFC][Test] cleanup on customDataTrait for tests ([17022](https://github.com/civicrm/civicrm-core/pull/17022))**
+
+- **[REF] Move generic preProcess function to the trait ([16954](https://github.com/civicrm/civicrm-core/pull/16954))**
+
+- **5.25  to master ([17023](https://github.com/civicrm/civicrm-core/pull/17023))**
+
+- **[NFC] Minor code cleanups ([17019](https://github.com/civicrm/civicrm-core/pull/17019))**
+
+- **dev/core#1659: Fix Case.get API returning Case Clients As Part of Related Contacts ([16837](https://github.com/civicrm/civicrm-core/pull/16837))**
+
+- **5.25 ([17018](https://github.com/civicrm/civicrm-core/pull/17018))**
+
+- **[REF] Clarify variable & tighten use. ([17016](https://github.com/civicrm/civicrm-core/pull/17016))**
+
+- **[REF] Use bool instead of boolean ([17013](https://github.com/civicrm/civicrm-core/pull/17013))**
+
+- **[REF] Formatting and use bool instead of boolean ([17012](https://github.com/civicrm/civicrm-core/pull/17012))**
+
+- **[REF] CustomField code cleanup to use isSerialized method ([17009](https://github.com/civicrm/civicrm-core/pull/17009))**
+
+- **[REF] CustomField code cleanup ([16968](https://github.com/civicrm/civicrm-core/pull/16968))**
+
+- **[NFC][Test] Minor cleanup in test class ([17002](https://github.com/civicrm/civicrm-core/pull/17002))**
+
+- **[REF] Cleanup customField prepareCreate function ([16996](https://github.com/civicrm/civicrm-core/pull/16996))**
+
+- **dev/core#1673 Ensure that SQL statements are not duplicated in the de… ([17001](https://github.com/civicrm/civicrm-core/pull/17001))**
+
+- **[NFC] Add Comment to avoid someone removing field only used in CiviCase extension ([17000](https://github.com/civicrm/civicrm-core/pull/17000))**
+
+- **[REF] Update custom data handing in contact import ([16986](https://github.com/civicrm/civicrm-core/pull/16986))**
+
+- **Fix setting custom field TextArea attributes ([16997](https://github.com/civicrm/civicrm-core/pull/16997))**
+
+- **add filter and sorting for receipt date in contribution report ([16994](https://github.com/civicrm/civicrm-core/pull/16994))**
+
+- **Case Details field is empty ([16995](https://github.com/civicrm/civicrm-core/pull/16995))**
+
+- **Fix bug on handling 'is_required' ([16901](https://github.com/civicrm/civicrm-core/pull/16901))**
+
+- **dev/core#1685 - Search builder returns DB error on Group => Empty filter ([16953](https://github.com/civicrm/civicrm-core/pull/16953))**
+
+- **Fix values passed to tokenValues hook ([16623](https://github.com/civicrm/civicrm-core/pull/16623))**
+
+- **[REF] Cleanup custom field handling... twice ([16989](https://github.com/civicrm/civicrm-core/pull/16989))**
+
+- **Cleanup custom field handling in ufGroup BAO ([16984](https://github.com/civicrm/civicrm-core/pull/16984))**
+
+- **[REF] Cleanup CustomField BAO to use its own isSerialized function ([16990](https://github.com/civicrm/civicrm-core/pull/16990))**
+
+- **5.25 ([16988](https://github.com/civicrm/civicrm-core/pull/16988))**
+
+- **Fix multiselect/checkbox custom field defaults on contribution online form ([16991](https://github.com/civicrm/civicrm-core/pull/16991))**
+
+- **Fix multiselect/checkbox custom field defaults on registration profile ([16981](https://github.com/civicrm/civicrm-core/pull/16981))**
+
+- **[REF] Call makeCSVTable function directly from writeRows ([16980](https://github.com/civicrm/civicrm-core/pull/16980))**
+
+- **Use isSerialized function rather guessing from html_type ([16979](https://github.com/civicrm/civicrm-core/pull/16979))**
+
+- **dev/translation#4 - Add nl_BE language ([16966](https://github.com/civicrm/civicrm-core/pull/16966))**
+
+- **[REF] CustomGroup - cleanup handling of serialized fields in old function ([16970](https://github.com/civicrm/civicrm-core/pull/16970))**
+
+- **[REF] CustomField - Remove pointless caching and move form variable to form class ([16975](https://github.com/civicrm/civicrm-core/pull/16975))**
+
+- **Capitalise PAN truncation ([16973](https://github.com/civicrm/civicrm-core/pull/16973))**
+
+- **5.25 ([16974](https://github.com/civicrm/civicrm-core/pull/16974))**
+
+- **[REF] Update XML file to match updated title in DAO File ([16969](https://github.com/civicrm/civicrm-core/pull/16969))**
+
+- **Code cleanup - replace overcomplicated test for null with isset ([16965](https://github.com/civicrm/civicrm-core/pull/16965))**
+
+- **Update FinancialTrxn.php ([16964](https://github.com/civicrm/civicrm-core/pull/16964))**
+
+- **5.25 ([16962](https://github.com/civicrm/civicrm-core/pull/16962))**
+
+- **Fix WordPress support for Get UF Locale ([16700](https://github.com/civicrm/civicrm-core/pull/16700))**
+
+- **dev/wordpress#49 Prevent 301 redirects if 'page=CiviCRM' ([199](https://github.com/civicrm/civicrm-wordpress/pull/199))**
+
+- **dev/wordpress#52 Accept empty string as q|qid for the REST endpoint civicrm/v3/url ([195](https://github.com/civicrm/civicrm-wordpress/pull/195))**
+
+- **dev/wordpress#53 Replace tracking URLs only if mail content is replaceable ([196](https://github.com/civicrm/civicrm-wordpress/pull/196))**
+
+- **Remove "page=CiviCRM" query string from WordPress front-end (5.26) ([194](https://github.com/civicrm/civicrm-wordpress/pull/194))**
+
+- **Support Clean URLs when using Polylang ([191](https://github.com/civicrm/civicrm-wordpress/pull/191))**
+
+- **Revert "Support polylang language prefixes with clean URLs" ([189](https://github.com/civicrm/civicrm-wordpress/pull/189))**
+
+- **Support polylang language prefixes with clean URLs ([176](https://github.com/civicrm/civicrm-wordpress/pull/176))**
+
+- **[REF] CRM_Utils_Array::value -> empty ([288](https://github.com/civicrm/civicrm-packages/pull/288))**
+
+- **5.25 ([290](https://github.com/civicrm/civicrm-packages/pull/290))**
+
+## <a name="misc"></a>Miscellany
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following code authors:
+
+a-n The Artists Information Company - William Mortada; AGH Strategies - Alice Frumin, Andrew Hunt; Andrei Mondoc; Christian Wach; Circle Interactive - Dave Jenkins, Pradeep Nayak; CiviCRM - Coleman Watts, Josh Gowans, Tim Otten; CiviDesk - Yashodha Chaku; Coop SymbioTIC - Mathieu Lutfy; Dave D; Fuzion - Jitendra Purohit; Greenpeace Central and Eastern Europe - Patrick Figel; GuillaumeSorel; ivan-compucorp; JMA Consulting - Seamus Lee; Lighthouse Design and Consulting - Brian Shaughnessy; Megaphone Technology Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; Ray Wright; Third Sector Design - Michael McAndrew; Timbsoft Technologies - Tunbola Ogunwande; Wikimedia Foundation - Eileen McNaughton
+
+Most authors also reviewed code for this release; in addition, the following
+reviewers contributed their comments:
+
+a-n The Artists Information Company - William Mortada; AGH Strategies - Alice Frumin, Andrew Hunt; Andrei Mondoc; Andrew Cormick-Dockery; andyburnsco; Artful Robot - Rich Lott; Blackfly Solutions - Alan Dixon; Christian Wach; Circle Interactive - Pradeep Nayak; civibot[bot]; CiviCoop - Jaap Jansma; civicrm-builder; CiviCRM - Coleman Watts, Tim Otten; CiviDesk - Yashodha Chaku; Coop SymbioTIC - Mathieu Lutfy; Dave D; Fuzion - Jitendra Purohit, Peter Davis; GMCVO Databases - Jade Gaunt; Greenpeace Central and Eastern Europe - Patrick Figel; JMA Consulting - Monish Deb, Seamus Lee; Megaphone Technology Consulting - Jon Goldberg; MJCO - Mikey O'Toole; MJW Consulting - Matthew Wire; Ray Wright; Richard van Oosterhout; Squiffle Consulting - Aidan Saunders; Tadpole Collective - Kevin Cristiano; Team Expansion - Greg Harris; Third Sector Design - Michael McAndrew; Timbsoft Technologies - Tunbola Ogunwande; Wikimedia Foundation - Eileen McNaughton
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Alice Frumin and Andrew Hunt.  If you'd like
+to provide feedback on them, please log in to https://chat.civicrm.org/civicrm
+and contact `@agh1`.
index 74e5e2f186621f32b9a11c0bd64c901ccec90dea..c193513b621c196485a25791a05b835b89032e9b 100644 (file)
@@ -12,7 +12,7 @@
 <div class="help">
   <div class="icon inform-icon"></div>&nbsp;
   {$cancelRecurDetailText}
-  {if !$cancelSupported}
+  {if $cancelRecurNotSupportedText}
     <div class="status-warning">{$cancelRecurNotSupportedText}</div>
   {/if}
 </div>
index 1606ab1f7141666c4c76ef1d9d6b12070e4541d5..8dff8bcfc3a1ad38e76464a790f3f9e9538da5c6 100644 (file)
@@ -1158,9 +1158,7 @@ class CRM_Activity_BAO_ActivityTest extends CiviUnitTestCase {
     $contactId = $this->individualCreate();
 
     // create a logged in USER since the code references it for sendEmail user.
-    $this->createLoggedInUser();
-    $session = CRM_Core_Session::singleton();
-    $loggedInUser = $session->get('userID');
+    $loggedInUser = $this->createLoggedInUser();
 
     $contact = $this->civicrm_api('contact', 'getsingle', ['id' => $contactId, 'version' => $this->_apiversion]);
     $contactDetailsIntersectKeys = [
index e65c333d7eae90ea9bde1f7e7dcf44ffdd288140..dad354ae1794472a5fd1ab6b3b4a077da8e85047 100644 (file)
@@ -149,6 +149,53 @@ class CRM_Activity_Form_ActivityTest extends CiviUnitTestCase {
     $this->assertTargetActivityIds($expectedActivityIds);
   }
 
+  /**
+   * Test deleting an activity that has an attachment.
+   */
+  public function testActivityDeleteWithAttachment() {
+    $loggedInUser = $this->createLoggedInUser();
+    // Create an activity
+    $activity = $this->callAPISuccess('Activity', 'create', [
+      'source_contact_id' => $loggedInUser,
+      'activity_type_id' => 'Meeting',
+      'subject' => 'test with attachment',
+      'status_id' => 'Completed',
+      'target_id' => $this->target,
+    ]);
+    $this->assertNotEmpty($activity['id']);
+
+    // Add an attachment - this will also create it in the filesystem.
+    $attachment = $this->callAPISuccess('Attachment', 'create', [
+      'name' => 'abc.txt',
+      'mime_type' => 'text/plain',
+      'entity_id' => $activity['id'],
+      'entity_table' => 'civicrm_activity',
+      'content' => 'delete me',
+    ]);
+    $this->assertNotEmpty($attachment['id']);
+
+    // Check the file is actually there
+    $file_path = $attachment['values'][$attachment['id']]['path'];
+    $this->assertTrue(file_exists($file_path));
+
+    // Call our local helper function to use the form to delete
+    $this->deleteActivity($activity['id']);
+
+    // File should be gone from the filesystem
+    $this->assertFalse(file_exists($file_path), "File is still in filesystem $file_path");
+
+    // Shouldn't be an entry in civicrm_entity_file
+    $query_params = [1 => [$activity['id'], 'Integer']];
+    $entity_file_id = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_entity_file WHERE entity_table='civicrm_activity' AND entity_id = %1", $query_params);
+    $this->assertEmpty($entity_file_id, 'Entry is still in civicrm_entity_file table.');
+
+    // In this situation there also shouldn't be an entry in civicrm_file since
+    // there's no other references to it.
+    $query_params = [1 => [$attachment['id'], 'Integer']];
+    $file_id = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_file WHERE id = %1", $query_params);
+    $this->assertEmpty($file_id, 'Entry is still in civicrm_file table.');
+  }
+
   /**
    * Asserts that the target contact has the expected activity IDs
    *
diff --git a/tests/phpunit/CRM/Contact/Form/Task/DeleteTest.php b/tests/phpunit/CRM/Contact/Form/Task/DeleteTest.php
new file mode 100644 (file)
index 0000000..35d8790
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+ /**
+  * @group headless
+  */
+class CRM_Contact_Form_Task_DeleteTest extends CiviUnitTestCase {
+
+  /**
+   * @var int
+   * The contact we are deleting and resurrecting.
+   */
+  protected $deleted_contact_id;
+
+  protected function setUp() {
+    parent::setUp();
+    $this->deleted_contact_id = $this->individualCreate([
+      'first_name' => 'Delete',
+      'last_name' => 'Me',
+      'prefix_id' => 3,
+      'suffix_id' => NULL,
+    ]);
+  }
+
+  protected function tearDown() {
+    $this->quickCleanup([
+      'civicrm_contact',
+    ]);
+
+    parent::tearDown();
+  }
+
+  /**
+   * Test delete to trash.
+   */
+  public function testDeleteToTrash() {
+    $old_undelete_setting = Civi::settings()->get('contact_undelete');
+    Civi::settings()->set('contact_undelete', '1');
+
+    $form = $this->getFormObject('CRM_Contact_Form_Task_Delete');
+    $form->set('cid', $this->deleted_contact_id);
+    $form->preProcess();
+    $form->buildQuickForm();
+    $form->setDefaultValues();
+    $form->postProcess();
+
+    $query_params = [1 => [$this->deleted_contact_id, 'Integer']];
+    $is_deleted = CRM_Core_DAO::singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = %1", $query_params);
+    $this->assertEquals(1, $is_deleted);
+
+    $session_status = CRM_Core_Session::singleton()->getStatus();
+    $this->assertEquals('Mr. Delete Me has been moved to the trash.', $session_status[0]['text']);
+
+    // put settings back
+    Civi::settings()->set('contact_undelete', $old_undelete_setting);
+  }
+
+  /**
+   * Test restore from trash.
+   */
+  public function testRestoreFromTrash() {
+    // First, put in trash.
+    $this->testDeleteToTrash();
+    // Clear session status
+    CRM_Core_Session::singleton()->getStatus(TRUE);
+
+    $old_undelete_setting = Civi::settings()->get('contact_undelete');
+    Civi::settings()->set('contact_undelete', '1');
+
+    $form = $this->getFormObject('CRM_Contact_Form_Task_Delete');
+    $form->set('cid', $this->deleted_contact_id);
+    $form->set('restore', '1');
+    $form->preProcess();
+    $form->buildQuickForm();
+    $form->setDefaultValues();
+    $form->postProcess();
+
+    $query_params = [1 => [$this->deleted_contact_id, 'Integer']];
+    $is_deleted = CRM_Core_DAO::singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = %1", $query_params);
+    $this->assertEquals(0, $is_deleted);
+
+    $session_status = CRM_Core_Session::singleton()->getStatus();
+    $this->assertEquals('Mr. Delete Me has been restored from the trash.', $session_status[0]['text']);
+
+    // put settings back
+    Civi::settings()->set('contact_undelete', $old_undelete_setting);
+  }
+
+  /**
+   * Test delete permanently.
+   *
+   * This is different from testDeleteWithoutTrash. This is where you have
+   * trash enabled and first move to trash, then delete from the trash.
+   */
+  public function testDeletePermanently() {
+    // First, put in trash.
+    $this->testDeleteToTrash();
+    // Clear session status
+    CRM_Core_Session::singleton()->getStatus(TRUE);
+
+    $old_undelete_setting = Civi::settings()->get('contact_undelete');
+    Civi::settings()->set('contact_undelete', '1');
+
+    $form = $this->getFormObject('CRM_Contact_Form_Task_Delete');
+    $form->set('cid', $this->deleted_contact_id);
+    $form->set('skip_undelete', '1');
+    $form->preProcess();
+    $form->buildQuickForm();
+    $form->setDefaultValues();
+    $form->postProcess();
+
+    $query_params = [1 => [$this->deleted_contact_id, 'Integer']];
+    $contact_id = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_contact WHERE id = %1", $query_params);
+    $this->assertEmpty($contact_id);
+
+    $session_status = CRM_Core_Session::singleton()->getStatus();
+    $this->assertEquals('Mr. Delete Me has been permanently deleted.', $session_status[0]['text']);
+
+    // put settings back
+    Civi::settings()->set('contact_undelete', $old_undelete_setting);
+  }
+
+  /**
+   * Test delete when trash is not enabled.
+   *
+   * This is different from testDeletePermanently. This is where trash is
+   * not enabled at all.
+   */
+  public function testDeleteWithoutTrash() {
+    $old_undelete_setting = Civi::settings()->get('contact_undelete');
+    Civi::settings()->set('contact_undelete', '0');
+
+    $form = $this->getFormObject('CRM_Contact_Form_Task_Delete');
+    $form->set('cid', $this->deleted_contact_id);
+    $form->preProcess();
+    $form->buildQuickForm();
+    $form->setDefaultValues();
+    $form->postProcess();
+
+    $query_params = [1 => [$this->deleted_contact_id, 'Integer']];
+    $contact_id = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_contact WHERE id = %1", $query_params);
+    $this->assertEmpty($contact_id);
+
+    // @todo This is currently buggy in the UI. It deletes properly but shows
+    // the wrong message.
+    //$session_status = CRM_Core_Session::singleton()->getStatus();
+    //$this->assertEquals('Mr. Delete Me has been permanently deleted.', $session_status[0]['text']);
+
+    // put settings back
+    Civi::settings()->set('contact_undelete', $old_undelete_setting);
+  }
+
+}
index 8ad69d1efd23083385b8b042fca7f35d2bd00a4e..4065e734f678b5e7f10ad6dc50dc6e0668a160a8 100644 (file)
  */
 class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
 
+  use \Civi\Test\GuzzleTestTrait;
+
+  /**
+   * @var \CRM_Core_Payment_AuthorizeNet
+   */
+  protected $processor;
+
   public function setUp() {
     parent::setUp();
     $this->_paymentProcessorID = $this->paymentProcessorAuthorizeNetCreate();
@@ -37,12 +44,15 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
    * Test works but not both due to some form of caching going on in the SmartySingleton
    */
   public function testCreateSingleNowDated() {
-    $firstName = 'John_' . substr(sha1(rand()), 0, 7) . uniqid();
-    $lastName = 'Smith_' . substr(sha1(rand()), 0, 7) . uniqid();
-    $nameParams = ['first_name' => $firstName, 'last_name' => $lastName];
+    $this->createMockHandler([$this->getExpectedResponse()]);
+    $this->setUpClientWithHistoryContainer();
+    $this->processor->setGuzzleClient($this->getGuzzleClient());
+    $firstName = 'John';
+    $lastName = 'Smith';
+    $nameParams = ['first_name' => 'John', 'last_name' => $lastName];
     $contactId = $this->individualCreate($nameParams);
 
-    $invoiceID = sha1(rand());
+    $invoiceID = 123456;
     $amount = rand(100, 1000) . '.00';
 
     $recur = $this->callAPISuccess('ContributionRecur', 'create', [
@@ -76,7 +86,7 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'qfKey' => '08ed21c7ca00a1f7d32fff2488596ef7_4454',
       'hidden_CreditCard' => 1,
       'billing_first_name' => $firstName,
-      'billing_middle_name' => "",
+      'billing_middle_name' => '',
       'billing_last_name' => $lastName,
       'billing_street_address-5' => '8 Hobbitton Road',
       'billing_city-5' => 'The Shire',
@@ -96,14 +106,14 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'installments' => 12,
       'financial_type_id' => $this->_financialTypeId,
       'is_email_receipt' => 1,
-      'from_email_address' => "{$firstName}.{$lastName}@example.com",
+      'from_email_address' => 'john.smith@example.com',
       'receive_date' => date('Ymd'),
       'receipt_date_time' => '',
       'payment_processor_id' => $this->_paymentProcessorID,
       'price_set_id' => '',
       'total_amount' => $amount,
       'currency' => 'USD',
-      'source' => "Mordor",
+      'source' => 'Mordor',
       'soft_credit_to' => '',
       'soft_contact_id' => '',
       'billing_state_province-5' => 'IL',
@@ -116,20 +126,20 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
       'amount' => 7,
       'amount_level' => 0,
       'currencyID' => 'USD',
-      'pcp_display_in_roll' => "",
-      'pcp_roll_nickname' => "",
-      'pcp_personal_note' => "",
-      'non_deductible_amount' => "",
-      'fee_amount' => "",
-      'net_amount' => "",
+      'pcp_display_in_roll' => '',
+      'pcp_roll_nickname' => '',
+      'pcp_personal_note' => '',
+      'non_deductible_amount' => '',
+      'fee_amount' => '',
+      'net_amount' => '',
       'invoiceID' => $invoiceID,
-      'contribution_page_id' => "",
+      'contribution_page_id' => '',
       'thankyou_date' => NULL,
       'honor_contact_id' => NULL,
       'first_name' => $firstName,
       'middle_name' => '',
       'last_name' => $lastName,
-      'street_address' => '8 Hobbiton Road' . uniqid(),
+      'street_address' => '8 Hobbiton Road',
       'city' => 'The Shire',
       'state_province' => 'IL',
       'postal_code' => 5010,
@@ -160,6 +170,17 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     $message = '';
     $result = $this->processor->cancelSubscription($message, ['subscriptionId' => $subscriptionID]);
     $this->assertTrue($result, 'Failed to cancel subscription with Authorize.');
+
+    $requests = $this->getRequestBodies();
+    $this->assertEquals($this->getExpectedRequest(date('Y-m-d')), $requests[0]);
+    $header = $this->getRequestHeaders()[0];
+    $this->assertEquals(['apitest.authorize.net'], $header['Host']);
+    $this->assertEquals(['text/xml; charset=UTF8'], $header['Content-Type']);
+
+    $this->assertEquals([
+      CURLOPT_RETURNTRANSFER => TRUE,
+      CURLOPT_SSL_VERIFYPEER => Civi::settings()->get('verifySSL'),
+    ], $this->container[0]['options']['curl']);
   }
 
   /**
@@ -320,4 +341,65 @@ class CRM_Core_Payment_AuthorizeNetTest extends CiviUnitTestCase {
     }
   }
 
+  /**
+   * Get the content that we expect to see sent out.
+   *
+   * @param string $startDate
+   *
+   * @return string
+   */
+  public function getExpectedRequest($startDate) {
+    return '<?xml version="1.0" encoding="utf-8"?>
+<ARBCreateSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
+  <merchantAuthentication>
+    <name>4y5BfuW7jm</name>
+    <transactionKey>4cAmW927n8uLf5J8</transactionKey>
+  </merchantAuthentication>
+  <refId>123456</refId>
+  <subscription>
+        <paymentSchedule>
+      <interval>
+        <length>1</length>
+        <unit>months</unit>
+      </interval>
+      <startDate>' . $startDate . '</startDate>
+      <totalOccurrences>12</totalOccurrences>
+    </paymentSchedule>
+    <amount>7</amount>
+    <payment>
+      <creditCard>
+        <cardNumber>4444333322221111</cardNumber>
+        <expirationDate>2025-09</expirationDate>
+      </creditCard>
+    </payment>
+      <order>
+     <invoiceNumber>1</invoiceNumber>
+        </order>
+       <customer>
+      <id>3</id>
+      <email>John.Smith@example.com</email>
+    </customer>
+    <billTo>
+      <firstName>John</firstName>
+      <lastName>Smith</lastName>
+      <address>8 Hobbiton Road</address>
+      <city>The Shire</city>
+      <state>IL</state>
+      <zip>5010</zip>
+      <country>US</country>
+    </billTo>
+  </subscription>
+</ARBCreateSubscriptionRequest>
+';
+  }
+
+  /**
+   * Get a successful response to setting up a recurring.
+   *
+   * @return string
+   */
+  public function getExpectedResponse() {
+    return '<?xml version="1.0" encoding="utf-8"?><ARBCreateSubscriptionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><refId>8d468ca1b1dd5c2b56c7</refId><messages><resultCode>Ok</resultCode><message><code>I00001</code><text>Successful.</text></message></messages><subscriptionId>6632052</subscriptionId><profile><customerProfileId>1512023280</customerProfileId><customerPaymentProfileId>1512027350</customerPaymentProfileId></profile></ARBCreateSubscriptionResponse>';
+  }
+
 }
index a5c22596d7797c9402099f42d30833618bbc9e91..7aa516ebd47191325edffd2845efe2448739e9d9 100644 (file)
@@ -316,4 +316,20 @@ class api_v3_FinancialTypeACLTest extends CiviUnitTestCase {
     $this->assertEquals($contribution['count'], 1);
   }
 
+  public function testMembersipTypeACLFinancialTypeACL() {
+    $contactID = $this->individualCreate();
+    $this->contactMembershipCreate(['contact_id' => $contactID]);
+    $this->enableFinancialACLs();
+    $this->setPermissions([
+      'access CiviCRM',
+      'access CiviContribute',
+      'view all contacts',
+      'add contributions of type Donation',
+      'view contributions of type Donation',
+    ]);
+    $this->assertEquals(0, CRM_Member_BAO_Membership::getContactMembershipCount($contactID));
+    $this->addFinancialAclPermissions([['view', 'Member Dues']]);
+    $this->assertEquals(1, CRM_Member_BAO_Membership::getContactMembershipCount($contactID));
+  }
+
 }
index 47a623054846f76c078f8c5ebaac8dd1522e1c87..0007eefaf2fe76a2ca347cc4221a357c54a1b49e 100644 (file)
@@ -43,6 +43,7 @@
     <uniqueName>membership_type</uniqueName>
     <title>Membership Type</title>
     <type>varchar</type>
+    <required>true</required>
     <import>true</import>
     <length>128</length>
     <localizable>true</localizable>