Ejemplo n.º 1
0
/**
 * Given a string $str and values $vars, replace tags in the string with the values
 *
 * The $vars may also be an object, in which case values will be pulled as properties of the object. 
 *
 * By default, tags are specified in the format: {first_name} where first_name is the name of the
 * variable to pull from $vars, '{' is the opening tag character, and '}' is the closing tag char.
 *
 * The tag parser can also handle subfields and OR tags, if $vars is an object that supports that.
 * For instance {products.title} is a subfield, and {first_name|title|name} is an OR tag. 
 *
 * @param string $str The string to operate on (where the {tags} might be found)
 * @param WireData|object|array Object or associative array to pull replacement values from. 
 * @param array $options Array of optional changes to default behavior, including: 
 * 	- tagOpen: The required opening tag character(s), default is '{'
 *	- tagClose: The optional closing tag character(s), default is '}'
 *	- recursive: If replacement value contains tags, populate those too? Default=false. 
 *	- removeNullTags: If a tag resolves to a NULL, remove it? If false, tag will remain. Default=true. 
 *	- entityEncode: Entity encode the values pulled from $vars? Default=false. 
 *	- entityDecode: Entity decode the values pulled from $vars? Default=false.
 * @return string String with tags populated. 
 *
 */
function wirePopulateStringTags($str, $vars, array $options = array())
{
    $defaults = array('tagOpen' => '{', 'tagClose' => '}', 'recursive' => false, 'removeNullTags' => true, 'entityEncode' => false, 'entityDecode' => false);
    $options = array_merge($defaults, $options);
    // check if this string even needs anything populated
    if (strpos($str, $options['tagOpen']) === false) {
        return $str;
    }
    if (strlen($options['tagClose']) && strpos($str, $options['tagClose']) === false) {
        return $str;
    }
    // find all tags
    $tagOpen = preg_quote($options['tagOpen']);
    $tagClose = preg_quote($options['tagClose']);
    $numFound = preg_match_all('/' . $tagOpen . '([-_.|a-zA-Z0-9]+)' . $tagClose . '/', $str, $matches);
    if (!$numFound) {
        return $str;
    }
    $replacements = array();
    // create a list of replacements by finding replacement values in $vars
    foreach ($matches[1] as $key => $fieldName) {
        $tag = $matches[0][$key];
        if (isset($replacements[$tag])) {
            continue;
        }
        // if already found, don't continue
        $fieldValue = null;
        if (is_object($vars)) {
            if ($vars instanceof Page) {
                $fieldValue = $vars->getMarkup($fieldName);
            } else {
                if ($vars instanceof WireData) {
                    $fieldValue = $vars->get($fieldName);
                } else {
                    $fieldValue = $vars->{$fieldName};
                }
            }
        } else {
            if (is_array($vars)) {
                $fieldValue = isset($vars[$fieldName]) ? $vars[$fieldName] : null;
            }
        }
        if ($options['entityEncode']) {
            $fieldValue = htmlentities($fieldValue, ENT_QUOTES, 'UTF-8', false);
        }
        if ($options['entityDecode']) {
            $fieldValue = html_entity_decode($fieldValue, ENT_QUOTES, 'UTF-8');
        }
        $replacements[$tag] = $fieldValue;
    }
    // replace the tags
    foreach ($replacements as $tag => $value) {
        // populate tags recursively, if asked to do so
        if ($options['recursive'] && strpos($value, $options['tagOpen'])) {
            $opt = array_merge($options, array('recursive' => false));
            // don't go recursive beyond 1 level
            $value = wirePopulateStringTags($value, $vars, $opt);
        }
        // replace tags with replacement values
        $str = str_replace($tag, $value, $str);
    }
    return $str;
}
Ejemplo n.º 2
0
 /**
  * Return the markup value for a given field name or {tag} string
  *
  * 1. If given a field name (or name.subname or name1|name2|name3) it will return the
  * markup value as defined by the fieldtype.
  *
  * 2. If given a string with field names referenced in {tags}, it will populate those
  * tags and return the populated string.
  *
  * @param string $key Field name or markup string with field {name} tags in it
  * @return string
  *
  */
 public function ___getMarkup($key)
 {
     $value = '';
     if (strpos($key, '{') !== false && strpos($key, '}')) {
         // populate a string with {tags}
         // note that the wirePopulateStringTags() function calls back on this method
         // to retrieve the markup values for each of the found field names
         return wirePopulateStringTags($key, $this);
     }
     if (strpos($key, '|') !== false) {
         $key = $this->getFieldFirstValue($key, true);
         if (!$key) {
             return '';
         }
     }
     if ($this->wire('sanitizer')->name($key) != $key) {
         // not a possible field name
         return '';
     }
     $parts = strpos($key, '.') ? explode('.', $key) : array($key);
     $value = $this;
     do {
         $name = array_shift($parts);
         $field = null;
         if ($this->template && $this->template->fieldgroup) {
             $field = $this->template->fieldgroup->getField($name);
         }
         if (!$field && $this->wire($name)) {
             // disallow API vars
             $value = '';
             break;
         }
         if ($value instanceof Page) {
             $value = $value->getFormatted($name);
         } else {
             if ($value instanceof Wire) {
                 $value = $value->get($name);
             } else {
                 $value = $value->{$name};
             }
         }
         if ($field && count($parts) < 2) {
             // this is a field that will provide its own formatted value
             $subname = count($parts) == 1 ? array_shift($parts) : '';
             if (!$this->wire($subname)) {
                 $value = $field->type->markupValue($this, $field, $value, $subname);
             }
         }
     } while (is_object($value) && count($parts));
     if (is_object($value)) {
         if ($value instanceof Page) {
             $value = $value->getFormatted('title|name');
         }
         if ($value instanceof PageArray) {
             $value = $value->getMarkup();
         }
     }
     if (!is_string($value)) {
         $value = (string) $value;
     }
     return $value;
 }
