Merge pull request #5513 from mallezie/contact-select-file-16178
[civicrm-core.git] / CRM / Utils / Token.php
index 10d5d8937f3b8817c306009027b247b4d901a02a..b549e4aa9f1f6ae764e6456ca3b73bb8fd975f0f 100644 (file)
@@ -1,9 +1,9 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.5                                                |
+ | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2014                                |
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
  | GNU Affero General Public License or the licensing of CiviCRM,     |
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
-*/
+ */
 
 /**
  *
  * @package CRM
- * @copyright CiviCRM LLC (c) 2004-2014
+ * @copyright CiviCRM LLC (c) 2004-2015
  * $Id: $
  *
  */
@@ -84,28 +84,21 @@ class CRM_Utils_Token {
       'id',
       'description',
     ),
-    'subscribe' => array( 'group' ),
-    'unsubscribe' => array( 'group' ),
-    'resubscribe' => array( 'group' ),
-    'welcome' => array( 'group' ),
+    'subscribe' => array('group'),
+    'unsubscribe' => array('group'),
+    'resubscribe' => array('group'),
+    'welcome' => array('group'),
   );
 
+
   /**
-   * Check a string (mailing body) for required tokens.
-   *
-   * @param string $str           The message
-   *
-   * @return true|array           true if all required tokens are found,
-   *                              else an array of the missing tokens
-   * @access public
-   * @static
+   * @return array
    */
