require_plugin('smd_lib');
// MLP support
global $smd_gallLang;
$smd_gallStr = array(
'navfirst' => 'First',
'navlast' => 'Last',
'navprev' => '«',
'navnext' => '»',
);
$smd_gallLang = new smd_MLP('smd_gallery', 'smd_gall', $smd_gallStr);
function smd_gallery($atts, $thing='') {
global $pretext, $thisarticle, $img_dir, $dateformat, $smd_gallLang, $l10n_language;
// Plugin options
extract(lAtts(array(
'columns' => '',
'delim' => ',',
'paramdelim' => ':',
'collatedelim' => ',',
'strictfields' => '0',
'form' => '',
'countform' => '',
'countpos' => 'above',
'id' => '',
'category' => '',
'aspect' => '',
'author' => '',
'dimensions' => '',
'extension' => '',
'directory' => '',
'match' => '',
'sublevel' => '0',
'escape' => 'alt, title, caption',
'sort' => '',
'offset' => '0',
'limit' => '0',
'maxlimit' => '99999',
'thumblimit' => '99999',
'thumboffset' => '0',
'thumb' => '0:1',
'thumbsize' => '',
'imgsize' => '',
'onchange' => 'category',
'onchangewraptag' => '',
'onchangeclass' => '',
'objectform' => '',
'grouptag' => '',
'groupclass' => '',
'text' => '',
'format' => $dateformat,
'gmt' => '',
'lang' => '',
'collate' => '',
'combo' => '',
'paging' => '0',
'pageform' => '',
'pagepos' => 'below',
'navwraptag' => 'ul',
'navbreak' => 'li',
'navclass' => 'smd_gallery_nav',
'emptyclass' => 'empty',
'galleryid' => '?4:6',
'wraptag' => '',
'html_id' => '',
'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']: '');
$sort = ($sort) ? $sort : ( ($id) ? 'id' : 'category' );
// ** LOOKUP TABLES
// $fieldMap holds database column as key, and replacement identifier as value.
// Additional cols copied to $extraMap for iteration while creating replacements.
// Use array_search to find if value exists and return correct key for use in db calls/array refs.
$fieldMap = array();
$extraMap = array();
$coreCols = array("name", "id", "alt", "caption", "category", "author", "date", "ext", "w:width", "h:height", "thumb_w:thumb_width", "thumb_h:thumb_height", "thumbnail:hasthumb");
$mlpFields = array("alt", "caption"); // Manually create the MLP column names, since using getRows() later does not. Category title also has the same treatment
$thislang = (isset($l10n_language['long'])) ? $l10n_language['long'] : LANG;
$dflt_tbl = PFX."txp_image";
$columns = do_list($columns);
foreach (array_merge($coreCols, $columns) as $colinfo) {
$colbit = do_list($colinfo, ":");
$coltbl = do_list($colbit[0], ".");
if ($colbit[0] == '') continue;
if (count($coltbl) > 1) {
$tbl = $coltbl[0];
$colname = $coltbl[1];
} else {
$tbl = $dflt_tbl;
$colname = $coltbl[0];
}
$colid = (count($colbit) > 1) ? $colbit[1] : $colname;
$fieldMap[(($tbl)?$tbl.'.':'').( (isset($l10n_language['long']) && in_array($colname, $mlpFields)) ? _l10n_make_field_name($colname, $thislang). ' AS '.$colname : $colname )] = $colid;
if (!in_array($colinfo, $coreCols)) {
$extraMap[$colname] = $colid;
}
}
$fieldMap = array_unique($fieldMap);
// Handle forms and set a default tag if none specified
$thing = (empty($form)) ? $thing : fetch_form($form);
$thing = (empty($thing)) ? '' : $thing;
$objectform = (empty($objectform)) ? '' : fetch_form($objectform);
// Counting
$countPosAllowed = array("above", "below");
$countposns = array();
$counting = 0;
if ($countform) {
$counting = 1;
$countform = do_list($countform, $delim);
$countpos = str_replace('smd_', '', $countpos); // For convenience
$countpos = do_list($countpos, $delim);
foreach ($countpos as $countitem) {
$countposns[] = (in_array($countitem, $countPosAllowed)) ? $countitem : $countPosAllowed[0];
}
}
// Paging init
$pagePosAllowed = array("below", "above");
$pageout = array();
if ($pageform) {
$paging = 1;
$pageform = fetch_form($pageform);
$pagepos = str_replace('smd_', '', $pagepos);
$pagepos = do_list($pagepos, $delim);
foreach ($pagepos as $pageitem) {
$pageout[] = (in_array($pageitem, $pagePosAllowed)) ? $pageitem : $pagePosAllowed[0];
}
}
// onchange verification
$onchange = do_list($onchange, $delim);
$onchange = ($onchange[0] == "") ? array() : $onchange;
$resetOpts = array();
foreach ($onchange as $resetOpt) {
$resetOpts[$resetOpt] = "";
}
// Escaping
$spc = ($strictfields) ? 0 : 1;
$escapes = do_list($escape, $delim);
foreach ($escapes as $idx => $val) {
if ($val == '') {
unset($escapes[$idx]);
}
}
// 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, $spc);
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, $spc);
list($catinc, $catexc) = smd_doList($category, false, $subinfo, true, $delim, $spc);
if ($idinc) {
$clauseOR[] = PFX.'txp_image.id IN ('.implode(",", $idinc).')';
}
if ($catinc) {
$clauseOR[] = PFX.'txp_image.category IN ('.implode(",", $catinc).')';
}
if (!empty($clauseOR)) {
$clause[] = ' ('.implode(" OR ", $clauseOR).') ';
}
$clause = implode(" AND ", $clause);
$clause .= ($catexc) ? ' AND '.PFX.'txp_image.category NOT IN ('.implode(",", $catexc).')' : '';
$clause .= ($idexc) ? ' AND '.PFX.'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 = PFX.'txp_image.category = "smd_' .mt_rand(). '"';
}
$clause = '('.str_replace('SMD_EMPTY', '', $clause).')';
if ($debug > 1) {
echo "++ INCLUDED/EXCLUDED IDs AND CATs ++";
if ($idinc) dmp($idinc);
if ($idexc) dmp($idexc);
if ($catinc) dmp($catinc);
if ($catexc) dmp($catexc);
}
// Filter by aspect ratio
if ($aspect) {
$aspects = do_list($aspect, $delim);
// Compare fullsize or thumbnail aspect ratios
$fldmod = ($fullmod) == 't' ? 'thumb_' : '';
$wfld = PFX.'txp_image.'.$fldmod.'w';
$hfld = PFX.'txp_image.'.$fldmod.'h';
$clauseOR = array();
foreach ($aspects as $ratio) {
switch($ratio) {
case 'portrait':
$clauseOR[] = $hfld. ' > '. $wfld;
break;
case 'landscape':
$clauseOR[] = $wfld. ' > '. $hfld;
break;
case 'square':
$clauseOR[] = $hfld. ' = '. $wfld;
break;
}
}
if (!empty($clauseOR)) {
$clause .= ' AND '.$wfld.' > 0 AND '.$hfld.' > 0 AND ('.implode(" OR ", $clauseOR).') ';
}
}
// Filter by author
if ($author) {
$authors = do_list($author, $delim);
$clause .= " AND " . PFX."txp_image.author IN ('".implode("','", $authors)."')";
}
// Filter by extension
if ($extension) {
$extensions = do_list($extension, $delim);
foreach ($extensions as $idx => $ext) {
$extensions[$idx] = ".".$ext;
}
$clause .= " AND " . PFX."txp_image.ext IN ('".implode("','", $extensions)."')";
}
// Filter by dimensions
if ($dimensions) {
$dimAllow = array('=', '>', '<', '>=', '<=');
$dims = do_list($dimensions, $delim);
// Compare fullsize or thumbnail aspect ratios
$fldmod = ($fullmod) == 't' ? 'thumb_' : '';
$wfld = PFX.'txp_image.'.$fldmod.'w';
$hfld = PFX.'txp_image.'.$fldmod.'h';
$wdim = $dims[0];
$hdim = (isset($dims[1])) ? $dims[1] : '';
$wdimval = preg_replace('/[^0-9]/', '', $wdim);
$hdimval = preg_replace('/[^0-9]/', '', $hdim);
$wdimop = preg_replace('/[0-9]/', '', $wdim);
$wdimop = in_array($wdimop, $dimAllow) ? $wdimop : '=';
$hdimop = preg_replace('/[0-9]/', '', $hdim);
$hdimop = in_array($hdimop, $dimAllow) ? $hdimop : '=';
$clause .= (($wdim) ? ' AND ' . $wfld . $wdimop . $wdimval : '') . (($hdim) ? ' AND ' . $hfld . $hdimop . $hdimval : '');
}
// 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);
$colName = $fieldMap[$colRef];
break;
}
if ($rule == "sql") {
if ($colRef != '') {
$clauseSort[] = $colRef.$direction;
}
} else {
if (!$randsort) {
if ($colRef != '') {
$postOrder[] = array("col" => $colName, "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));
$cTitle = (isset($l10n_language['long'])) ? _l10n_make_field_name('title', $thislang) : 'title';
$rs = getRows("
SELECT DISTINCT $fields, ".PFX."txp_category.".$cTitle." AS category_title
FROM ".PFX."txp_image LEFT JOIN ".PFX."txp_category
ON ".PFX."txp_image.category = ".PFX."txp_category.name
WHERE $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) {
foreach ($row as $identifier => $item) {
$varname = "col_".$identifier;
${$varname}[$key] = $item;
}
}
// Make up an array_multisort arg list and execute it.
// The necessary evil() is because we don't know how many cols there will be in the array
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
if ($rs) {
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
if ($rs) {
$rs = array_slice($rs, $offset, (($directory) ? $dirlimit : (($limit==0) ? $maxlimit : $limit)));
}
// Prepare fixed thumbsizes
$thumbWidth = $thumbHeight = '';
$thumbWUnits = $thumbHUnits = '';
if ($thumbsize) {
$thumbSizes = do_list($thumbsize, $delim);
$units = preg_replace('/[0-9]/', '', $thumbSizes[0]);
if (count($thumbSizes) == 1) {
$thumbWidth = $thumbHeight = preg_replace('/[^0-9]/', '', $thumbSizes[0]);
$thumbWUnits = $thumbHUnits = ($units == '') ? $thumbWUnits : $units;
} else {
$thumbWidth = preg_replace('/[^0-9]/', '', $thumbSizes[0]);
$thumbHeight = preg_replace('/[^0-9]/', '', $thumbSizes[1]);
$thumbWUnits = ($units == '' && $thumbWidth != '') ? $thumbWUnits : $units;
$units = preg_replace('/[0-9]/', '', $thumbSizes[1]);
$thumbHUnits = ($units == '' && $thumbHeight != '') ? $thumbHUnits : $units;
}
}
// Prepare fixed image sizes
$imageWidth = $imageHeight = '';
$imageWUnits = $imageHUnits = '';
if ($imgsize) {
$imageSizes = do_list($imgsize, $delim);
$units = preg_replace('/[0-9]/', '', $imageSizes[0]);
if (count($imageSizes) == 1) {
$imageWidth = $imageHeight = preg_replace('/[^0-9]/', '', $imageSizes[0]);
$imageWUnits = $imageHUnits = ($units == '') ? $imageWUnits : $units;
} else {
$imageWidth = preg_replace('/[^0-9]/', '', $imageSizes[0]);
$imageHeight = preg_replace('/[^0-9]/', '', $imageSizes[1]);
$imageWUnits = ($units == '' && $imageWidth != '') ? $imageWUnits : $units;
$units = preg_replace('/[0-9]/', '', $imageSizes[1]);
$imageHUnits = ($units == '' && $imageHeight != '') ? $imageHUnits : $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, $spc);
$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 = "onchange";
if ($debug > 2) {
echo "++ RECORD SET ++";
dmp($rs);
}
if ($debug > 3) {
echo "++ AVAILABLE '?' VARS ++";
if ($pretext) dmp($pretext);
if ($thisarticle) 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);
$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}' => $smd_gallLang->gTxt('navfirst'),
'{navprev}' => $smd_gallLang->gTxt('navprev'),
'{navearlier}' => '',
'{navthis}' => $thumPage,
'{navthisurl}' => $thumPage,
'{navlater}' => '',
'{navnext}' => $smd_gallLang->gTxt('navnext'),
'{navlast}' => $smd_gallLang->gTxt('navlast'),
);
$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 escaping here, just prior to output
if ($escapes) {
foreach ($repagements as $defName => $defVal) {
if (in_array(trim($defName, "{}"), $escapes)) {
$repagements[$defName] = htmlspecialchars($defVal, ENT_QUOTES);
}
}
}
// 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 (strpos($resetOpt, 'smd_every') === 0) {
$iter = explode($paramdelim, $resetOpt);
$iter = (count($iter) > 1) ? $iter[1] : 0;
if ($thumbIdx % $iter == 0) {
$thumbIdx = 0;
$thumbCtr = 1;
}
} else if ($row[$resetOpt] != $resetVal) {
$thumbIdx = 0;
$thumbCtr = 1;
break;
}
}
// Override thumbsize / imgsize if required
if ($thumbsize) {
$theThumbWidth = empty($thumbWidth) ? $row['thumb_w'] : $thumbWidth;
$theThumbHeight = empty($thumbHeight) ? $row['thumb_h'] : $thumbHeight;
$theThumbWUnits = $thumbWUnits;
$theThumbHUnits = $thumbHUnits;
} else {
$theThumbWidth = $row['thumb_w'];
$theThumbHeight = $row['thumb_h'];
$theThumbWUnits = $theThumbHUnits = '';
}
if ($imgsize) {
$theImageWidth = empty($imageWidth) ? $row['w'] : $imageWidth;
$theImageHeight = empty($imageHeight) ? $row['h'] : $imageHeight;
$theImageWUnits = $imageWUnits;
$theImageHUnits = $imageHUnits;
} else {
$theImageWidth = $row['w'];
$theImageHeight = $row['h'];
$theImageWUnits = $theImageHUnits = '';
}
// 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}' => (isset($row['thumbnail']) ? $row['thumbnail'] : 0),
'{url}' => $fullSize,
'{thumburl}' => $theThumb,
'{imagepath}' => $urlPath,
'{imagedef}' => basename($fullSize),
'{thumbdef}' => basename($theThumb),
'{alt}' => $row['alt'],
'{title}' => $row['caption'],
'{caption}' => $row['caption'],
'{thumbwidth}' => $theThumbWidth,
'{thumbheight}' => $theThumbHeight,
'{thumbwunits}' => $theThumbWUnits,
'{thumbhunits}' => $theThumbHUnits,
'{width}' => $theImageWidth,
'{height}' => $theImageHeight,
'{wunits}' => $theImageWUnits,
'{hunits}' => $theImageHUnits,
'{date}' => (($format) ? safe_strftime($format, strtotime($row['date']), $gmt, $lang) : $row['date']),
'{galleryid}' => $gallID,
'{index}' => $idx,
'{counter}' => $ctr,
'{thumbindex}' => $thumbIdx,
'{thumbcounter}' => $thumbCtr,
'{totalimages}' => $numImages,
'{maximages}' => $allImages,
);
// Add any custom columns
foreach ($extraMap as $eCol => $eVal) {
$replacements['{'.$eVal.'}'] = $row[$eCol];
}
// Append any changed items that are required
$endtag = false;
foreach ($resetOpts as $resetOpt => $resetVal) {
if (strpos($resetOpt, 'smd_every') === 0) {
$iter = explode($paramdelim, $resetOpt);
$iter = (count($iter) > 1) ? $iter[1] : 0;
if ($thumbCtr % $iter === 0 || $ctr == $numImages) {
$endtag = true;
}
} else {
$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) ? '' . $grouptag . '>' : '';
$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];
}
// Perform escaping on the replacements.
// Note the repagements have already been escaped so when/if they are combined with the replacements,
// the escaping is not done twice
if ($escapes) {
foreach ($replacements as $defName => $defVal) {
if (in_array(trim($defName, "{}"), $escapes)) {
$replacements[$defName] = htmlspecialchars($defVal, ENT_QUOTES);
}
}
}
// Add the navigation items if they're defined
if (count($repagements) > 0) {
$replacements = array_merge($repagements, $replacements);
}
// Is a thumb/text object required this time?
$object = '';
if ($thumbIdx >= $thumboffset && $thumbIdx < $thumboffset+$thumblimit) {
$object = ($objectform) ? parse(strtr($objectform, $replacements)) : (($text) ? $text : '');
}
$replacements['{object}'] = $object;
if ($debug > 0) {
echo "++ REPLACEMENTS : IMAGE ".$ctr." ++";
dmp($replacements);
}
// Check if countform is to be called
$countpre = $countpost = array();
if ($counting) {
foreach ($countform as $countlist) {
$posover = array();
$countlist = strtr($countlist, $replacements); // Replace any {} vars with their real values
$countlist = do_list($countlist, $paramdelim);
if ($dpos=array_search('smd_above', $countlist)) {
$posover[] = "above";
unset($countlist[$dpos]);
}
if ($dpos=array_search('smd_below', $countlist)) {
$posover[] = "below";
unset($countlist[$dpos]);
}
$countlist = array_merge($countlist); // re-index
$posover = (empty($posover)) ? $countposns : $posover;
$divby = false;
if ($countlist[0] == 'smd_every') {
$divby = true;
array_shift($countlist);
}
$numforms = count($countlist);
$callform = fetch_form($countlist[$numforms-1]);
unset($countlist[$numforms-1]);
$orlogic = $andlogic = array();
foreach ($countlist as $custcount) {
$showval = (strpos($custcount, "!") === 0) ? false : true;// Negative logic required
$custcount = str_replace('!', '', $custcount);
if ($showval) {
$orlogic[] = empty($custcount) || (($divby) ? (($ctr % $custcount === 0) ? true : false) : (($custcount == $ctr) ? true : false));
} else {
$andlogic[] = ($custcount == $ctr) ? false : true;
}
}
if (in_array('1', $orlogic) && !in_array('0', $andlogic)) {
if (in_array("above", $posover)) {
$countpre[] = parse(strtr($callform, $replacements));
}
if (in_array("below", $posover)) {
$countpost[] = parse(strtr($callform, $replacements));
}
}
}
}
if ($debug > 0 && ($countpre || $countpost)) {
echo "++ COUNT FORM TRIGGERED ++";
if ($countpre) {
dmp($countpre);
}
if ($countpost) {
dmp($countpost);
}
}
// 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 {
if ($counting) {
$thumbout = array_merge($thumbout, $countpre);
}
$thumbout[] = parse(strtr($thing, $replacements));
if ($counting) {
$thumbout = array_merge($thumbout, $countpost);
}
}
// Keep track of the current values so we know if they change next time
foreach ($resetOpts as $resetOpt => $resetVal) {
if (strpos($resetOpt, 'smd_every') === false) {
$resetOpts[$resetOpt] = $row[$resetOpt];
} else {
$resetOpts[$resetOpt] = $thumbCtr;
}
}
$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, '', '', '', $html_id);
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);
}
// Work out which page this gallery is on and return the relevant info
function smd_getPage($rs, $gallID, $limit, $offset, $paging) {
$numThums = count($rs) - $offset;
if (($limit > 0) && $paging) {
$numPages = ($numThums > 0) ? ceil($numThums/$limit) : 1;
$thumPage = (!gps($gallID)) ? 1 : gps($gallID);
$offset = (($thumPage - 1) * $limit) + $offset;
} 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=",", $spc=1, $ctr=0) {
list($dirinc, $direxc) = smd_doList($lst, false, $sub, false, $dlm, $spc);
list($matchinc, $matchexc) = smd_doList($match, false, '', false, $dlm, $spc);
$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, $spc, $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;
}