Split CRM_Utils_Address::vcard into 2 functions
authorEileen McNaughton <emcnaughton@wikimedia.org>
Fri, 8 Dec 2023 03:43:26 +0000 (16:43 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Fri, 8 Dec 2023 07:46:12 +0000 (20:46 +1300)
CRM/Core/BAO/Address.php
CRM/Utils/Address.php

index 1489b5ca670f8a6dadaeac12f8e1b1a24c0030d4..cb0d95e66c8d5d51e806912154ca088633b624b3 100644 (file)
@@ -471,9 +471,13 @@ class CRM_Core_BAO_Address extends CRM_Core_DAO_Address implements Civi\Core\Hoo
     else {
       $fields['county'] = NULL;
     }
-
-    $this->display = CRM_Utils_Address::format($fields, NULL, $microformat);
-    $this->display_text = CRM_Utils_Address::format($fields);
+    if ($microformat) {
+      $this->display = CRM_Utils_Address::formatVCard($fields);
+      $this->display_text = CRM_Utils_Address::format($fields);
+    }
+    else {
+      $this->display = $this->display_text = CRM_Utils_Address::format($fields);
+    }
   }
 
   /**
index 2b79d40a599bc00fa777718797b5509ed2ebd09c..91f89f082264ee3e6e87ab4b29714818b56c9971 100644 (file)
@@ -47,7 +47,10 @@ class CRM_Utils_Address {
     $unused = FALSE,
     $tokenFields = NULL
   ) {
-
+    if ($microformat) {
+      CRM_Core_Error::deprecatedFunctionWarning('CRM_Utils_Address::formatVCard (not recommended outside core - figure out a token way)');
+      self::formatVCard($fields);
+    }
     if (!$format) {
       $format = Civi::settings()->get('address_format');
     }
@@ -58,6 +61,123 @@ class CRM_Utils_Address {
       $fullPostalCode .= '-' . $fields['postal_code_suffix'];
     }
 
+    $replacements = [
+      'contact.display_name' => $fields['display_name'] ?? NULL,
+      'contact.formal_title' => $fields['formal_title'] ?? NULL,
+      'contact.first_name' => $fields['first_name'] ?? NULL,
+      'contact.middle_name' => $fields['middle_name'] ?? NULL,
+      'contact.last_name' => $fields['last_name'] ?? NULL,
+      'contact.individual_prefix' => $fields['prefix_id:label'] ?? ($fields['individual_prefix'] ?? NULL),
+      'contact.prefix_id:label' => $fields['prefix_id:label'] ?? ($fields['individual_prefix'] ?? NULL),
+      'contact.individual_suffix' => $fields['suffix_id:label'] ?? ($fields['individual_suffix'] ?? NULL),
+      'contact.suffix_id:label' => $fields['suffix_id:label'] ?? ($fields['individual_suffix'] ?? NULL),
+      'contact.address_name' => $fields['address_name'] ?? NULL,
+      'contact.street_address' => $fields['street_address'] ?? NULL,
+      'contact.supplemental_address_1' => $fields['supplemental_address_1'] ?? NULL,
+      'contact.supplemental_address_2' => $fields['supplemental_address_2'] ?? NULL,
+      'contact.supplemental_address_3' => $fields['supplemental_address_3'] ?? NULL,
+      'contact.city' => $fields['city'] ?? NULL,
+      'contact.state_province_name' => $fields['state_province_id:label'] ?? ($fields['state_province_name'] ?? NULL),
+      'contact.county' => $fields['county_id:label'] ?? ($fields['county'] ?? NULL),
+      'contact.state_province' => $fields['state_province_id:label'] ?? ($fields['state_province'] ?? NULL),
+      'contact.postal_code' => $fullPostalCode,
+      'contact.country' => $fields['country_id:label'] ?? ($fields['country'] ?? NULL),
+      'contact.world_region' => $fields['world_region'] ?? NULL,
+      'contact.geo_code_1' => $fields['geo_code_1'] ?? NULL,
+      'contact.geo_code_2' => $fields['geo_code_2'] ?? NULL,
+      'contact.current_employer' => $fields['current_employer'] ?? NULL,
+      'contact.nick_name' => $fields['nick_name'] ?? NULL,
+      'contact.email' => $fields['email'] ?? NULL,
+      'contact.im' => $fields['im'] ?? NULL,
+      'contact.do_not_email' => $fields['do_not_email'] ?? NULL,
+      'contact.do_not_phone' => $fields['do_not_phone'] ?? NULL,
+      'contact.do_not_mail' => $fields['do_not_mail'] ?? NULL,
+      'contact.do_not_sms' => $fields['do_not_sms'] ?? NULL,
+      'contact.do_not_trade' => $fields['do_not_trade'] ?? NULL,
+      'contact.job_title' => $fields['job_title'] ?? NULL,
+      'contact.birth_date' => $fields['birth_date'] ?? NULL,
+      'contact.gender' => $fields['gender'] ?? NULL,
+      'contact.is_opt_out' => $fields['is_opt_out'] ?? NULL,
+      'contact.phone' => $fields['phone'] ?? NULL,
+      'contact.home_URL' => $fields['home_URL'] ?? NULL,
+      'contact.contact_source' => $fields['contact_source'] ?? NULL,
+      'contact.external_identifier' => $fields['external_identifier'] ?? NULL,
+      'contact.contact_id' => $fields['id'] ?? NULL,
+      'contact.household_name' => $fields['household_name'] ?? NULL,
+      'contact.organization_name' => $fields['organization_name'] ?? NULL,
+      'contact.legal_name' => $fields['legal_name'] ?? NULL,
+      'contact.preferred_communication_method' => $fields['preferred_communication_method'] ?? NULL,
+      'contact.communication_style' => $fields['communication_style'] ?? NULL,
+      'contact.addressee' => $fields['addressee_display'] ?? NULL,
+      'contact.email_greeting' => $fields['email_greeting_display'] ?? NULL,
+      'contact.postal_greeting' => $fields['postal_greeting_display'] ?? NULL,
+    ];
+
+    // replacements in case of Custom Token
+    if (stristr(($formatted ?? ''), 'custom_')) {
+      $customToken = array_keys($fields);
+      foreach ($customToken as $value) {
+        if (substr($value, 0, 7) == 'custom_') {
+          $replacements["contact.{$value}"] = $fields["{$value}"];
+        }
+      }
+    }
+
+    // also sub all token fields
+    if ($tokenFields) {
+      foreach ($tokenFields as $token) {
+        $replacements["{$token}"] = $fields["{$token}"] ?? NULL;
+      }
+    }
+
+    // for every token, replace {fooTOKENbar} with fooVALUEbar if
+    // the value is not empty, otherwise drop the whole {fooTOKENbar}
+    foreach ($replacements as $token => $value) {
+      if ($value && is_string($value) || is_numeric($value)) {
+        $formatted = preg_replace("/{([^{}]*)\b{$token}\b([^{}]*)}/u", "\${1}{$value}\${2}", ($formatted ?? ''));
+      }
+      else {
+        $formatted = preg_replace("/{[^{}]*\b{$token}\b[^{}]*}/u", '', ($formatted ?? ''));
+      }
+    }
+
+    $formatted = "\n$formatted\n";
+
+    $formatted = preg_replace('/\n{[^{}]*}/u', "\n", $formatted);
+    $formatted = preg_replace('/{[^{}]*}\n/u', "\n", $formatted);
+
+    // if there are any 'sibling' {...} constructs, replace them with the
+    // contents of the first one; for example, when there's no state_province:
+    // 1. {city}{, }{state_province}{ }{postal_code}
+    // 2. San Francisco{, }{ }12345
+    // 3. San Francisco, 12345
+    $formatted = preg_replace('/{([^{}]*)}({[^{}]*})+/u', '\1', $formatted);
+
+    // drop any remaining curly braces leaving their contents
+    $formatted = str_replace(['{', '}'], '', $formatted);
+
+    // drop any empty lines left after the replacements
+    $formatted = preg_replace('/^[ \t]*[\r\n]+/m', '', $formatted);
+    return $formatted;
+  }
+
+  /**
+   * Format an address in the vcard format.
+   *
+   * @param array $fields
+   *   The address fields.
+   *
+   * @return string
+   *   formatted address string
+   */
+  public static function formatVCard($fields) {
+    $formatted = Civi::settings()->get('address_format');
+
+    $fullPostalCode = $fields['postal_code'] ?? NULL;
+    if (!empty($fields['postal_code_suffix'])) {
+      $fullPostalCode .= '-' . $fields['postal_code_suffix'];
+    }
+
     // make sure that some of the fields do have values
     $emptyFields = [
       'supplemental_address_1',
@@ -72,87 +192,31 @@ class CRM_Utils_Address {
       }
     }
 
-    if (!$microformat) {
-      // replacements in case of Individual Name Format
-      $replacements = [
-        'contact.display_name' => $fields['display_name'] ?? NULL,
-        'contact.formal_title' => $fields['formal_title'] ?? NULL,
-        'contact.first_name' => $fields['first_name'] ?? NULL,
-        'contact.middle_name' => $fields['middle_name'] ?? NULL,
-        'contact.last_name' => $fields['last_name'] ?? NULL,
-        'contact.individual_prefix' => $fields['prefix_id:label'] ?? ($fields['individual_prefix'] ?? NULL),
-        'contact.prefix_id:label' => $fields['prefix_id:label'] ?? ($fields['individual_prefix'] ?? NULL),
-        'contact.individual_suffix' => $fields['suffix_id:label'] ?? ($fields['individual_suffix'] ?? NULL),
-        'contact.suffix_id:label' => $fields['suffix_id:label'] ?? ($fields['individual_suffix'] ?? NULL),
-        'contact.address_name' => $fields['address_name'] ?? NULL,
-        'contact.street_address' => $fields['street_address'] ?? NULL,
-        'contact.supplemental_address_1' => $fields['supplemental_address_1'] ?? NULL,
-        'contact.supplemental_address_2' => $fields['supplemental_address_2'] ?? NULL,
-        'contact.supplemental_address_3' => $fields['supplemental_address_3'] ?? NULL,
-        'contact.city' => $fields['city'] ?? NULL,
-        'contact.state_province_name' => $fields['state_province_id:label'] ?? ($fields['state_province_name'] ?? NULL),
-        'contact.county' => $fields['county_id:label'] ?? ($fields['county'] ?? NULL),
-        'contact.state_province' => $fields['state_province_id:label'] ?? ($fields['state_province'] ?? NULL),
-        'contact.postal_code' => $fullPostalCode,
-        'contact.country' => $fields['country_id:label'] ?? ($fields['country'] ?? NULL),
-        'contact.world_region' => $fields['world_region'] ?? NULL,
-        'contact.geo_code_1' => $fields['geo_code_1'] ?? NULL,
-        'contact.geo_code_2' => $fields['geo_code_2'] ?? NULL,
-        'contact.current_employer' => $fields['current_employer'] ?? NULL,
-        'contact.nick_name' => $fields['nick_name'] ?? NULL,
-        'contact.email' => $fields['email'] ?? NULL,
-        'contact.im' => $fields['im'] ?? NULL,
-        'contact.do_not_email' => $fields['do_not_email'] ?? NULL,
-        'contact.do_not_phone' => $fields['do_not_phone'] ?? NULL,
-        'contact.do_not_mail' => $fields['do_not_mail'] ?? NULL,
-        'contact.do_not_sms' => $fields['do_not_sms'] ?? NULL,
-        'contact.do_not_trade' => $fields['do_not_trade'] ?? NULL,
-        'contact.job_title' => $fields['job_title'] ?? NULL,
-        'contact.birth_date' => $fields['birth_date'] ?? NULL,
-        'contact.gender' => $fields['gender'] ?? NULL,
-        'contact.is_opt_out' => $fields['is_opt_out'] ?? NULL,
-        'contact.phone' => $fields['phone'] ?? NULL,
-        'contact.home_URL' => $fields['home_URL'] ?? NULL,
-        'contact.contact_source' => $fields['contact_source'] ?? NULL,
-        'contact.external_identifier' => $fields['external_identifier'] ?? NULL,
-        'contact.contact_id' => $fields['id'] ?? NULL,
-        'contact.household_name' => $fields['household_name'] ?? NULL,
-        'contact.organization_name' => $fields['organization_name'] ?? NULL,
-        'contact.legal_name' => $fields['legal_name'] ?? NULL,
-        'contact.preferred_communication_method' => $fields['preferred_communication_method'] ?? NULL,
-        'contact.communication_style' => $fields['communication_style'] ?? NULL,
-        'contact.addressee' => $fields['addressee_display'] ?? NULL,
-        'contact.email_greeting' => $fields['email_greeting_display'] ?? NULL,
-        'contact.postal_greeting' => $fields['postal_greeting_display'] ?? NULL,
-      ];
-    }
-    else {
-      $replacements = [
-        'contact.address_name' => "<span class=\"address-name\">" . $fields['address_name'] . "</span>",
-        'contact.street_address' => "<span class=\"street-address\">" . $fields['street_address'] . "</span>",
-        'contact.supplemental_address_1' => "<span class=\"extended-address\">" . $fields['supplemental_address_1'] . "</span>",
-        'contact.supplemental_address_2' => $fields['supplemental_address_2'],
-        'contact.supplemental_address_3' => $fields['supplemental_address_3'],
-        'contact.city' => "<span class=\"locality\">" . $fields['city'] . "</span>",
-        'contact.state_province_name' => "<span class=\"region\">" . $fields['state_province_name'] . "</span>",
-        'contact.county' => "<span class=\"region\">" . $fields['county'],
-        'contact.state_province' => "<span class=\"region\">" . $fields['state_province'] . "</span>",
-        'contact.postal_code' => "<span class=\"postal-code\">" . $fullPostalCode . "</span>",
-        'contact.country' => "<span class=\"country-name\">" . $fields['country'] . "</span>",
-        'contact.world_region' => "<span class=\"region\">" . $fields['world_region'] . "</span>",
-      ];
-
-      // Erase all empty ones, so we don't get blank lines
-      foreach (array_keys($replacements) as $key) {
-        $exactKey = substr($key, 0, 8) == 'contact.' ? substr($key, 8) : $key;
-        if ($key !== 'contact.postal_code' && empty($fields[$exactKey])) {
-          $replacements[$key] = '';
-        }
-      }
-      if (empty($fullPostalCode)) {
-        $replacements['contact.postal_code'] = '';
+    $replacements = [
+      'contact.address_name' => "<span class=\"address-name\">" . $fields['address_name'] . "</span>",
+      'contact.street_address' => "<span class=\"street-address\">" . $fields['street_address'] . "</span>",
+      'contact.supplemental_address_1' => "<span class=\"extended-address\">" . $fields['supplemental_address_1'] . "</span>",
+      'contact.supplemental_address_2' => $fields['supplemental_address_2'],
+      'contact.supplemental_address_3' => $fields['supplemental_address_3'],
+      'contact.city' => "<span class=\"locality\">" . $fields['city'] . "</span>",
+      'contact.state_province_name' => "<span class=\"region\">" . $fields['state_province_name'] . "</span>",
+      'contact.county' => "<span class=\"region\">" . $fields['county'],
+      'contact.state_province' => "<span class=\"region\">" . $fields['state_province'] . "</span>",
+      'contact.postal_code' => "<span class=\"postal-code\">" . $fullPostalCode . "</span>",
+      'contact.country' => "<span class=\"country-name\">" . $fields['country'] . "</span>",
+      'contact.world_region' => "<span class=\"region\">" . $fields['world_region'] . "</span>",
+    ];
+
+    // Erase all empty ones, so we don't get blank lines
+    foreach (array_keys($replacements) as $key) {
+      $exactKey = substr($key, 0, 8) == 'contact.' ? substr($key, 8) : $key;
+      if ($key !== 'contact.postal_code' && empty($fields[$exactKey])) {
+        $replacements[$key] = '';
       }
     }
+    if (empty($fullPostalCode)) {
+      $replacements['contact.postal_code'] = '';
+    }
 
     // replacements in case of Custom Token
     if (stristr(($formatted ?? ''), 'custom_')) {
@@ -164,13 +228,6 @@ class CRM_Utils_Address {
       }
     }
 
-    // also sub all token fields
-    if ($tokenFields) {
-      foreach ($tokenFields as $token) {
-        $replacements["{$token}"] = $fields["{$token}"] ?? NULL;
-      }
-    }
-
     // for every token, replace {fooTOKENbar} with fooVALUEbar if
     // the value is not empty, otherwise drop the whole {fooTOKENbar}
     foreach ($replacements as $token => $value) {
@@ -182,18 +239,7 @@ class CRM_Utils_Address {
       }
     }
 
-    // drop any {...} constructs from lines' ends
-    if (!$microformat) {
-      $formatted = "\n$formatted\n";
-    }
-    else {
-      if ($microformat == 1) {
-        $formatted = "\n<div class=\"location vcard\"><span class=\"adr\">\n$formatted</span></div>\n";
-      }
-      else {
-        $formatted = "\n<div class=\"vcard\"><span class=\"adr\">$formatted</span></div>\n";
-      }
-    }
+    $formatted = "\n<div class=\"location vcard\"><span class=\"adr\">\n$formatted</span></div>\n";
 
     $formatted = preg_replace('/\n{[^{}]*}/u', "\n", $formatted);
     $formatted = preg_replace('/{[^{}]*}\n/u', "\n", $formatted);
@@ -210,27 +256,21 @@ class CRM_Utils_Address {
 
     // drop any empty lines left after the replacements
     $formatted = preg_replace('/^[ \t]*[\r\n]+/m', '', $formatted);
-
-    if (!$microformat) {
-      $finalFormatted = $formatted;
-    }
-    else {
-      // remove \n from each line and only add at the end
-      // this hack solves formatting issue, when we convert nl2br
-      $count = 1;
-      $finalFormatted = NULL;
-      $formattedArray = explode("\n", $formatted);
-      $formattedArray = array_filter($formattedArray);
-
-      foreach ($formattedArray as $line) {
-        $line = trim($line);
-        if ($line) {
-          if ($count > 1 && $count < count($formattedArray)) {
-            $line = "$line\n";
-          }
-          $finalFormatted .= $line;
-          $count++;
+    // remove \n from each line and only add at the end
+    // this hack solves formatting issue, when we convert nl2br
+    $count = 1;
+    $finalFormatted = NULL;
+    $formattedArray = explode("\n", $formatted);
+    $formattedArray = array_filter($formattedArray);
+
+    foreach ($formattedArray as $line) {
+      $line = trim($line);
+      if ($line) {
+        if ($count > 1 && $count < count($formattedArray)) {
+          $line = "$line\n";
         }
+        $finalFormatted .= $line;
+        $count++;
       }
     }
     return $finalFormatted;