-  public static function requiredTokens(&$str) {
+  public static function getRequiredTokens() {
     if (self::$_requiredTokens == NULL) {
       self::$_requiredTokens = array(
         'domain.address' => ts("Domain address - displays your organization's postal address."),
-        'action.optOutUrl or action.unsubscribeUrl' =>
-        array(
+        'action.optOutUrl or action.unsubscribeUrl' => array(
           'action.optOut' => ts("'Opt out via email' - displays an email address for recipients to opt out of receiving emails from your organization."),
           'action.optOutUrl' => ts("'Opt out via web page' - creates a link for recipients to click if they want to opt out of receiving emails from your organization. Alternatively, you can include the 'Opt out via email' token."),
           'action.unsubscribe' => ts("'Unsubscribe via email' - displays an email address for recipients to unsubscribe from the specific mailing list used to send this message."),
@@ -113,9 +106,24 @@ class CRM_Utils_Token {
         ),
       );
     }
+    return self::$_requiredTokens;
+  }
+
+  /**
+   * Check a string (mailing body) for required tokens.
+   *
+   * @param string $str
+   *   The message.
+   *
+   * @return bool|array
+   *    true if all required tokens are found,
+   *    else an array of the missing tokens
+   */
+  public static function requiredTokens(&$str) {
+    $requiredTokens = self::getRequiredTokens();
 
     $missing = array();
-    foreach (self::$_requiredTokens as $token => $value) {
+    foreach ($requiredTokens as $token => $value) {
       if (!is_array($value)) {
         if (!preg_match('/(^|[^\{])' . preg_quote('{' . $token . '}') . '/', $str)) {
           $missing[$token] = $value;
@@ -143,15 +151,17 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Wrapper for token matching
+   * Wrapper for token matching.
    *
-   * @param string $type      The token type (domain,mailing,contact,action)
-   * @param string $var       The token variable
-   * @param string $str       The string to search
+   * @param string $type
+   *   The token type (domain,mailing,contact,action).
+   * @param string $var
+   *   The token variable.
+   * @param string $str
+   *   The string to search.
    *
-   * @return boolean          Was there a match
-   * @access public
-   * @static
+   * @return bool
+   *   Was there a match
    */
   public static function token_match($type, $var, &$str) {
     $token = preg_quote('{' . "$type.$var") . '(\|.+?)?' . preg_quote('}');
@@ -159,18 +169,20 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Wrapper for token replacing
-   *
-   * @param string $type The token type
-   * @param string $var The token variable
-   * @param string $value The value to substitute for the token
+   * Wrapper for token replacing.
+   *
+   * @param string $type
+   *   The token type.
+   * @param string $var
+   *   The token variable.
+   * @param string $value
+   *   The value to substitute for the token.
    * @param string (reference) $str The string to replace in
    *
    * @param bool $escapeSmarty
    *
-   * @return string           The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &token_replace($type, $var, $value, &$str, $escapeSmarty = FALSE) {
     $token = preg_quote('{' . "$type.$var") . '(\|([^\}]+?))?' . preg_quote('}');
@@ -185,47 +197,47 @@ class CRM_Utils_Token {
   }
 
   /**
-   * get< the regex for token replacement
-   *
-   * @param $token_type
+   * Get< the regex for token replacement
    *
-   * @internal param string $key a string indicating the the type of token to be used in the expression
+   * @param string $token_type
+   *   A string indicating the the type of token to be used in the expression.
    *
-   * @return string           regular expression sutiable for using in preg_replace
-   * @access private
-   * @static
+   * @return string
+   *   regular expression sutiable for using in preg_replace
    */
   private static function tokenRegex($token_type) {
     return '/(?<!\{|\\\\)\{' . $token_type . '\.([\w]+(\-[\w\s]+)?)\}(?!\})/';
   }
 
   /**
-   * escape the string so a malicious user cannot inject smarty code into the template
+   * Escape the string so a malicious user cannot inject smarty code into the template.
    *
-   * @param string $string    a string that needs to be escaped from smarty parsing
+   * @param string $string
+   *   A string that needs to be escaped from smarty parsing.
    *
-   * @return string           the escaped string
-   * @access private
-   * @static
+   * @return string
+   *   the escaped string
    */
   private static function tokenEscapeSmarty($string) {
     // need to use negative look-behind, as both str_replace() and preg_replace() are sequential
     return preg_replace(array('/{/', '/(?<!{ldelim)}/'), array('{ldelim}', '{rdelim}'), $string);
   }
 
-   /**
+  /**
    * Replace all the domain-level tokens in $str
    *
-   * @param string $str The string with tokens to be replaced
-   * @param object $domain The domain BAO
-   * @param boolean $html Replace tokens with HTML or plain text
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param object $domain
+   *   The domain BAO.
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
    *
    * @param null $knownTokens
    * @param bool $escapeSmarty
    *
-   * @return string           The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceDomainTokens(
     $str,
@@ -236,13 +248,14 @@ class CRM_Utils_Token {
   ) {
     $key = 'domain';
     if (
-      !$knownTokens || empty($knownTokens[$key])) {
+      !$knownTokens || empty($knownTokens[$key])
+    ) {
       return $str;
     }
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use(&$domain, $html, $escapeSmarty) {
+      function ($matches) use (&$domain, $html, $escapeSmarty) {
         return CRM_Utils_Token::getDomainTokenReplacement($matches[1], $domain, $html, $escapeSmarty);
       },
       $str
@@ -315,19 +328,21 @@ class CRM_Utils_Token {
   /**
    * Replace all the org-level tokens in $str
    *
-   * @param string $str The string with tokens to be replaced
-   * @param object $org Associative array of org properties
-   * @param boolean $html Replace tokens with HTML or plain text
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param object $org
+   *   Associative array of org properties.
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
    *
    * @param bool $escapeSmarty
    *
-   * @return string           The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceOrgTokens($str, &$org, $html = FALSE, $escapeSmarty = FALSE) {
-    self::$_tokens['org'] =
-      array_merge(
+    self::$_tokens['org']
+      array_merge(
         array_keys(CRM_Contact_BAO_Contact::importableFields('Organization')),
         array('address', 'display_name', 'checksum', 'contact_id')
       );
@@ -395,16 +410,18 @@ class CRM_Utils_Token {
   /**
    * Replace all mailing tokens in $str
    *
-   * @param string $str The string with tokens to be replaced
-   * @param object $mailing The mailing BAO, or null for validation
-   * @param boolean $html Replace tokens with HTML or plain text
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param object $mailing
+   *   The mailing BAO, or null for validation.
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
    *
    * @param null $knownTokens
    * @param bool $escapeSmarty
    *
-   * @return string           The processed sstring
-   * @access public
-   * @static
+   * @return string
+   *   The processed sstring
    */
   public static function &replaceMailingTokens(
     $str,
@@ -420,7 +437,7 @@ class CRM_Utils_Token {
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use(&$mailing, $escapeSmarty) {
+      function ($matches) use (&$mailing, $escapeSmarty) {
         return CRM_Utils_Token::getMailingTokenReplacement($matches[1], $mailing, $escapeSmarty);
       },
       $str
@@ -524,17 +541,21 @@ class CRM_Utils_Token {
   /**
    * Replace all action tokens in $str
    *
-   * @param string $str The string with tokens to be replaced
-   * @param array $addresses Assoc. array of VERP event addresses
-   * @param array $urls Assoc. array of action URLs
-   * @param boolean $html Replace tokens with HTML or plain text
-   * @param array $knownTokens A list of tokens that are known to exist in the email body
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param array $addresses
+   *   Assoc. array of VERP event addresses.
+   * @param array $urls
+   *   Assoc. array of action URLs.
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
+   * @param array $knownTokens
+   *   A list of tokens that are known to exist in the email body.
    *
    * @param bool $escapeSmarty
    *
-   * @return string             The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceActionTokens(
     $str,
@@ -555,7 +576,7 @@ class CRM_Utils_Token {
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use(&$addresses, &$urls, $html, $escapeSmarty) {
+      function ($matches) use (&$addresses, &$urls, $html, $escapeSmarty) {
         return CRM_Utils_Token::getActionTokenReplacement($matches[1], $addresses, $urls, $html, $escapeSmarty);
       },
       $str
@@ -580,7 +601,7 @@ class CRM_Utils_Token {
     $escapeSmarty = FALSE
   ) {
     /* If the token is an email action, use it.  Otherwise, find the
-         * appropriate URL */
+     * appropriate URL */
 
     if (!in_array($token, self::$_tokens['action'])) {
       $value = "{action.$token}";
@@ -613,17 +634,21 @@ class CRM_Utils_Token {
    * Replace all the contact-level tokens in $str with information from
    * $contact.
    *
-   * @param string $str The string with tokens to be replaced
-   * @param array $contact Associative array of contact properties
-   * @param boolean $html Replace tokens with HTML or plain text
-   * @param array $knownTokens A list of tokens that are known to exist in the email body
-   * @param boolean $returnBlankToken return unevaluated token if value is null
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param array $contact
+   *   Associative array of contact properties.
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
+   * @param array $knownTokens
+   *   A list of tokens that are known to exist in the email body.
+   * @param bool $returnBlankToken
+   *   Return unevaluated token if value is null.
    *
    * @param bool $escapeSmarty
    *
-   * @return string                    The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceContactTokens(
     $str,
@@ -637,8 +662,8 @@ class CRM_Utils_Token {
     if (self::$_tokens[$key] == NULL) {
       /* This should come from UF */
 
-      self::$_tokens[$key] =
-        array_merge(
+      self::$_tokens[$key]
+        array_merge(
           array_keys(CRM_Contact_BAO_Contact::exportableFields('All')),
           array('checksum', 'contact_id')
         );
@@ -654,7 +679,7 @@ class CRM_Utils_Token {
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use(&$contact, $html, $returnBlankToken, $escapeSmarty) {
+      function ($matches) use (&$contact, $html, $returnBlankToken, $escapeSmarty) {
         return CRM_Utils_Token::getContactTokenReplacement($matches[1], $contact, $html, $returnBlankToken, $escapeSmarty);
       },
       $str
@@ -683,8 +708,8 @@ class CRM_Utils_Token {
     if (self::$_tokens['contact'] == NULL) {
       /* This should come from UF */
 
-      self::$_tokens['contact'] =
-        array_merge(
+      self::$_tokens['contact']
+        array_merge(
           array_keys(CRM_Contact_BAO_Contact::exportableFields('All')),
           array('checksum', 'contact_id')
         );
@@ -745,7 +770,10 @@ class CRM_Utils_Token {
     }
 
     if ($escapeSmarty
-        && !($returnBlankToken && $noReplace)) { // $returnBlankToken means the caller wants to do further attempts at processing unreplaced tokens -- so don't escape them yet in this case.
+      && !($returnBlankToken && $noReplace)
+    ) {
+      // $returnBlankToken means the caller wants to do further attempts at
+      // processing unreplaced tokens -- so don't escape them yet in this case.
       $value = self::tokenEscapeSmarty($value);
     }
 
@@ -756,16 +784,18 @@ class CRM_Utils_Token {
    * Replace all the hook tokens in $str with information from
    * $contact.
    *
-   * @param string $str The string with tokens to be replaced
-   * @param array $contact Associative array of contact properties (including hook token values)
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param array $contact
+   *   Associative array of contact properties (including hook token values).
    * @param $categories
-   * @param boolean $html Replace tokens with HTML or plain text
+   * @param bool $html
+   *   Replace tokens with HTML or plain text.
    *
    * @param bool $escapeSmarty
    *
-   * @return string             The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceHookTokens(
     $str,
@@ -777,7 +807,7 @@ class CRM_Utils_Token {
     foreach ($categories as $key) {
       $str = preg_replace_callback(
         self::tokenRegex($key),
-        function ($matches) use(&$contact, $key, $html, $escapeSmarty) {
+        function ($matches) use (&$contact, $key, $html, $escapeSmarty) {
           return CRM_Utils_Token::getHookTokenReplacement($matches[1], $contact, $key, $html, $escapeSmarty);
         },
         $str
@@ -787,11 +817,12 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Parse html through Smarty resolving any smarty functions
+   * Parse html through Smarty resolving any smarty functions.
    * @param string $tokenHtml
    * @param array $entity
    * @param string $entityType
-   * @return string html parsed through smarty
+   * @return string
+   *   html parsed through smarty
    */
   public static function parseThroughSmarty($tokenHtml, $entity, $entityType = 'contact') {
     if (defined('CIVICRM_MAIL_SMARTY') && CIVICRM_MAIL_SMARTY) {
@@ -811,7 +842,8 @@ class CRM_Utils_Token {
    * @param bool $escapeSmarty
    *
    * @return mixed|string
-   */public static function getHookTokenReplacement(
+   */
+  public static function getHookTokenReplacement(
     $token,
     &$contact,
     $category,
@@ -837,28 +869,31 @@ class CRM_Utils_Token {
    *
    *  this routine will remove the extra backslashes and braces
    *
-   *  @param $str ref to the string that will be scanned and modified
-   *  @return void  this function works directly on the string that is passed
-   *  @access public
-   *  @static
+   * @param $str ref to the string that will be scanned and modified
+   * @return void
+   *   this function works directly on the string that is passed
    */
   public static function unescapeTokens(&$str) {
     $str = preg_replace('/\\\\|\{(\{\w+\.\w+\})\}/', '\\1', $str);
   }
 
   /**
-   * Replace unsubscribe tokens
-   *
-   * @param string $str           the string with tokens to be replaced
-   * @param object $domain        The domain BAO
-   * @param array $groups         The groups (if any) being unsubscribed
-   * @param boolean $html         Replace tokens with html or plain text
-   * @param int $contact_id       The contact ID
-   * @param string hash           The security hash of the unsub event
-   *
-   * @return string               The processed string
-   * @access public
-   * @static
+   * Replace unsubscribe tokens.
+   *
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param object $domain
+   *   The domain BAO.
+   * @param array $groups
+   *   The groups (if any) being unsubscribed.
+   * @param bool $html
+   *   Replace tokens with html or plain text.
+   * @param int $contact_id
+   *   The contact ID.
+   * @param string $hash The security hash of the unsub event
+   *
+   * @return string
+   *   The processed string
    */
   public static function &replaceUnsubscribeTokens(
     $str,
@@ -889,20 +924,25 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Replace resubscribe tokens
-   *
-   * @param string $str           the string with tokens to be replaced
-   * @param object $domain        The domain BAO
-   * @param array $groups         The groups (if any) being resubscribed
-   * @param boolean $html         Replace tokens with html or plain text
-   * @param int $contact_id       The contact ID
-   * @param string hash           The security hash of the resub event
-   *
-   * @return string               The processed string
-   * @access public
-   * @static
+   * Replace resubscribe tokens.
+   *
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param object $domain
+   *   The domain BAO.
+   * @param array $groups
+   *   The groups (if any) being resubscribed.
+   * @param bool $html
+   *   Replace tokens with html or plain text.
+   * @param int $contact_id
+   *   The contact ID.
+   * @param string $hash The security hash of the resub event
+   *
+   * @return string
+   *   The processed string
    */
-  public static function &replaceResubscribeTokens($str, &$domain, &$groups, $html,
+  public static function &replaceResubscribeTokens(
+    $str, &$domain, &$groups, $html,
     $contact_id, $hash
   ) {
     if (self::token_match('resubscribe', 'group', $str)) {
@@ -917,14 +957,16 @@ class CRM_Utils_Token {
   /**
    * Replace subscription-confirmation-request tokens
    *
-   * @param string $str The string with tokens to be replaced
-   * @param string $group The name of the group being subscribed
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param string $group
+   *   The name of the group being subscribed.
    * @param $url
-   * @param boolean $html Replace tokens with html or plain text
+   * @param bool $html
+   *   Replace tokens with html or plain text.
    *
-   * @return string               The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceSubscribeTokens($str, $group, $url, $html) {
     if (self::token_match('subscribe', 'group', $str)) {
@@ -939,11 +981,11 @@ class CRM_Utils_Token {
   /**
    * Replace subscription-invitation tokens
    *
-   * @param string $str           The string with tokens to be replaced
+   * @param string $str
+   *   The string with tokens to be replaced.
    *
-   * @return string               The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceSubscribeInviteTokens($str) {
     if (preg_match('/\{action\.subscribeUrl\}/', $str)) {
@@ -968,9 +1010,9 @@ class CRM_Utils_Token {
 
     if (preg_match('/\{action\.subscribe.\d+\}/', $str, $matches)) {
       foreach ($matches as $key => $value) {
-        $gid       = substr($value, 18, -1);
-        $config    = CRM_Core_Config::singleton();
-        $domain    = CRM_Core_BAO_MailSettings::defaultDomain();
+        $gid = substr($value, 18, -1);
+        $config = CRM_Core_Config::singleton();
+        $domain = CRM_Core_BAO_MailSettings::defaultDomain();
         $localpart = CRM_Core_BAO_MailSettings::defaultLocalpart();
         // we add the 0.0000000000000000 part to make this match the other email patterns (with action, two ids and a hash)
         $str = preg_replace('/' . preg_quote($value) . '/', "mailto:{$localpart}s.{$gid}.0.0000000000000000@$domain", $str);
@@ -982,13 +1024,15 @@ class CRM_Utils_Token {
   /**
    * Replace welcome/confirmation tokens
    *
-   * @param string $str           The string with tokens to be replaced
-   * @param string $group         The name of the group being subscribed
-   * @param boolean $html         Replace tokens with html or plain text
+   * @param string $str
+   *   The string with tokens to be replaced.
+   * @param string $group
+   *   The name of the group being subscribed.
+   * @param bool $html
+   *   Replace tokens with html or plain text.
    *
-   * @return string               The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceWelcomeTokens($str, $group, $html) {
     if (self::token_match('welcome', 'group', $str)) {
@@ -1000,11 +1044,11 @@ class CRM_Utils_Token {
   /**
    * Find unprocessed tokens (call this last)
    *
-   * @param string $str       The string to search
+   * @param string $str
+   *   The string to search.
    *
-   * @return array            Array of tokens that weren't replaced
-   * @access public
-   * @static
+   * @return array
+   *   Array of tokens that weren't replaced
    */
   public static function &unmatchedTokens(&$str) {
     //preg_match_all('/[^\{\\\\]\{(\w+\.\w+)\}[^\}]/', $str, $match);
@@ -1013,18 +1057,20 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Find and replace tokens for each component
+   * Find and replace tokens for each component.
    *
-   * @param string $str The string to search
-   * @param array $contact Associative array of contact properties
-   * @param array $components A list of tokens that are known to exist in the email body
+   * @param string $str
+   *   The string to search.
+   * @param array $contact
+   *   Associative array of contact properties.
+   * @param array $components
+   *   A list of tokens that are known to exist in the email body.
    *
    * @param bool $escapeSmarty
    * @param bool $returnEmptyToken
    *
-   * @return string           The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceComponentTokens(&$str, $contact, $components, $escapeSmarty = FALSE, $returnEmptyToken = TRUE) {
     if (!is_array($components) || empty($contact)) {
@@ -1050,14 +1096,15 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Get array of string tokens
+   * Get array of string tokens.
    *
-   * @param  $string the input string to parse for tokens
+   * @param string $string
+   *   The input string to parse for tokens.
    *
-   * @return array $tokens array of tokens mentioned in field@access public
-   * @static
+   * @return array
+   *   array of tokens mentioned in field
    */
-  static function getTokens($string) {
+  public static function getTokens($string) {
     $matches = array();
     $tokens = array();
     preg_match_all('/(?<!\{|\\\\)\{(\w+\.\w+)\}(?!\})/',
@@ -1081,31 +1128,62 @@ class CRM_Utils_Token {
   }
 
   /**
-   * gives required details of contacts in an indexed array format so we
+   * Function to determine which values to retrieve to insert into tokens. The heavy resemblance between this function
+   * and getTokens appears to be historical rather than intentional and should be reviewed
+   * @param $string
+   * @return array
+   *   fields to pass in as return properties when populating token
+   */
+  public static function getReturnProperties(&$string) {
+    $returnProperties = array();
+    $matches = array();
+    preg_match_all('/(?<!\{|\\\\)\{(\w+\.\w+)\}(?!\})/',
+      $string,
+      $matches,
+      PREG_PATTERN_ORDER
+    );
+    if ($matches[1]) {
+      foreach ($matches[1] as $token) {
+        list($type, $name) = preg_split('/\./', $token, 2);
+        if ($name) {
+          $returnProperties["{$name}"] = 1;
+        }
+      }
+    }
+
+    return $returnProperties;
+  }
+
+  /**
+   * Gives required details of contacts in an indexed array format so we
    * can iterate in a nice loop and do token evaluation
    *
    * @param $contactIDs
-   * @param  array $returnProperties of required properties
-   * @param  boolean $skipOnHold don't return on_hold contact info also.
-   * @param  boolean $skipDeceased don't return deceased contact info.
-   * @param  array $extraParams extra params
-   * @param  array $tokens the list of tokens we've extracted from the content
+   * @param array $returnProperties
+   *   Of required properties.
+   * @param bool $skipOnHold Don't return on_hold contact info also.
+   *   Don't return on_hold contact info also.
+   * @param bool $skipDeceased Don't return deceased contact info.
+   *   Don't return deceased contact info.
+   * @param array $extraParams
+   *   Extra params.
+   * @param array $tokens
+   *   The list of tokens we've extracted from the content.
    * @param null $className
-   * @param  int $jobID the mailing list jobID - this is a legacy param
+   * @param int $jobID
+   *   The mailing list jobID - this is a legacy param.
    *
-   * @internal param array $contactIds of contacts
    * @return array
-   * @access public
-   * @static
    */
-  static function getTokenDetails($contactIDs,
+  public static function getTokenDetails(
+    $contactIDs,
     $returnProperties = NULL,
-    $skipOnHold       = TRUE,
-    $skipDeceased     = TRUE,
-    $extraParams      = NULL,
-    $tokens           = array(),
-    $className        = NULL,
-    $jobID            = NULL
+    $skipOnHold = TRUE,
+    $skipDeceased = TRUE,
+    $extraParams = NULL,
+    $tokens = array(),
+    $className = NULL,
+    $jobID = NULL
   ) {
     if (empty($contactIDs)) {
       // putting a fatal here so we can track if/when this happens
@@ -1116,7 +1194,10 @@ class CRM_Utils_Token {
     foreach ($contactIDs as $key => $contactID) {
       $params[] = array(
         CRM_Core_Form::CB_PREFIX . $contactID,
-        '=', 1, 0, 0,
+        '=',
+        1,
+        0,
+        0,
       );
     }
 
@@ -1190,7 +1271,10 @@ class CRM_Utils_Token {
 
         //special case for greeting replacement
         foreach (array(
-          'email_greeting', 'postal_greeting', 'addressee') as $val) {
+                   'email_greeting',
+                   'postal_greeting',
+                   'addressee',
+                 ) as $val) {
           if (!empty($contactDetails[$contactID][$val])) {
             $contactDetails[$contactID][$val] = $contactDetails[$contactID]["{$val}_display"];
           }
@@ -1212,28 +1296,33 @@ class CRM_Utils_Token {
    * Call hooks on tokens for anonymous users - contact id is set to 0 - this allows non-contact
    * specific tokens to be rendered
    *
-   * @param array $contactIDs - this should always be array(0) or its not anonymous - left to keep signature same
-   * as main fn
+   * @param array $contactIDs
+   *   This should always be array(0) or its not anonymous - left to keep signature same.
+   *   as main fn
    * @param string $returnProperties
-   * @param boolean $skipOnHold
-   * @param boolean $skipDeceased
+   * @param bool $skipOnHold
+   * @param bool $skipDeceased
    * @param string $extraParams
    * @param array $tokens
-   * @param string $className sent as context to the hook
+   * @param string $className
+   *   Sent as context to the hook.
    * @param string $jobID
-   * @return array contactDetails with hooks swapped out
+   * @return array
+   *   contactDetails with hooks swapped out
    */
-  function getAnonymousTokenDetails($contactIDs = array(0),
-    $returnProperties = NULL,
-    $skipOnHold       = TRUE,
-    $skipDeceased     = TRUE,
-    $extraParams      = NULL,
-    $tokens           = array(),
-    $className        = NULL,
-    $jobID            = NULL) {
+  public function getAnonymousTokenDetails($contactIDs = array(
+      0,
+    ),
+                                           $returnProperties = NULL,
+                                           $skipOnHold = TRUE,
+                                           $skipDeceased = TRUE,
+                                           $extraParams = NULL,
+                                           $tokens = array(),
+                                           $className = NULL,
+                                           $jobID = NULL) {
     $details = array(0 => array());
-      // also call a hook and get token details
-      CRM_Utils_Hook::tokenValues($details[0],
+    // also call a hook and get token details
+    CRM_Utils_Hook::tokenValues($details[0],
       $contactIDs,
       $jobID,
       $tokens,
@@ -1243,30 +1332,29 @@ class CRM_Utils_Token {
   }
 
   /**
-   * gives required details of contribuion in an indexed array format so we
+   * Gives required details of contribuion in an indexed array format so we
    * can iterate in a nice loop and do token evaluation
    *
-   * @param $contributionIDs
-   * @param  array $returnProperties of required properties
-   * @param  array $extraParams extra params
-   * @param  array $tokens the list of tokens we've extracted from the content
-   *
-   * @param null $className
+   * @param array $contributionIDs
+   * @param array $returnProperties
+   *   Of required properties.
+   * @param array $extraParams
+   *   Extra params.
+   * @param array $tokens
+   *   The list of tokens we've extracted from the content.
+   * @param string $className
    *
-   * @internal param array $contributionId one contribution id
-   * @internal param bool $skipOnHold don't return on_hold contact info.
-   * @internal param bool $skipDeceased don't return deceased contact info.
    * @return array
-   * @access public
-   * @static
    */
-  static function getContributionTokenDetails($contributionIDs,
+  public static function getContributionTokenDetails(
+    $contributionIDs,
     $returnProperties = NULL,
-    $extraParams      = NULL,
-    $tokens           = array(),
-    $className        = NULL
+    $extraParams = NULL,
+    $tokens = array(),
+    $className = NULL
   ) {
-    //@todo - this function basically replications calling civicrm_api3('contribution', 'get', array('id' => array('IN' => array())
+    //@todo - this function basically replicates calling
+    //civicrm_api3('contribution', 'get', array('id' => array('IN' => array())
     if (empty($contributionIDs)) {
       // putting a fatal here so we can track if/when this happens
       CRM_Core_Error::fatal();
@@ -1311,19 +1399,22 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Get Membership Token Details
-   * @param array $membershipIDs array of membership IDS
+   * Get Membership Token Details.
+   * @param array $membershipIDs
+   *   Array of membership IDS.
    */
-  static function getMembershipTokenDetails($membershipIDs) {
-    $memberships = civicrm_api3('membership', 'get', array('options' => array('limit' => 200000), 'membership_id' => array('IN' => (array) $membershipIDs)));
+  public static function getMembershipTokenDetails($membershipIDs) {
+    $memberships = civicrm_api3('membership', 'get', array(
+        'options' => array('limit' => 200000),
+        'membership_id' => array('IN' => (array) $membershipIDs),
+      ));
     return $memberships['values'];
   }
+
   /**
-   * replace greeting tokens exists in message/subject
-   *
-   * @access public
+   * Replace greeting tokens exists in message/subject
    */
-  static function replaceGreetingTokens(&$tokenString, $contactDetails = NULL, $contactId = NULL, $className = NULL, $escapeSmarty = FALSE) {
+  public static function replaceGreetingTokens(&$tokenString, $contactDetails = NULL, $contactId = NULL, $className = NULL, $escapeSmarty = FALSE) {
 
     if (!$contactDetails && !$contactId) {
       return;
@@ -1341,7 +1432,8 @@ class CRM_Utils_Token {
       // check if there are any unevaluated tokens
       $greetingTokens = self::getTokens($tokenString);
 
-      // $greetingTokens not empty, means there are few tokens which are not evaluated, like custom data etc
+      // $greetingTokens not empty, means there are few tokens which are not
+      // evaluated, like custom data etc
       // so retrieve it from database
       if (!empty($greetingTokens) && array_key_exists('contact', $greetingTokens)) {
         $greetingsReturnProperties = array_flip(CRM_Utils_Array::value('contact', $greetingTokens));
@@ -1364,17 +1456,17 @@ class CRM_Utils_Token {
           $escapeSmarty
         );
       }
-      
+
       // check if there are still any unevaluated tokens
       $remainingTokens = self::getTokens($tokenString);
 
-      // contact related $greetingTokens not empty, there are customized or hook tokens to replace 
-      if (!empty($remainingTokens['contact']) ) {
+      // contact related $greetingTokens not empty, there are customized or hook tokens to replace
+      if (!empty($remainingTokens['contact'])) {
         // Fill the return properties array
         $greetingTokens = $remainingTokens['contact'];
         reset($greetingTokens);
         $greetingsReturnProperties = array();
-        while(list($key) = each($greetingTokens)) {
+        while (list($key) = each($greetingTokens)) {
           $props = array_flip(CRM_Utils_Array::value($key, $greetingTokens));
           $props = array_fill_keys(array_keys($props), 1);
           $greetingsReturnProperties = $greetingsReturnProperties + $props;
@@ -1400,11 +1492,14 @@ class CRM_Utils_Token {
    *
    * @return array
    */
-  static function flattenTokens(&$tokens) {
+  public static function flattenTokens(&$tokens) {
     $flattenTokens = array();
 
     foreach (array(
-      'html', 'text', 'subject') as $prop) {
+               'html',
+               'text',
+               'subject',
+             ) as $prop) {
       if (!isset($tokens[$prop])) {
         continue;
       }
@@ -1424,14 +1519,14 @@ class CRM_Utils_Token {
   /**
    * Replace all user tokens in $str
    *
-   * @param string $str The string with tokens to be replaced
+   * @param string $str
+   *   The string with tokens to be replaced.
    *
    * @param null $knownTokens
    * @param bool $escapeSmarty
    *
-   * @return string           The processed string
-   * @access public
-   * @static
+   * @return string
+   *   The processed string
    */
   public static function &replaceUserTokens($str, $knownTokens = NULL, $escapeSmarty = FALSE) {
     $key = 'user';
@@ -1443,7 +1538,7 @@ class CRM_Utils_Token {
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use($escapeSmarty) {
+      function ($matches) use ($escapeSmarty) {
         return CRM_Utils_Token::getUserTokenReplacement($matches[1], $escapeSmarty);
       },
       $str
@@ -1480,19 +1575,18 @@ class CRM_Utils_Token {
   }
 
   /**
-   *
    */
   protected static function _buildContributionTokens() {
     $key = 'contribution';
     if (self::$_tokens[$key] == NULL) {
       self::$_tokens[$key] = array_keys(array_merge(CRM_Contribute_BAO_Contribution::exportableFields('All'),
-          array('campaign', 'financial_type')
-        ));
+        array('campaign', 'financial_type')
+      ));
     }
   }
 
   /**
-   * store membership tokens on the static _tokens array
+   * Store membership tokens on the static _tokens array.
    */
   protected static function _buildMembershipTokens() {
     $key = 'membership';
@@ -1507,20 +1601,24 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Replace tokens for an entity
+   * Replace tokens for an entity.
    * @param string $entity
-   * @param array $entityArray (e.g. in format from api)
-   * @param string $str string to replace in
-   * @param array $knownTokens array of tokens present
-   * @param boolean $escapeSmarty
-   * @return string string with replacements made
+   * @param array $entityArray
+   *   (e.g. in format from api).
+   * @param string $str
+   *   String to replace in.
+   * @param array $knownTokens
+   *   Array of tokens present.
+   * @param bool $escapeSmarty
+   * @return string
+   *   string with replacements made
    */
   public static function replaceEntityTokens($entity, $entityArray, $str, $knownTokens = array(), $escapeSmarty = FALSE) {
     if (!$knownTokens || empty($knownTokens[$entity])) {
       return $str;
     }
 
-    $fn = 'get' . ucFirst($entity) . 'tokenReplacement';
+    $fn = 'get' . ucfirst($entity) . 'tokenReplacement';
     //since we already know the tokens lets just use them & do str_replace which is faster & simpler than preg_replace
     foreach ($knownTokens[$entity] as $token) {
       $replaceMent = CRM_Utils_Token::$fn($token, $entityArray, $escapeSmarty);
@@ -1531,7 +1629,7 @@ class CRM_Utils_Token {
   }
 
   /**
-   * Replace Contribution tokens in html
+   * Replace Contribution tokens in html.
    *
    * @param string $str
    * @param array $contribution
@@ -1539,7 +1637,7 @@ class CRM_Utils_Token {
    * @param string $knownTokens
    * @param bool|string $escapeSmarty
    *
-   * @return unknown|Ambigous <string, mixed>|mixed
+   * @return mixed
    */
   public static function replaceContributionTokens($str, &$contribution, $html = FALSE, $knownTokens = NULL, $escapeSmarty = FALSE) {
     $key = 'contribution';
@@ -1555,7 +1653,7 @@ class CRM_Utils_Token {
 
     $str = preg_replace_callback(
       self::tokenRegex($key),
-      function ($matches) use(&$contribution, $html, $escapeSmarty) {
+      function ($matches) use (&$contribution, $html, $escapeSmarty) {
         return CRM_Utils_Token::getContributionTokenReplacement($matches[1], $contribution, $html, $escapeSmarty);
       },
       $str
@@ -1585,11 +1683,11 @@ class CRM_Utils_Token {
    * @return \Ambigous|mixed|string|\unknown
    */
   public static function replaceMultipleContributionTokens($separator, $str, &$contribution, $html = FALSE, $knownTokens = NULL, $escapeSmarty = FALSE) {
-    if(empty($knownTokens['contribution'])) {
+    if (empty($knownTokens['contribution'])) {
       return $str;
     }
 
-    if(in_array('receive_date', $knownTokens['contribution'])) {
+    if (in_array('receive_date', $knownTokens['contribution'])) {
       $formattedDates = array();
       $dates = explode($separator, $contribution['receive_date']);
       foreach ($dates as $date) {
@@ -1605,40 +1703,48 @@ class CRM_Utils_Token {
    * Get replacement strings for any membership tokens (only a small number of tokens are implemnted in the first instance
    * - this is used by the pdfLetter task from membership search
    * @param string $token
-   * @param array $membership an api result array for a single membership
-   * @param boolean $escapeSmarty
-   * @return string token replacement
+   * @param array $membership
+   *   An api result array for a single membership.
+   * @param bool $escapeSmarty
+   * @return string
+   *   token replacement
    */
   public static function getMembershipTokenReplacement($token, $membership, $escapeSmarty = FALSE) {
     $entity = 'membership';
     self::_buildMembershipTokens();
-   switch ($token) {
-     case 'type':
-       $value = $membership['membership_name'];
-       break;
-     case 'status':
-       $statuses = CRM_Member_BAO_Membership::buildOptions('status_id');
-       $value = $statuses[$membership['status_id']];
-       break;
-     case 'fee':
-       try{
-         $value = civicrm_api3('membership_type', 'getvalue', array('id' => $membership['membership_type_id'], 'return' => 'minimum_fee'));
-       }
-       catch (CiviCRM_API3_Exception $e) {
-         // we can anticipate we will get an error if the minimum fee is set to 'NULL' because of the way the
-         // api handles NULL (4.4)
-         $value = 0;
-       }
-       break;
-     default:
-       if (in_array($token, self::$_tokens[$entity])) {
-         $value = $membership[$token];
-       }
-       else {
-         //ie unchanged
-         $value = "{$entity}.{$token}";
-       }
-       break;
+    switch ($token) {
+      case 'type':
+        $value = $membership['membership_name'];
+        break;
+
+      case 'status':
+        $statuses = CRM_Member_BAO_Membership::buildOptions('status_id');
+        $value = $statuses[$membership['status_id']];
+        break;
+
+      case 'fee':
+        try {
+          $value = civicrm_api3('membership_type', 'getvalue', array(
+              'id' => $membership['membership_type_id'],
+              'return' => 'minimum_fee',
+            ));
+        }
+        catch (CiviCRM_API3_Exception $e) {
+          // we can anticipate we will get an error if the minimum fee is set to 'NULL' because of the way the
+          // api handles NULL (4.4)
+          $value = 0;
+        }
+        break;
+
+      default:
+        if (in_array($token, self::$_tokens[$entity])) {
+          $value = $membership[$token];
+        }
+        else {
+          //ie unchanged
+          $value = "{$entity}.{$token}";
+        }
+        break;
     }
 
     if ($escapeSmarty) {
@@ -1681,7 +1787,6 @@ class CRM_Utils_Token {
         break;
     }
 
-
     if ($escapeSmarty) {
       $value = self::tokenEscapeSmarty($value);
     }
@@ -1689,9 +1794,10 @@ class CRM_Utils_Token {
   }
 
   /**
-   * @return array: legacy_token => new_token
+   * @return array
+   *   legacy_token => new_token
    */
-  static function legacyContactTokens() {
+  public static function legacyContactTokens() {
     return array(
       'individual_prefix' => 'prefix_id',
       'individual_suffix' => 'suffix_id',
@@ -1702,10 +1808,11 @@ class CRM_Utils_Token {
 
   /**
    * Formats a token list for the select2 widget
+   *
    * @param $tokens
    * @return array
    */
-  static function formatTokensForDisplay($tokens) {
+  public static function formatTokensForDisplay($tokens) {
     $sorted = $output = array();
 
     // Sort in ascending order by ignoring word case
@@ -1739,4 +1846,5 @@ class CRM_Utils_Token {
 
     return $output;
   }
+
 }