// ------------------------------------------------------------- // Iterate over arbitrary matching variables, either from TXP fields or on the URL line // by Stef Dawson function smd_each($atts, $thing='') { global $pretext, $thisarticle, $thisfile, $thislink, $variable; extract(lAtts(array( 'type' => 'field', 'include' => '', 'exclude' => '', 'match' => '', 'matchwith' => 'name', 'subset' => '0', 'collate' => '', 'form' => '', 'delim' => ',', 'paramdelim' => ':', 'outdelim' => ',', 'wraptag' => '', 'break' => '', 'class' => '', 'debug' => '0', ), $atts)); // Lookups for allowable options $matchOpts = array('name', 'value'); // Validate the options $thing = (empty($form)) ? $thing : fetch_form($form); $thing = (empty($thing)) ? '{var_value}' : $thing; $include = do_list($include, $delim); $include = ($include[0] == "") ? array() : $include; $exclude = do_list($exclude, $delim); $exclude = ($exclude[0] == "") ? array() : $exclude; $match = do_list($match, $delim); $match = ($match[0] == "") ? array() : $match; $matchwith = do_list($matchwith, $delim); foreach ($matchwith as $thismatch) { $matches[] = (in_array($thismatch,$matchOpts)) ? $thismatch : $matchOpts[0]; } $matches = array_unique($matches); // Set up collated quoting if necessary if ($collate) { $quotes = array('SMDNONE'); $collateOpts = do_list($collate, $delim); foreach ($collateOpts as $option) { $indexes = do_list($option, $paramdelim); $colType = array_shift($indexes); // Supplying 'quote' on its own will empty the relevant array, implying "ALL" fields are to be quoted switch ($colType) { case "quote": $quotes = $indexes; break; } } } // Make up an array of name => value pairs populated from the arrays of the chosen $types $types = array(); $vars = array(); $type = do_list($type, $delim); foreach ($type as $thistype) { switch ($thistype) { case "urlvar": if ($_POST) $vars = smd_each_grab($_POST, $vars, 'doSpecial, doStripTags', $delim, $subset); if ($_GET) $vars = smd_each_grab($_GET, $vars, 'doSpecial, doStripTags', $delim, $subset); break; case "svrvar": if ($_SERVER) $vars = smd_each_grab($_SERVER, $vars, 'doSpecial, doStripTags', $delim, $subset); break; case "cookie": if ($_COOKIE) $vars = smd_each_grab($_COOKIE, $vars, 'doSpecial, doStripTags', $delim, $subset); break; case "txpvar": if ($variable) $vars = smd_each_grab($variable, $vars, '', $delim, $subset); break; case "fixed": $newvars = array(); foreach ($include as $key => $value) { $subs = do_list($value, $paramdelim); if (count($subs) > 1) { $newvar = array_shift($subs); $extravars[$newvar] = join($delim, $subs); // The new variable's values have been extracted and stored, so overwrite the array entry with just the variable name $include[$key] = $newvar; } } if ($extravars) $vars = smd_each_grab($extravars, $vars, 'doStripTags', $delim, $subset); break; case "field": case "default": if ($thisfile) $vars = smd_each_grab($thisfile, $vars, '', $delim, $subset); if ($thislink) $vars = smd_each_grab($thislink, $vars, '', $delim, $subset); if ($pretext) $vars = smd_each_grab($pretext, $vars, '', $delim, $subset); if ($thisarticle) $vars = smd_each_grab($thisarticle, $vars, 'doStripTags', $delim, $subset); break; } } if ($debug) { echo "++ VARIABLE POOL ++"; dmp($vars); } // Filter the array if necessary into a smaller array of desired elements $filtervars = array(); // Named variables are always copied across if ($include) { foreach ($include as $thisname) { if ($thisname != "") { $re = '/('.$thisname.'(_[0-9]*)?)/'; $num = preg_match_all($re, join($delim,array_keys($vars)), $keynames); for ($ctr = 0; $ctr < $num; $ctr++) { $filtervars[$keynames[0][$ctr]] = $vars[$keynames[0][$ctr]]; } } } } // Any names/values matching $match are also added if ($match) { foreach ($vars as $key => $val) { if (in_array("name", $matches) && (!array_key_exists($key, $filtervars))) { foreach ($match as $thismatch) { if ($thismatch && strpos($key, $thismatch) !== false) { if ($debug) { dmp("ADDING ".$key." (from name) "); } $filtervars[$key] = $val; break; } } } // No point checking the values if the variable has already been added to the filtered list if (in_array("value", $matches) && (!array_key_exists($key, $filtervars))) { foreach ($match as $thismatch) { if ($thismatch && strpos($val, $thismatch) !== false) { if ($debug) { dmp ("ADDING ".$key." (from value) "); } $filtervars[$key] = $val; break; } } } } } // Remove any excluded variables if ($exclude) { foreach ($exclude as $thisname) { if ($thisname != "") { $re = '/('.$thisname.'(_[0-9]*)?)/'; $num = preg_match_all($re, join($delim,array_keys($filtervars)), $keynames); for ($ctr = 0; $ctr < $num; $ctr++) { if ($debug) { dmp("EXCLUDING ".$keynames[0][$ctr]); } unset ($filtervars[$keynames[0][$ctr]]); } } } } // If no filters are specified if (!$include && !$exclude && !$match) { $filtervars = $vars; } if ($debug && ($filtervars != $vars)) { echo "++ FILTERED VARS ++"; dmp($filtervars); } // Throw the name => value pairs at the form $out = array(); $collations = array(); $ctr = 1; $totalvars = count($filtervars); foreach ($filtervars as $key => $val) { $replacements = array( '{var_name}' => $key, '{var_value}' => $val, '{var_counter}' => $ctr, '{var_total}' => $totalvars, ); // Solos are items in the output form that require details from a specific row. Useful only in collation // mode, they are added to the replacements array on an as-needed basis to save space/time $soloRE = '/\{([a-z0-9_]+)#'.$ctr.'\}/'; $numSolos = preg_match_all($soloRE, $thing, $solos); for ($soloCtr = 0; $soloCtr < $numSolos; $soloCtr++) { $fieldname = '{'.$solos[1][$soloCtr].'#'.$ctr.'}'; $grabfield = '{'.$solos[1][$soloCtr].'}'; $replacements[$fieldname] = $replacements[$grabfield]; } if ($debug) { echo "++ REPLACEMENT #$ctr ++"; dmp($replacements); } // In collate mode the form is only parsed at the end: build a collosal multi-dimension array of all items here if ($collate) { foreach ($replacements as $defName => $defVal) { $collations[$defName][] = $defVal; } } else { $out[] = parse(strtr($thing, $replacements)); } $ctr++; } // Handle quoting of collations if ($collate) { foreach ($collations as $item => $list) { // Quote the lists if required $list = (empty($quotes) || in_array($item, $quotes)) ? doArray($list, 'doQuote') : $list; $collations[$item] = implode($outdelim, $list); } if ($debug) { echo "++ COLLATIONS ++"; dmp($collations); } $out[] = parse(strtr($thing, $collations)); } return doWrap($out, $wraptag, $break, $class); } // ------------------------------------------------------------- // Take an array of name-value pairs, process and combine them with what is already in $out. // Handle sub-lists as well function smd_each_grab($item, $out='', $proc='', $dlm=',', $sub=0) { $out = ($out) ? $out : array(); $proc = do_list($proc, $dlm); $proc = ($proc[0] == "") ? array() : $proc; while (list($key, $val) = each($item)) { $val = (is_array($val)) ? join($dlm, $val) : $val; if ($sub) { if ($sub == 1) { // Add the complete element before attempting to split it foreach($proc as $op) { $val = $op($val); } $out[$key] = $val; } $vals = do_list($val, $dlm); $ctr = 1; foreach ($vals as $subval) { foreach($proc as $op) { $subval = $op($subval); } $out[$key.'_'.$ctr++] = $subval; } } else { foreach($proc as $op) { $val = $op($val); } $out[$key] = $val; } } return $out; }