/** * Process the variable stack scope (pagevars, stackvars). * * @param array $postvars The http request variables. */ protected function _stackscope(&$postvars) { $sessionData =& self::getSession(); // session vars are valid until they are set to something else. if you go a session level higher, // the next level will still contain these vars (unless overriden in the url) $sessionVars = array('atknodeuri', 'atkfilter', 'atkaction', 'atkpkret', 'atkstore', 'atkstore_key'); // pagevars are valid on a page. if you go a session level higher, the pagevars are no longer // visible until you return. if the name ends in a * the pagevar is treated as an array that // needs to be merged recursive with new postvar values $pageVars = array('atkdg*', 'atkdgsession', 'atksearch', 'atkselector', 'atksearchmode', 'atkorderby', 'atkstartat', 'atklimit', 'atktarget', 'atkformdata', 'atktree', 'atksuppress', 'atktab', 'atksmartsearch', 'atkindex'); // lockedvars are session or page vars that will not be overwritten in partial mode // e.g., the values that are already known in the session will be used $lockedVars = array('atknodeuri', 'atkaction', 'atkselector'); // Mental note: We have an $this->atkLevel() function for retrieving the atklevel, // but we use the global var itself here, because it gets modified in // the stackscope function. if (!isset($this->atklevel) || $this->atklevel == '') { $this->atklevel = 0; } Tools::atkdebug('ATKLevel: ' . $this->atklevel); if ($this->_verifyStackIntegrity() && $this->atklevel == -1) { // New stack, new stackid, if level = -1. $stackid = $this->atkStackID($this->atklevel == -1); } else { $stackid = $this->atkStackID(); } $stack =& $sessionData[$this->m_namespace]['stack'][$stackid]; // garbage collect $this->_touchCurrentStack(); $this->_removeExpiredStacks(); // Prevent going more than 1 level above the current stack top which // causes a new stackitem to be pushed onto the stack at the wrong // location. if ($this->atklevel > count($stack)) { Tools::atkdebug('Requested ATKLevel (' . $this->atklevel . ') too high for stack, lowering to ' . count($stack)); $this->atklevel = count($stack); } if (isset($postvars['atkescape']) && $postvars['atkescape'] != '') { $this->m_escapemode = true; Tools::atkdebug('ATK session escapemode'); $currentitem =& $stack[count($stack) - 1]; Tools::atkdebug('Saving formdata in session'); unset($currentitem['atkreject']); // clear old reject info $atkformdata = []; foreach (array_keys($postvars) as $varname) { // Only save formdata itself, hence no $atk.. variables. // Except atktab because it could be changed in the page load. // but why don't we save all page vars here? What is the reason for // not doing this? TODO: Ask Ivo. if (substr($varname, 0, 3) != 'atk' || $varname == 'atktab') { $atkformdata[$varname] = $postvars[$varname]; } } $currentitem['atkformdata'] = $atkformdata; // also remember getvars that were passed in the url // this *may not be* $_REQUEST, because then the posted vars // will be overwritten, which may not be done in escape mode, // I wonder if the next few lines are necessary at all, but // I think I needed them once, so I'll leave it in place. foreach (array_keys($_GET) as $var) { if (isset($postvars[$var]) && $postvars[$var] != '') { $currentitem[$var] = $postvars[$var]; } } // finally, reset atkescape to prevent atk from keeping escaping upon return unset($currentitem['atkescape']); } else { // partial mode? $partial = false; if ($this->atklevel == -1 || !is_array($stack)) { // SessionManager::SESSION_NEW Tools::atkdebug('Cleaning stack'); $stack = []; $this->atklevel = 0; } else { if ($this->atklevel == -2) { // SessionManager::SESSION_REPLACE // Replace top level. array_pop($stack); // Note that the atklevel is now -2. This is actually wrong. We are at // some level in the stack. We can determine the real level by // counting the stack. $this->atklevel = count($stack); } else { if ($this->atklevel == -3) { // SessionManager::SESSION_PARTIAL $partial = true; // Note that the atklevel is now -3. This is actually wrong. We are at // some level in the stack. We can determine the real level by // counting the stack. $this->atklevel = count($stack) - 1; } } } if (isset($stack[$this->atklevel])) { $currentitem = $stack[$this->atklevel]; } if (!isset($currentitem) || $currentitem == '') { Tools::atkdebug('New level on session stack'); // Initialise $currentitem = []; // new level.. always based on the previous level if (isset($stack[count($stack) - 1])) { $copieditem = $stack[count($stack) - 1]; } if (isset($copieditem) && is_array($copieditem)) { foreach ($copieditem as $key => $value) { if (in_array($key, $sessionVars) || isset($copieditem['defined_stackvars']) && is_array($copieditem['defined_stackvars']) && in_array($key, $copieditem['defined_stackvars'])) { $currentitem[$key] = $value; } } if (isset($copieditem['defined_stackvars'])) { $currentitem['defined_stackvars'] = $copieditem['defined_stackvars']; } } // Posted vars always overwrite anything in the current session.. foreach (array_merge($pageVars, $sessionVars) as $var) { $recursive = $var[strlen($var) - 1] == '*'; $var = $recursive ? substr($var, 0, -1) : $var; if (isset($postvars[$var]) && $postvars[$var] != '') { if ($postvars[$var] == 'clear') { $currentitem[$var] = ''; } else { if ($recursive && is_array($currentitem[$var]) && is_array($postvars[$var])) { $currentitem[$var] = array_merge_recursive($currentitem[$var], $postvars[$var]); } else { $currentitem[$var] = $postvars[$var]; } } } } array_push($stack, $currentitem); } else { // Stay at the current level.. // If we are getting back from a higher level, we may now delete everything above $deletecount = count($stack) - 1 - $this->atklevel; for ($i = 0; $i < $deletecount; ++$i) { Tools::atkdebug('popped an item out of the stack'); array_pop($stack); } foreach ($pageVars as $var) { $recursive = $var[strlen($var) - 1] == '*'; $var = $recursive ? substr($var, 0, -1) : $var; if (isset($postvars[$var]) && count($postvars[$var]) > 0 && (!$partial || !in_array($var, $lockedVars))) { if ($recursive && isset($currentitem[$var]) && is_array($currentitem[$var]) && is_array($postvars[$var])) { $currentitem[$var] = Tools::atk_array_merge_recursive($currentitem[$var], $postvars[$var]); } else { $currentitem[$var] = $postvars[$var]; } } } // page vars must overwrite the current stack.. $stack[$this->atklevel] =& $currentitem; // session vars need not be remembered.. foreach ($sessionVars as $var) { if (isset($postvars[$var]) && count($postvars[$var]) > 0 && (!$partial || !in_array($var, $lockedVars))) { $currentitem[$var] = $postvars[$var]; } } } if (isset($currentitem['atkformdata']) && is_array($currentitem['atkformdata'])) { Tools::atkdebug('Session formdata present'); foreach ($currentitem['atkformdata'] as $var => $value) { // don't override what was passed in the url. if (!isset($postvars[$var])) { $postvars[$var] = $value; } else { if (is_array($postvars[$var]) && is_array($value)) { // Formdata that was posted earlier needs to be merged with the current // formdata. We use a custom array_merge here to preserve key=>value pairs. $postvars[$var] = Tools::atk_array_merge_keys($value, $postvars[$var]); } } } // We leave atkformdata in the current stack entry untouched so that // when the stack might be forked of whatsoever the form data is still // present. However, this data should not be directly accessed in the node! } if (is_array($currentitem)) { foreach ($currentitem as $var => $value) { $recursive = in_array("{$var}*", $pageVars); // don't override what was passed in the url except for // recursive mergeable pagevars if ($recursive || !isset($postvars[$var])) { $postvars[$var] = $value; } } } } // end if atkescape }