Ejemplo n.º 3
0
 /**
  * Return the markup value for a given field name or {tag} string
  *
  * 1. If given a field name (or name.subname or name1|name2|name3) it will return the
  * markup value as defined by the fieldtype.
  *
  * 2. If given a string with field names referenced in {tags}, it will populate those
  * tags and return the populated string.
  *
  * @param string $key Field name or markup string with field {name} tags in it
  * @return string
  *
  */
 public function ___getMarkup($key)
 {
     $value = '';
     if (strpos($key, '{') !== false && strpos($key, '}')) {
         // populate a string with {tags}
         // note that the wirePopulateStringTags() function calls back on this method
         // to retrieve the markup values for each of the found field names
         $value = wirePopulateStringTags($key, $this);
     } else {
         if (strpos($key, '|') !== false) {
             $key = $this->getFieldFirstValue($key, true);
             if (!$key) {
                 return '';
             }
         }
         if ($this->wire('sanitizer')->name($key) != $key) {
             // not a possible field name
             return '';
         }
         $name = $key;
         $subname = '';
         if (strpos($name, '.')) {
             list($name, $subname) = explode('.', $key);
         }
         $field = $this->fieldgroup->getField($name);
         if ($field) {
             // corresponds to a known field in this page's fieldgroup
             $value = $this->getFormatted($name);
             $value = $field->type->markupValue($this, $field, $value, $subname);
         } else {
             if ($this->wire($name) || $subname && $this->wire($subname)) {
                 // we don't allow API variables in markup values
             } else {
                 // native or unknown field
                 $value = $this->getFormatted($key);
             }
         }
         if (is_object($value)) {
             if ($value instanceof Page) {
                 $value = $value->getFormatted('title|name');
             }
             if ($value instanceof PageArray) {
                 $value = $value->getMarkup();
             }
         }
     }
     if (!is_string($value)) {
         $value = (string) $value;
     }
     return $value;
 }
Ejemplo n.º 4
0
 /**
  * Execute a function for each item, or build a string or array from each item
  * 
  * @param callable|function|string|array|null $func Accepts any of the following:
  * 1. Callable function that each item will be passed to as first argument. If this 
  *    function returns a string, it will be appended to that of the other items and 
  *    the result returned by this each() method.
  * 2. Markup or text string with variable {tags} within it where each {tag} resolves
  *    to a property in each item. This each() method will return the concatenated result.
  * 3. A property name (string) common to items in this WireArray. The result will be 
  *    returned as an array. 
  * 4. An array of property names common to items in this WireArray. The result will be
  *    returned as an array of associative arrays indexed by property name. 
  *   	
  * @return array|null|string|WireArray Returns one of the following (related to numbers above).
  * 1a. $this WireArray of given a function that has no return values. 
  * 1b. Returns a string containing the concatenated results of all function calls, if 
  *     your function returns strings.
  * 2.  Returns the processed and concatenated result (string) of all items in your 
  *     template string.
  * 3.  Returns regular PHP array of the property values for each item you requested.
  * 4.  Returns an array of associative arrays containing the property values for each item
  *     you requested.
  * 
  */
 public function each($func = null)
 {
     $result = null;
     // return value, if it's detected that one is desired
     if (is_callable($func)) {
         $funcInfo = new ReflectionFunction($func);
         $useIndex = $funcInfo->getNumberOfParameters() > 1;
         foreach ($this as $index => $item) {
             $val = $useIndex ? $func($index, $item) : $func($item);
             if ($val && is_string($val)) {
                 // function returned a string, so we assume they are wanting us to return the result
                 if (is_null($result)) {
                     $result = '';
                 }
                 // if returned value resulted in {tags}, go ahead and parse them
                 if (strpos($val, '{') !== false && strpos($val, '}')) {
                     $val = wirePopulateStringTags($val, $item);
                 }
                 $result .= $val;
             }
         }
     } else {
         if (is_string($func) && strpos($func, '{') !== false && strpos($func, '}')) {
             // string with variables
             $result = '';
             foreach ($this as $item) {
                 $result .= wirePopulateStringTags($func, $item);
             }
         } else {
             // array or string or null
             if (is_null($func)) {
                 $func = 'name';
             }
             $result = $this->explode($func);
         }
     }
     return $result === null ? $this : $result;
 }