function smd_query($atts, $thing='') { global $thispage, $pretext, $smd_query_pginfo; extract(lAtts(array( 'column' => '', 'table' => '', 'where' => '', 'query' => '', 'form' => '', 'pageform' => '', 'pagevar' => 'pg', 'pagepos' => 'below', 'colsform' => '', 'escape' => '', 'strictfields' => '0', 'preparse' => '0', 'urlfilter' => '', 'urlreplace' => '', 'defaults' => '', 'delim' => ',', 'paramdelim' => ':', 'silent' => '0', 'count' => 'up', 'limit' => 0, 'offset' => 0, 'break' => '', 'wraptag' => '', 'label' => '', 'labeltag' => '', 'class' => '', 'debug' => '0', ),$atts)); // Grab the form or embedded $thing $thing = ($thing) ? $thing : fetch_form($form); $colsform = (empty($colsform)) ? '' : fetch_form($colsform); $pagebit = array(); if ($pageform) { $pagePosAllowed = array("below", "above"); $paging = 1; $pageform = fetch_form($pageform); $pagepos = str_replace('smd_', '', $pagepos); $pagepos = do_list($pagepos, $delim); foreach ($pagepos as $pageitem) { $pagebit[] = (in_array($pageitem, $pagePosAllowed)) ? $pageitem : $pagePosAllowed[0]; } } $urlfilter = (!empty($urlfilter)) ? do_list($urlfilter, $delim) : ''; $urlreplace = (!empty($urlreplace)) ? do_list($urlreplace, $delim) : ''; if ($debug > 0) { echo "++ URL FILTERS ++"; dmp($urlfilter); dmp($urlreplace); } // Process any defaults $spc = ($strictfields) ? 0 : 1; $defaults = do_list($defaults, $delim); $dflts = array(); foreach ($defaults as $item) { $item = do_list($item, $paramdelim); if ($item[0] == '') continue; if (count($item) == 2) { $dflts[$item[0]] = smd_query_parse($item[1], array(''), array(''), array(''), $spc); } } if ($debug > 0) { echo "++ DEFAULTS ++"; dmp($dflts); } // Get a list of fields to escape $escapes = do_list($escape, $delim); foreach ($escapes as $idx => $val) { if ($val == '') { unset($escapes[$idx]); } } $rs = array(); $out = array(); $colout = $finalout = array(); $pageout = ''; // query overrides column/table/where if ($query) { $query = smd_query_parse($query, $dflts, $urlfilter, $urlreplace, $spc); $rs = ($silent) ? @getRows($query, $debug) : getRows($query, $debug); } else { if ($column && $table) { // TODO: Perhaps doSlash() these? $column = smd_query_parse($column, $dflts, $urlfilter, $urlreplace, $spc); $table = smd_query_parse($table, $dflts, $urlfilter, $urlreplace, $spc); $where = smd_query_parse($where, $dflts, $urlfilter, $urlreplace, $spc); $where = ($where) ? $where : "1=1"; $rs = ($silent) ? @safe_rows($column, $table, $where, $debug) : safe_rows($column, $table, $where, $debug); } else { trigger_error("You must specify at least 1 'column' and a 'table'."); } } $numrows = count($rs); $truePart = EvalElse($thing, 1); if ($rs) { if ($debug > 1) { echo "++ QUERY RESULT SET ++"; dmp($numrows . " ROWS"); dmp($rs); } if ($limit > 0) { $keepsafe = $thispage; $total = $numrows - $offset; $numPages = ceil($total/$limit); $pg = (!gps($pagevar)) ? 1 : gps($pagevar); $pgoffset = $offset + (($pg - 1) * $limit); // send paging info to txp:newer and txp:older $pageout['pg'] = $pg; $pageout['numPages'] = $numPages; $pageout['s'] = $pretext['s']; $pageout['c'] = $pretext['c']; $pageout['grand_total'] = $numrows; $pageout['total'] = $total; $thispage = $pageout; } else { $pgoffset = $offset; } $rs = array_slice($rs, $pgoffset, (($limit==0) ? 99999 : $limit)); $pagerows = count($rs); $replacements = $repagements = $colreplacements = array(); $page_rowcnt = ($count=="up") ? 0 : $pagerows-1; $qry_rowcnt = ($count=="up") ? $pgoffset-$offset : $numrows-$pgoffset-1; $first_row = $qry_rowcnt + 1; foreach ($rs as $row) { foreach ($row as $colid => $val) { if ($page_rowcnt == 0 && $colsform) { $colreplacements['{'.$colid.'}'] = $colid; } // Construct the replacement arrays $replacements['{'.$colid.'}'] = (in_array($colid, $escapes) ? htmlspecialchars($val, ENT_QUOTES) : $val); if ($page_rowcnt == (($count=="up") ? $pagerows-1 : 0) && $pageform && $limit>0) { $prevpg = (($pg-1) > 0) ? $pg-1 : ''; $nextpg = (($pg+1) <= $numPages) ? $pg+1 : ''; $repagements['{smd_allrows}'] = $total; $repagements['{smd_pages}'] = $numPages; $repagements['{smd_prevpage}'] = $prevpg; $repagements['{smd_thispage}'] = $pg; $repagements['{smd_nextpage}'] = $nextpg; $repagements['{smd_row_start}'] = $first_row; $repagements['{smd_row_end}'] = $qry_rowcnt + 1; $repagements['{smd_rows_prev}'] = (($prevpg) ? $limit : 0); $repagements['{smd_rows_next}'] = (($nextpg) ? (($qry_rowcnt+$limit+1) > $total ? $total-$qry_rowcnt-1 : $limit) : 0); $smd_query_pginfo = $repagements; } } $replacements['{smd_allrows}'] = (($limit>0) ? $total : $numrows-$pgoffset); $replacements['{smd_rows}'] = $pagerows; $replacements['{smd_pages}'] = (($limit>0) ? $numPages : 1); $replacements['{smd_thispage}'] = (($limit>0) ? $pg : 1); $replacements['{smd_thisindex}'] = $page_rowcnt; $replacements['{smd_thisrow}'] = $page_rowcnt + 1; $replacements['{smd_cursorindex}'] = $qry_rowcnt; $replacements['{smd_cursor}'] = $qry_rowcnt + 1; if ($debug > 0) { echo "++ REPLACEMENTS ++"; dmp($replacements); } $out[] = ($preparse) ? strtr(parse($truePart), $replacements) : parse(strtr($truePart, $replacements)); $qry_rowcnt = ($count=="up") ? $qry_rowcnt+1 : $qry_rowcnt-1; $page_rowcnt = ($count=="up") ? $page_rowcnt+1 : $page_rowcnt-1; } if ($out) { if ($colreplacements) { $colout[] = ($preparse) ? strtr(parse($colsform), $colreplacements) : parse(strtr($colsform, $colreplacements)); } if ($repagements) { $pageout = ($preparse) ? strtr(parse($pageform), $repagements) : parse(strtr($pageform, $repagements)); } // Make up the final output if (in_array("above", $pagebit)) { $finalout[] = $pageout; } $finalout[] = doLabel($label, $labeltag).doWrap(array_merge($colout, $out), $wraptag, $break, $class); if (in_array("below", $pagebit)) { $finalout[] = $pageout; } // Restore the paging outside the plugin container if ($limit > 0) { $thispage = $keepsafe; } return join('', $finalout); } } else { return parse(EvalElse($thing, 0)); } return ''; } // Returns a string with any ? variables replaced with their globals // URL Variables are optionally run through preg_replace() to sanitize them. // $pat is an array of regex search patterns // $rep is an array of regex search repalcements (default = '', i.e. remove whatever matches) function smd_query_parse($item, $dflts=array(''), $pat=array(''), $rep=array(''), $lax=true) { global $pretext, $thisarticle, $thisimage, $thisfile, $thislink, $variable; $item = html_entity_decode($item); // Sometimes pesky Unicode is not compiled in. Detect if so and fall back to ASCII if (!@preg_match('/\pL/u', 'a')) { $modRE = ($lax) ? '/(\?)([A-Za-z0-9_\- ]+)/' : '/(\?)([A-Za-z0-9_\-]+)/'; } else { $modRE = ($lax) ? '/(\?)([\p{L}\p{N}\p{Pc}\p{Pd}\p{Zs}]+)/' : '/(\?)([\p{L}\p{N}\p{Pc}\p{Pd}]+)/'; } $numMods = preg_match_all($modRE, $item, $mods); for ($modCtr = 0; $modCtr < $numMods; $modCtr++) { $modChar = $mods[1][$modCtr]; $modItem = trim($mods[2][$modCtr]); $lowitem = strtolower($modItem); $urlvar = $svrvar = ''; if (gps($lowitem) != '') { $urlvar = doSlash(gps($lowitem)); if ($urlvar && $pat) { $urlvar = preg_replace($pat, $rep, $urlvar); } } if (serverSet($modItem) != '') { $svrvar = doSlash(serverSet($modItem)); if ($svrvar && $pat) { $svrvar = preg_replace($pat, $rep, $svrvar); } } if (isset($variable[$lowitem]) && $variable[$lowitem] != '') { $item = str_replace($modChar.$modItem, $variable[$lowitem], $item); } else if ($svrvar != '') { $item = str_replace($modChar.$modItem, $svrvar, $item); } else if (isset($thisimage[$lowitem]) && !empty($thisimage[$lowitem])) { $item = str_replace($modChar.$modItem, $thisimage[$lowitem], $item); } else if (isset($thisfile[$lowitem]) && !empty($thisfile[$lowitem])) { $item = str_replace($modChar.$modItem, $thisfile[$lowitem], $item); } else if (isset($thislink[$lowitem]) && !empty($thislink[$lowitem])) { $item = str_replace($modChar.$modItem, $thislink[$lowitem], $item); } else if (array_key_exists($lowitem, $pretext) && !empty($pretext[$lowitem])) { $item = str_replace($modChar.$modItem, $pretext[$lowitem], $item); } else if (isset($thisarticle[$lowitem]) && !empty($thisarticle[$lowitem])) { $item = str_replace($modChar.$modItem, $thisarticle[$lowitem], $item); } else if ($urlvar != '') { $item = str_replace($modChar.$modItem, $urlvar, $item); } else if (isset($dflts[$lowitem])) { $item = str_replace($modChar.$modItem, $dflts[$lowitem], $item); } else { $item = str_replace($modChar.$modItem, $modItem, $item); } } return $item; } // Convenience functions to check if there's a prev/next page defined. Could also use smd_if function smd_query_if_prev($atts, $thing) { global $smd_query_pginfo; $res = $smd_query_pginfo && $smd_query_pginfo['{smd_prevpage}'] != ''; return parse(EvalElse(strtr($thing, $smd_query_pginfo), $res)); } function smd_query_if_next($atts, $thing) { global $smd_query_pginfo; $res = $smd_query_pginfo && $smd_query_pginfo['{smd_nextpage}'] != ''; return parse(EvalElse(strtr($thing, $smd_query_pginfo), $res)); }