function smd_gallery($atts, $thing='') { global $pretext, $thisarticle, $img_dir; // ** LOOKUP TABLE // Holds database field as key index and plugin option names as value. // Use array_search to find if value exists and return correct key for use in db calls/array refs. $fieldMap = array( "txp_image.name" => "name", "txp_image.id" => "id", "txp_image.alt" => "alt", "txp_image.caption" => "caption", "txp_image.category" => "category", "txp_image.author" => "author", "txp_image.date" => "date", "txp_image.ext" => "ext", "txp_image.w" => "width", "txp_image.h" => "height", "txp_image.thumbnail" => "hasthumb", ); // Plugin options extract(lAtts(array( 'type' => 'image', 'delim' => ',', 'paramdelim' => ':', 'collatedelim' => ',', 'form' => '', 'id' => '', 'category' => '', 'directory' => '', 'match' => '', 'sublevel' => '0', 'sort' => 'category', 'offset' => '0', 'limit' => '0', 'maxlimit' => '99999', 'thumblimit' => '99999', 'thumboffset' => '0', 'thumb' => '0:1', 'thumbsize' => '', 'thumbchange' => '', // DEPRECATED 'thumbchangewraptag' => '', // DEPRECATED 'thumbchangeclass' => '', // DEPRECATED 'onchange' => 'category', 'onchangewraptag' => '', 'onchangeclass' => '', 'grouptag' => '', 'groupclass' => '', 'text' => '', 'collate' => '', 'combo' => '', 'paging' => '0', 'pageform' => '', 'pagepos' => 'below', 'navwraptag' => 'ul', 'navbreak' => 'li', 'navclass' => 'smd_gallery_nav', 'emptyclass' => 'empty', 'galleryid' => '?4:6', 'wraptag' => '', 'break' => '', 'class' => '', 'debug' => '0', ), $atts)); // Category relies on whether id has been specified or not. // lAtts() won't let us handle this logic so it has to be done manually $attemptMatch = (empty($category) && empty($id)) ? false : true; $category = isset($category) ? doSlash($category) : (($id=='') ? $pretext['c']: ''); // Handle forms and set a default tag if none specified $thing = (empty($form)) ? $thing : fetch_form($form); $thing = (empty($thing)) ? '' : $thing; // Paging init $pagePosAllowed = array("below", "above"); $pageout = array(); if ($pageform) { $paging = 1; $pageform = fetch_form($pageform); $pagepos = do_list($pagepos, $delim); foreach ($pagepos as $pageitem) { $pageout[] = (in_array($pageitem, $pagePosAllowed)) ? $pageitem : $pagePosAllowed[0]; } } // Temporary redirect for deprecated options $onchange = ($onchange) ? $onchange : $thumbchange; $onchangewraptag = ($onchangewraptag) ? $onchangewraptag : $thumbchangewraptag; $onchangeclass = ($onchangeclass) ? $onchangeclass : $thumbchangeclass; // onchange verification $onchange = do_list($onchange, $delim); $onchange = ($onchange[0] == "") ? array() : $onchange; $resetOpts = array(); foreach ($onchange as $resetOpt) { $resetOpts[$resetOpt] = ""; } // The gallery identifier is used for keeping track of next/prev thumbnail page links $gallID = ''; if ($galleryid == '' || substr($galleryid,0,1) == "?") { // Generate a (fairly likely) unique ID for this gallery instance $gallTmp = md5($category.$id.$directory.$match.$sublevel.$sort.$limit.$maxlimit); list($gallLen, $gallSkip) = explode(":", substr($galleryid,1)); $gallLen = (empty($gallLen)) ? "4" : $gallLen; $gallSkip = (empty($gallSkip)) ? "1" : $gallSkip; for ($idx = 0, $cnt = 0; $cnt < $gallLen; $cnt++, $idx = (($idx+$gallSkip) % strlen($gallTmp))) { $gallID .= $gallTmp[$idx]; } } else { $gallID = $galleryid; } $gallID = "smd_glry_".$gallID; // Avoid (already incredibly unlikely) namespace clashes // Set up the variables from the thumb option. // Don't use paramdelim here or the default option breaks $thumbOpts = do_list($thumb, ":"); if (count($thumbOpts) == 1) { $fullmod = ($thumbOpts[0] == 1) ? "t" : ""; $thumbmod = "t"; } else { $fullmod = ($thumbOpts[0] == 1) ? "t" : ""; $thumbmod = ($thumbOpts[1] == 1) ? "t" : ""; } // The manner of obtaining files differs if using directory vs category/id $rs = array(); if ($directory) { $rs = smd_doDirectory($directory, 0, $sublevel, $match, $delim); list($allImages, $numPages, $thumPage, $offset) = smd_getPage($rs, $gallID, $limit, $offset, $paging); $dirlimit = ($limit==0) ? $maxlimit : $limit; $postOrder = array(); $fixedOrder = 0; $randsort = false; } else { // Process categories/IDs and make up the crux of the where clause. // Clause order = IDs OR cats AND !cats AND !IDs $clause[] = '1=1'; $clauseOR = array(); // Surround each entry in the ID list with quotes and make an SQL "in" list $subinfo = ($sublevel) ? "image:".$sublevel : ''; list($idinc, $idexc) = smd_doList($id, true, '', true, $delim); list($catinc, $catexc) = smd_doList($category, false, $subinfo, true, $delim); if ($idinc) { $clauseOR[] = 'txp_image.id IN ('.implode(",", $idinc).')'; } if ($catinc) { $clauseOR[] = 'txp_image.category IN ('.implode(",", $catinc).')'; } if (!empty($clauseOR)) { $clause[] = ' ('.implode(" OR ", $clauseOR).') '; } $clause = implode(" AND ", $clause); $clause .= ($catexc) ? ' AND txp_image.category NOT IN ('.implode(",", $catexc).')' : ''; $clause .= ($idexc) ? ' AND txp_image.id NOT IN ('.implode(",", $idexc).')' : ''; // If a category/id option was chosen and they matched nothing, use a bogus category that should not exist. // This ensures that the plugin does the expected thing of matching nothing in the event it finds nothing. if ($clause == "1=1" && $attemptMatch) { $clause = 'txp_image.category = "smd_' .mt_rand(). '"'; } if ($debug > 1) { echo "++ INCLUDED/EXCLUDED IDs AND CATs ++"; dmp($idinc); dmp($idexc); dmp($catinc); dmp($catexc); } // Convert the sort into a valid sorting hierarchy. // Note that random is a special case and the following rules apply: // 1) Anything appearing before random is passed to the database query for ordering // 2) As soon as random is encountered, the rest of the sort string is ignored. // The resultset will be sorted randomly instead // 3) If random appears first in the list, the data is retrieved randomly then the // remaining options sort the resultset $clauseSort = array(); $postOrder = array(); $rule = "sql"; $postPrefix = "SORT_"; $fixedOrder = $randsort = false; $sort = do_list($sort, $delim); for ($idx = 0; $idx < count($sort); $idx++) { $sort_dir = explode(' ', $sort[$idx]); $direction = $colRef = ''; if (count($sort_dir) <= 1) { $sort_dir[1] = "asc"; } if ($rule == "sql") { $direction = ($sort_dir[1] == "desc") ? ' desc' : ' asc'; } else { $direction = ($sort_dir[1] == "desc") ? $postPrefix.'DESC' : $postPrefix.'ASC'; } switch ($sort_dir[0]) { case 'random': $rule = "post"; if ($idx == 0) { $clauseSort[] = 'rand()'; } else { $randsort = true; } break; case 'fixed': // 'fixed' only works on ids or categories $fixedOrder = ($id == '' && $category == '') ? false : true; break; default: $colRef = array_search($sort_dir[0], $fieldMap); break; } if ($rule == "sql") { if ($colRef != '') { $clauseSort[] = $colRef.$direction; } } else { if (!$randsort) { if ($colRef != '') { $postOrder[] = array("col" => $colRef, "sort" => $direction); } } } } if (count($clauseSort) > 0) { $clause .= ' ORDER BY ' . implode(",",$clauseSort); } if ($debug > 0) { echo "++ WHERE CLAUSE ++"; dmp($clause); } // The database fields required $fields = implode(",", array_keys($fieldMap)); // Time to grab the matching rows from the database // $rs = safe_rows($fields.', txp_category.title AS category_title', 'txp_image, txp_category', (($category) ? 'txp_category.name = txp_image.category AND ' : ''). 'txp_category.type="image" AND ' .$clause .' LIMIT 0,'. $maxlimit, $debug); $rs = safe_rows("DISTINCT ".$fields. (($category) ? ', txp_category.title AS category_title': ''), 'txp_image, txp_category', (($category) ? 'txp_category.name = txp_image.category AND ' : ''). 'txp_category.type="image" AND ' .$clause .' LIMIT 0,'. $maxlimit, $debug); list($allImages, $numPages, $thumPage, $offset) = smd_getPage($rs, $gallID, $limit, $offset, $paging); } // Is post-ordering required? Do it if ($randsort) { shuffle($rs); } else if (count($postOrder) > 0) { // Translate the rows into columns that can be sorted foreach($rs as $key => $row) { $col_id[$key] = $row['id']; $col_name[$key] = $row['name']; $col_caption[$key] = $row['caption']; $col_alt[$key] = $row['alt']; $col_category[$key] = $row['category']; $col_date[$key] = $row['date']; $col_ext[$key] = $row['ext']; $col_author[$key] = $row['author']; $col_w[$key] = $row['w']; $col_h[$key] = $row['h']; $col_thumbnail[$key] = $row['thumbnail']; } // Make up an array_multisort arg list and execute it for ($idx = 0; $idx < count($postOrder); $idx++) { $sortargs[] = '$col_'.$postOrder[$idx]['col']; $sortargs[] = $postOrder[$idx]['sort']; } $sortit = 'array_multisort('.implode(", ",$sortargs).', $rs);'; eval($sortit); } // Is fixed-order output desired? If so, re-order the $rs if ($fixedOrder) { $orderedRS = Array(); $ignoreList = Array(); $remainingRS = Array(); // Suck out the fixed items first. IDs then categories for ($idx = 0; $idx < count($idinc); $idx++) { foreach($rs as $row) { if ($id && doQuote($row['id']) == $idinc[$idx]) { $orderedRS[] = $row; $ignoreList[] = $row['id']; break; } } } for ($idx = 0; $idx < count($catinc); $idx++) { foreach($rs as $row) { if ($category && doQuote($row['category']) == $catinc[$idx]) { $orderedRS[] = $row; $ignoreList[] = $row['id']; } } } // Tack on the remaining rows foreach($rs as $row) { if (!in_array($row['id'], $ignoreList)) { $remainingRS[] = $row; } } $rs = array_merge($orderedRS, $remainingRS); } // Grab the portion of the record set actually required to iterate over $rs = array_slice($rs, $offset, (($directory) ? $dirlimit : (($limit==0) ? $maxlimit : $limit))); // Handle thumbsize - of limited use now but still available $thumbWidth = $thumbHeight = ''; $thumbWUnits = $thumbHUnits = ''; if ($thumbsize) { $thumbSizes = do_list($thumbsize, $delim); if (count($thumbSizes) == 1) { $thumbWidth = $thumbHeight = ereg_replace("[^0-9]", '', $thumbSizes[0]); $units = ereg_replace("[0-9]", '', $thumbSizes[0]); $thumbWUnits = $thumbHUnits = ($units == '') ? $thumbWUnits : $units; } else { $thumbWidth = ereg_replace("[^0-9]", '', $thumbSizes[0]); $thumbHeight = ereg_replace("[^0-9]", '', $thumbSizes[1]); $units = ereg_replace("[0-9]", '', $thumbSizes[0]); $thumbWUnits = ($units == '' && $thumbWidth != '') ? $thumbWUnits : $units; $units = ereg_replace("[0-9]", '', $thumbSizes[1]); $thumbHUnits = ($units == '' && $thumbHeight != '') ? $thumbHUnits : $units; } } // Collation defers parsing the form for each returned item. // Instead it outputs the data as a list at the end (items may be individually quoted or extracted if required) //TODO : Add ALWAYS switch as a shortcut to specify that all matching items (regardless of #1, #2, #3 etc) are to be quoted if ($collate) { $dblQuote = $sglQuote = 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 "sglquote": $sglQuote = $indexes; break; case "dblquote": case "quote": $dblQuote = $indexes; break; } } } // Combos are user-defined combinations of replacement modifiers (e.g. idext: {id}{ext}, ... $combos = array(); if ($combo) { $combo = do_list($combo, $delim); foreach ($combo as $newDef) { list($defParts, $unwanted) = smd_doList($newDef, false, '', false, $paramdelim); $defName = "{".array_shift($defParts)."}"; $combos[$defName] = $defParts[0]; } } if ($debug > 1) { echo "++ COMBOs ++"; dmp($combos); } // Construct the output $thumbout = array(); $groupout = array(); $navout = array(); $out = array(); $collations = array(); $chIdentifier = ($thumbchange) ? "changed" : "onchange"; // TODO: Fix when $thumbchange is removed if ($debug > 2) { echo "++ RECORD SET ++"; dmp($rs); } if ($debug > 3) { echo "++ AVAILABLE '?' VARS ++"; dmp($pretext); dmp($thisarticle); } if($rs) { $idx = 0; $ctr = 1; $thumbIdx = 0; $thumbCtr = 1; $numImages = count($rs); $repagements = array(); // Set up the paging features if required if (($limit > 0) && $paging) { $next = ($numPages > 1 && $thumPage != $numPages); $prev = ($numPages > 1 && $thumPage > 1); // Replace any paging info in the query string $prevPage = smd_addQSVar($pretext['request_uri'], $gallID, $thumPage-1); $nextPage = smd_addQSVar($pretext['request_uri'], $gallID, $thumPage+1); $thisPage = smd_addQSVar($pretext['request_uri'], $gallID, $thumPage); $firstPage = smd_addQSVar($pretext['request_uri'], $gallID, 1); $lastPage = smd_addQSVar($pretext['request_uri'], $gallID, $numPages); // Labels can be specified in the replacement tag after a paramdelim. // 'earlier' and 'later' don't have labels. Anything specified after paramdelim is the max number of pages to show; empty = all pages $label = array( '{navfirst}' => 'First', '{navprev}' => '«', '{navearlier}' => '', '{navthis}' => $thumPage, '{navthisurl}' => $thumPage, '{navlater}' => '', '{navnext}' => '»', '{navlast}' => 'Last', ); $labelRE = '/\{(nav[a-z]+)'.$paramdelim.'(.+?)\}/'; $numLabels = preg_match_all($labelRE, $pageform, $labels); for ($labelCtr = 0; $labelCtr < $numLabels; $labelCtr++) { $fieldname = '{'.$labels[1][$labelCtr].'}'; $label[$fieldname] = $labels[2][$labelCtr]; $pageform = str_replace($labels[0][$labelCtr], '{'.$labels[1][$labelCtr].'}', $pageform); } if ($debug > 1) { echo "++ PAGING LABELS ++"; dmp($label); } // Generate 'earlier' and 'later' lists $numEarlier = intval($label['{navearlier}']); $numLater = intval($label['{navlater}']); $numEarlier = ($numEarlier && ($thumPage-$numEarlier > 1)) ? $numEarlier : $thumPage-1; $numLater = ($numLater && ($thumPage+$numLater < $numPages)) ? $numLater : $numPages-$thumPage; $navEarlier = $navLater = array(); for ($cod = $thumPage-$numEarlier; $cod < $thumPage; $cod++) { $navEarlier[] = ''.$cod.''; } for ($cod = $thumPage+1; $cod <= $thumPage+$numLater; $cod++) { $navLater[] = ''.$cod.''; } $navEarlier = doWrap($navEarlier, '', $navbreak, ''); $navLater = doWrap($navLater, '', $navbreak, ''); // Make up the repagements array for pageform $repagements = array( '{navfirst}' => (($prev) ? doTag(''.$label['{navfirst}'].'', $navbreak) : doTag($label['{navfirst}'], $navbreak, $emptyclass)), '{navprev}' => (($prev) ? doTag(''.$label['{navprev}'].'', $navbreak) : doTag($label['{navprev}'], $navbreak, $emptyclass)), '{navearlier}' => $navEarlier, '{navthis}' => doTag($label['{navthis}'], $navbreak, 'current '.$emptyclass), '{navthisurl}' => doTag(''.$label['{navthisurl}'].'', $navbreak, 'current'), '{navlater}' => $navLater, '{navnext}' => (($next) ? doTag(''.$label['{navnext}'].'', $navbreak) : doTag($label['{navnext}'], $navbreak, $emptyclass)), '{navlast}' => (($next) ? doTag(''.$label['{navlast}'].'', $navbreak) : doTag($label['{navlast}'], $navbreak, $emptyclass)), '{navthispageurl}' => $thisPage, '{navnextpageurl}' => (($next) ? $nextPage : ''), '{navprevpageurl}' => (($prev) ? $prevPage : ''), '{navfirstpageurl}' => $firstPage, '{navlastpageurl}' => $lastPage, '{totalimages}' => $numImages, '{totalpages}' => $numPages, '{maximages}' => $allImages, ); // Perform the substitutions $navout[] = parse(strtr($pageform, $repagements)); } // For every image in the gallery... foreach($rs as $key => $row) { if ($directory) { $urlPath = $row['path'].'/'; } else { $urlPath = hu.$img_dir.'/'; } $theThumb = $urlPath . $row['id'] . $thumbmod . $row['ext']; $fullSize = $urlPath . $row['id'] . $fullmod .$row['ext']; // Do we need to reset the thumb counter this time? foreach ($resetOpts as $resetOpt => $resetVal) { if ($row[$resetOpt] != $resetVal) { $thumbIdx = 0; $thumbCtr = 1; break; } } // Is a thumb/text object required this time? $object = ''; if ($thumbIdx >= $thumboffset && $thumbIdx < $thumboffset+$thumblimit) { switch ($type) { case 'image': $object = ($text) ? $text : ''.$row['alt'].''; break; } } // Construct the replacement array $replacements = array( '{id}' => $row['id'], '{name}' => $row['name'], '{ext}' => $row['ext'], '{category}' => $row['category'], '{category_title}' => ((isset($row['category_title'])) ? $row['category_title'] : ''), '{author}' => $row['author'], '{hasthumb}' => $row['thumbnail'], '{url}' => $fullSize, '{thumburl}' => $theThumb, '{imagepath}' => $urlPath, '{imagedef}' => basename($fullSize), '{thumbdef}' => basename($theThumb), '{alt}' => $row['alt'], '{title}' => $row['caption'], '{thumbwidth}' => $thumbWidth, '{thumbheight}' => $thumbHeight, '{thumbwunits}' => $thumbWUnits, '{thumbhunits}' => $thumbHUnits, '{width}' => $row['w'], '{height}' => $row['h'], '{date}' => $row['date'], '{object}' => $object, '{galleryid}' => $gallID, '{index}' => $idx, '{counter}' => $ctr, '{thumbindex}' => $thumbIdx, '{thumbcounter}' => $thumbCtr, '{totalimages}' => $numImages, '{maximages}' => $allImages, ); // Append any changed items that are required $endtag = false; foreach ($resetOpts as $resetOpt => $resetVal) { $replacements['{'.$chIdentifier.$paramdelim.$resetOpt.'}'] = ($thumbIdx == 0) ? doTag($row[$resetOpt], $onchangewraptag, $onchangeclass) : ''; // Do a sneaky (yuk) lookahead if (isset($rs[$key+1])) { if($rs[$key+1][$resetOpt] != $row[$resetOpt]) { $endtag = true; } } else { $endtag = true; // Last image } } $replacements['{grouptagend}'] = ($grouptag && $endtag) ? '' : ''; $replacements['{grouptagstart}'] = ($grouptag && $thumbIdx == 0) ? '<' . $grouptag . (($groupclass) ? ' class="'.$groupclass.'"' : '') . '>' : ''; // Append any combos foreach ($combos as $defName => $newDef) { if (!array_key_exists($defName, $replacements)) { $replacements[$defName] = strtr($newDef, $replacements); } } // 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]; } // Add the navigation items if they're defined if (count($repagements) > 0) { $replacements = array_merge($repagements, $replacements); } if ($debug > 0) { echo "++ REPLACEMENTS : IMAGE ".$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 { $thumbout[] = parse(strtr($thing, $replacements)); } // Keep track of the current values so we know if they change next time foreach ($resetOpts as $resetOpt => $resetVal) { $resetOpts[$resetOpt] = $row[$resetOpt]; } $thumbIdx++; $thumbCtr++; $idx++; $ctr++; } if ($collate) { foreach ($collations as $item => $list) { // Quote the lists if required $list = (empty($dblQuote) || in_array($item, $dblQuote)) ? doArray($list, 'smd_doDblQuote') : $list; $list = (empty($sglQuote) || in_array($item, $sglQuote)) ? doArray($list, 'doQuote') : $list; $collations[$item] = implode($collatedelim, $list); } if ($debug > 0) { echo "++ COLLATIONS ++"; dmp($collations); } $thumbout[] = parse(strtr($thing, $collations)); } // Tack on the paging from earlier if it's to go afterwards if (($limit > 0) && $paging) { if ($debug > 0) { echo "++ PAGING REPLACEMENTS ++"; dmp($repagements); } } } // Add the paging to the output if it's to go above the thumbs if (($limit > 0) && $paging) { if (in_array("above", $pageout)) { $out[] = doWrap($navout, $navwraptag, '', $navclass); } } $out[] = doWrap($thumbout, $wraptag, $break, $class); if (($limit > 0) && $paging) { if (in_array("below", $pageout)) { $out[] = doWrap($navout, $navwraptag, '', $navclass); } } if ($debug > 2) { echo "++ FINAL OUTPUT ++"; dmp($out); } return join(" ", $out); } // Return an expanded list of items: // 1) Anything containing '?' or '!' is checked for a match with a TXP field // 2) Any ranges of items are expanded (e.g. 4-7 = 4,5,6,7) // 3) TXP fields may themselves be lists or ranges // 4) Anything that is not a TXP field is used verbatim // 5) The items are returned as 2 lists; inclusion and exclusion // Args: // lst = the list as a delimited string // rng = whether to allow ranges or not (bool) // sub = the type of subcategory to traverse (image, file, link, article, none="") and how many levels to go down (e.g. image:2) // qte = whether to quote each item in the array or not (bool) // dlm = the delimiter (string) if (!function_exists("smd_doList")) { function smd_doList($lst, $rng=true, $sub="", $qte=true, $dlm=",") { global $thisarticle, $pretext; $inc = $exc = array(); $lst = do_list($lst, $dlm); $modRE = '/(\?|\!)([A-Za-z0-9_\- ]+)/'; foreach ($lst as $item) { $mod = 0; // 0 = include, 1 = exclude $numMods = preg_match_all($modRE, $item, $mods); for ($modCtr = 0; $modCtr < $numMods; $modCtr++) { // mod "type" is governed by the first one found only. i.e. if "article-?c!s" was used in one field // it would be an "include" of the word "article-" plus the category and section concatenated $mod = ($mods[1][0] === "!") ? 1 : 0; $modChar = $mods[1][$modCtr]; $modItem = trim($mods[2][$modCtr]); $lowitem = strtolower($modItem); if (array_key_exists($lowitem, $pretext)) { $item = str_replace($modChar.$modItem, $pretext[$lowitem], $item); } else if (isset($thisarticle[$lowitem])) { $item = str_replace($modChar.$modItem, $thisarticle[$lowitem], $item); } else { $item = str_replace($modChar.$modItem, $modItem, $item); } } // Handle ranges of values if ($rng && preg_match('/^(\d+)\-(\d+)$/', $item)) { list($lo, $hi) = explode("-", $item, 2); $item = implode($dlm, range($lo, $hi)); } // Item may be empty; ignore it if so if ($item) { $item = do_list($item, $dlm); // Handle sub-categories if ($sub) { list($subtype, $level) = explode(":", $sub); $level = (empty($level)) ? 0 : $level; $level = (strtolower($level)=="all") ? 99999 : $level; foreach ($item as $cat) { $cats = getTree(doslash($cat), $subtype); foreach ($cats as $jdx => $val) { if ($cats[$jdx]['level'] <= $level) { $item[] = $cats[$jdx]['name']; } } } } // Quote if asked $item = ($qte) ? doArray($item, 'doQuote') : $item; if ($mod === 0) { $inc = array_unique(array_merge($inc, $item)); } else { $exc = array_unique(array_merge($exc, $item)); } } } return array($inc, $exc); } } // Alternative to the core's doQuote(). This one dbl-quotes instead of sgl-quotes if (!function_exists("smd_doDblQuote")) { function smd_doDblQuote($val) { return '"'.$val.'"'; } } // Work out which page this gallery is on and return the relevant info function smd_getPage($rs, $gallID, $limit, $offset, $paging) { $numThums = count($rs); if (($limit > 0) && $paging) { $numPages = ($numThums > 0) ? ceil($numThums/$limit) : 1; $thumPage = (!gps($gallID)) ? 1 : gps($gallID); $offset = ($thumPage - 1) * $limit; } else { // No paging required $numPages = 1; $thumPage = 1; } return array($numThums, $numPages, $thumPage, $offset); } // Read the given delimited directories and get all files that match. // Go down as many subdir levels as given in the $sub parameter function smd_doDirectory($lst, $lvl=0, $sub=0, $match="", $dlm=",", $ctr=0) { list($dirinc, $direxc) = smd_doList($lst, false, $sub, false, $dlm); list($matchinc, $matchexc) = smd_doList($match, false, '', false, $dlm); $matchinc = ".*" .(($matchinc) ? "(" .implode("|",$matchinc).")+.*" : ""); $matchexc = ($matchexc) ? ".*(" .implode("|",$matchexc).")+.*" : "smd_glry_".mt_rand(); $sub = (empty($sub)) ? 0 : $sub; $sub = (strtolower($sub)=="all") ? 99999 : $sub; $fileList = array(); foreach ($dirinc as $dir) { if ($handle = @opendir($dir)) { while (($file = @readdir($handle)) !== false) { $fullpath = $dir.DS.$file; if (preg_match("/".$matchinc."/", $fullpath) && !preg_match("/".$matchexc."/", $fullpath)) { if (is_dir($fullpath)) { if (($file == ".") || ($file== "..") || (in_array($file, $direxc)) || ($lvl >= $sub)) { continue; } else { // Recurse the subdir. Note that the '!' is temporarily added back to each direxc item $tmp = $direxc; // Don't overwrite the original array array_unshift($tmp, $fullpath); $subFiles = smd_doDirectory(implode($dlm."!", $tmp), $lvl+1, $sub, $match, $dlm, $ctr); $fileList = array_merge($fileList, $subFiles); $ctr += count($subFiles); continue; } } else { $filestat = stat($fullpath); $imgsize = getimagesize($fullpath); $fileList[$ctr]['path'] = $dir; $fileList[$ctr]['name'] = basename($fullpath); $fileList[$ctr]['id'] = preg_replace('/\..+$/', '', $file); $fileList[$ctr]['alt'] = ''; $fileList[$ctr]['caption'] = ''; $parts = explode(DS, $dir); $fileList[$ctr]['category'] = (count($parts) > 1) ? end($parts) : ''; $fileList[$ctr]['author'] = strval($filestat['uid']); $fileList[$ctr]['date'] = strftime("%Y-%m-%d %H:%M:%S", $filestat['ctime']); $parts = explode(".", $file); $fileList[$ctr]['ext'] = (count($parts) > 1) ? ".".end($parts) : ''; $fileList[$ctr]['w'] = (is_array($imgsize)) ? strval($imgsize[0]) : ''; $fileList[$ctr]['h'] = (is_array($imgsize)) ? strval($imgsize[1]) : ''; } $ctr++; } } } if ($handle) { @closedir($handle); } } return $fileList; } if (!function_exists("smd_removeQSVar")) { function smd_removeQSVar($url, $key) { $url = preg_replace('/(.*)(\?|&)' . $key . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&'); $url = substr($url, 0, -1); return ($url); } } if (!function_exists("smd_addQSVar")) { function smd_addQSVar($url, $key, $value) { $url = smd_removeQSVar($url, $key); if (strpos($url, '?') === false) { return ($url . '?' . $key . '=' . $value); } else { return ($url . '&' . $key . '=' . $value); } } }