public function set($params = array(), $value = '', $type = 'variable', $scope = 'user')
{
/* Sample use
---------------------------------------------------------
{exp:stash:set name="title" type="snippet"}A title{/exp:stash:set}
OR static call within PHP enabled templates or other add-on:
<?php stash::set('title', 'My title') ?>
--------------------------------------------------------- */
// is this method being called directly?
if (func_num_args() > 0) {
if (!(isset($this) && get_class($this) == __CLASS__)) {
return self::_api_static_call(__FUNCTION__, $params, $type, $scope, $value);
} else {
return $this->_api_call(__FUNCTION__, $params, $type, $scope, $value);
}
}
// do we want to set the variable?
$set = TRUE;
// var name
$name = $this->EE->TMPL->fetch_param('name', FALSE);
// context handling
$context = $this->EE->TMPL->fetch_param('context', NULL);
if (!!$name) {
if ($context !== NULL && count(explode(':', $name) == 1)) {
$name = $context . ':' . $name;
$this->EE->TMPL->tagparams['context'] = NULL;
}
}
// replace '@' placeholders with the current context
$stash_key = $this->_parse_context($name);
// scope
$scope = strtolower($this->EE->TMPL->fetch_param('scope', $this->default_scope));
// local|user|site
// do we want this tag to return it's tagdata? (default: no)
$output = (bool) preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('output'));
// do we want to parse early global variables in variables retrieved from the cache
// append or prepend passed as parameters?
if (preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('prepend'))) {
$this->_update = TRUE;
$this->_append = FALSE;
} elseif (preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('append'))) {
$this->_update = TRUE;
$this->_append = TRUE;
}
// do we want to save this variable in a bundle?
$bundle = $this->EE->TMPL->fetch_param('bundle', NULL);
// save in a bundle?
// do we want to replace an existing variable?
if (!!$name && !$this->replace && !$this->_update) {
// try to get existing value
$existing_value = FALSE;
if (array_key_exists($stash_key, $this->_stash)) {
$existing_value = $this->_stash[$name];
} elseif ($scope !== 'local') {
// narrow the scope to user?
$session_id = $scope === 'user' ? $this->_session_id : '_global';
$existing_value = $this->EE->stash_model->get_key($stash_key, $this->bundle_id, $session_id, $this->site_id);
}
if ($existing_value !== FALSE) {
// yes, it's already been stashed
$this->EE->TMPL->tagdata = $this->_stash[$name] = $existing_value;
// don't overwrite existing value
$set = FALSE;
}
unset($existing_value);
}
// do we want to ignore empty tagdata values?
if ($not_empty = (bool) preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('not_empty'))) {
if (!$this->not_empty()) {
$set = FALSE;
}
}
if ($set) {
// support for deprecated no_results_prefix parameter
$no_results_prefix = $this->EE->TMPL->fetch_param('no_results_prefix');
// check for an unprefix parameter to avoid variable name conflicts in nested tags
if ($unprefix = $this->EE->TMPL->fetch_param('unprefix', $no_results_prefix)) {
$this->EE->TMPL->tagdata = $this->_un_prefix($unprefix, $this->EE->TMPL->tagdata);
}
if (($this->parse_tags || $this->parse_vars || $this->parse_conditionals) && !$this->parse_complete) {
$this->_parse_sub_template($this->parse_tags, $this->parse_vars, $this->parse_conditionals, $this->parse_depth);
$this->parse_complete = TRUE;
// don't run again
}
// apply any string manipulations
$this->EE->TMPL->tagdata = $this->_clean_string($this->EE->TMPL->tagdata);
if (!!$name) {
// get params
$label = $this->EE->TMPL->fetch_param('label', $name);
$save = (bool) preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('save'));
$match = $this->EE->TMPL->fetch_param('match', NULL);
// regular expression to test value against
$against = $this->EE->TMPL->fetch_param('against', $this->EE->TMPL->tagdata);
// text to apply test against
$filter = $this->EE->TMPL->fetch_param('filter', NULL);
// regex pattern to search for
$default = $this->EE->TMPL->fetch_param('default', NULL);
// default value
$delimiter = $this->EE->TMPL->fetch_param('delimiter', '|');
// implode arrays using this delimiter
// cache refresh time
$refresh = (int) $this->EE->TMPL->fetch_param('refresh', $this->default_refresh);
// do we want to set a placeholder somewhere in this template ?
$set_placeholder = (bool) preg_match('/1|on|yes|y/i', $this->EE->TMPL->fetch_param('set_placeholder'));
// make sure we have a value to fallback to for output in current template
if ($set_placeholder && is_null($default)) {
$default = '';
}
// set refresh
if ($refresh > 0) {
$refresh = $this->EE->localize->now + $refresh * 60;
}
// regex match
if ($match !== NULL && preg_match('/^#(.*)#$/', $match)) {
$is_match = $this->_matches($match, $against);
// did it fail to match the filter?
if (!$is_match) {
// if a default has been specified fallback to it
if (!is_null($default)) {
$this->EE->TMPL->tagdata = $default;
} else {
return;
}
}
}
// regex filter
if ($filter !== NULL && !is_array($this->EE->TMPL->tagdata)) {
preg_match($filter, $this->EE->TMPL->tagdata, $found);
if (isset($found[1])) {
$this->EE->TMPL->tagdata = $found[1];
}
}
// make sure we're working with a string
// if we're setting a variable from a global ($_POST, $_GET etc), it could be an array
if (is_array($this->EE->TMPL->tagdata)) {
$this->EE->TMPL->tagdata = array_filter($this->EE->TMPL->tagdata, 'strlen');
$this->EE->TMPL->tagdata = implode($delimiter, $this->EE->TMPL->tagdata);
}
if ($this->_update) {
// We're updating a variable, so lets see if it's in the session or db
if (!array_key_exists($name, $this->_stash)) {
$this->_stash[$name] = $this->_run_tag('get', array('name', 'type', 'scope', 'context'));
}
// Append or prepend?
if ($this->_append) {
$this->_stash[$name] .= $this->EE->TMPL->tagdata;
} else {
$this->_stash[$name] = $this->EE->TMPL->tagdata . $this->_stash[$name];
}
} else {
$this->_stash[$name] = $this->EE->TMPL->tagdata;
}
// replace value into a {placeholder} anywhere in the current template?
if ($set_placeholder) {
$this->EE->TMPL->template = $this->EE->functions->var_swap($this->EE->TMPL->template, array($name => $this->_stash[$name]));
}
// allow user- and site- scoped variables to be saved to the db
// stop bots saving data to reduce unnecessary load on the server
if ($save && $scope !== 'local' && self::$_is_human) {
// optionally clean data before inserting
$parameters = $this->_stash[$name];
if ($this->xss_clean) {
$this->EE->security->xss_clean($parameters);
}
// what's the intended variable scope?
if ($scope === 'site') {
$session_filter = '_global';
} else {
$session_filter =& $this->_session_id;
}
// let's check if there is an existing record
$result = $this->EE->stash_model->get_key($stash_key, $this->bundle_id, $session_filter, $this->site_id);
if ($result !== FALSE) {
// yes record exists, but do we want to update it?
$update_key = FALSE;
// is the new variable value identical to the value in the cache?
// allow append/prepend if the stash key has been created *in this page load*
$cache_key = $stash_key . '_' . $this->bundle_id . '_' . $this->site_id . '_' . $session_filter;
if ($result !== $parameters && ($this->replace || $this->_update && $this->EE->stash_model->is_inserted_key($cache_key))) {
$update_key = TRUE;
}
if ($update_key) {
// update
$this->EE->stash_model->update_key($stash_key, $this->bundle_id, $session_filter, $this->site_id, $refresh, $parameters);
}
} else {
// no record - insert one
// Don't save if this template has a 404 header set from a redirect
if ($this->EE->output->out_type !== "404") {
$this->EE->stash_model->insert_key($stash_key, $this->bundle_id, $session_filter, $this->site_id, $refresh, $parameters, $label);
}
}
}
} else {
// no name supplied, so let's assume we want to set sections of content within tag pairs
// {stash:my_variable}...{/stash:my_variable}
$vars = array();
$tagdata = $this->EE->TMPL->tagdata;
// context handling
if ($context !== NULL) {
$prefix = $context . ':';
$this->EE->TMPL->tagparams['context'] = NULL;
} else {
$prefix = '';
}
// if the tagdata has been parsed, we need to generate a new array of tag pairs
// this permits dynamic tag pairs, e.g. {stash:{key}}{/stash:{key}}
if ($this->parse_complete) {
$tag_vars = $this->EE->functions->assign_variables($this->EE->TMPL->tagdata);
$tag_pairs = $tag_vars['var_pair'];
} else {
$tag_pairs =& $this->EE->TMPL->var_pair;
}
foreach ($tag_pairs as $key => $val) {
if (strncmp($key, 'stash:', 6) == 0) {
$pattern = '/' . LD . $key . RD . '(.*)' . LD . '\\/' . $key . RD . '/Usi';
preg_match($pattern, $tagdata, $matches);
if (!empty($matches)) {
// set the variable, but cleanup first in case there are any nested tags
$this->EE->TMPL->tagparams['name'] = $prefix . str_replace('stash:', '', $key);
$this->EE->TMPL->tagdata = preg_replace('/' . LD . 'stash:[a-zA-Z0-9\\-_]+' . RD . '(.*)' . LD . '\\/stash:[a-zA-Z0-9\\-_]+' . RD . '/Usi', '', $matches[1]);
$this->parse_complete = TRUE;
// don't allow tagdata to be parsed
$this->set();
}
}
}
// reset tagdata to original value
$this->EE->TMPL->tagdata = $tagdata;
unset($tagdata);
}
}
if (!!$name) {
if ($bundle !== NULL) {
if (!isset(self::$bundles[$bundle])) {
self::$bundles[$bundle] = array();
}
self::$bundles[$bundle][$name] = $this->_stash[$name];
}
$this->EE->TMPL->log_item('Stash: SET ' . $name . ' to value ' . $this->_stash[$name]);
}
if ($output) {
return $this->EE->TMPL->tagdata;
}
}