// v0.1 Initial public release // v0.11 Added !category support // v0.12 Added textpos option (thanks lee) and imageid option (thanks wouaren) // v0.2 js and css can now be loaded elsewhere (thanks jstubbs). Added wraptag and changed defaults to make output less like tag-soup (thanks wouaren) // v0.21 Added orderby="fixed" to allowed fixed imageid ordering (thanks lee). $where warning squashed (thanks benjibot) // v0.22 Now uses smd_lib and subcats. Also MLP(Multi-lingual)-aware. // v0.23 Fixed orderby when using random (thanks mrdale) and added ability to override maxlimit // v0.24 Added libcheck (thanks papuass). Numeric ranges now allowed for IDs (smd_lib). Fixed empty field/imageid negation bugs. Fixed next/prev buttons for MLP. // v0.24b Fixed paging in subdirectory installations (thanks ultramega and Qwest) // v0.25 Extended groupname (thanks [Axel]) // v0.25a Bundled latest version of slimbox in the package. Made the docs easier to read. // v0.26 Added true multiple gallery support (thanks wheaticus) // v0.27 Added thumb (thank progre55) require_plugin('smd_lib'); register_callback('smd_sbox_enum_str', 'l10n.enumerate_strings'); global $smd_sbox_libs; global $smd_sbox_str; $smd_sbox_str = array( 'incerr' => 'If using the scripts option, specify up to three required scripts in this order: <txp:smd_slimbox_inc scripts="mootoolsJSLocation, slimboxJSLocation, slimboxCSSLocation" />. If any positions are left empty, the missing scripts must be supplied via the jsdir/cssdir options, or loaded externally and told to skip this step. The three values can either be a full XHTML string (e.g. as returned by txp:stm_javascript or txp:css, although they may not work directly within the tag; see the docs) or simply paths to the files. Note that no validation is performed to check if the files exist.', 'noinc' => 'Required libraries not loaded. Call <txp:smd_slimbox_inc /> in the <head> of this page.', 'next_lbl' => 'Next', 'prev_lbl' => 'Prev', ); // Use this to include the libraries in the section of the page function smd_slimbox_inc($atts) { global $smd_sbox_libs; global $smd_sbox_str; if (is_array($atts)) extract($atts); // Function options $jsdir = isset($jsdir) ? doSlash($jsdir) : ''; $cssdir = isset($cssdir) ? doSlash($cssdir) : ''; $scripts = isset($scripts) ? $scripts : ''; $skip = isset($skip) ? $skip : "0"; $modsRequired = 3; $modsLoaded = 0; $outStr = ''; if ($skip > 0) { $modsLoaded = $skip; } // Include the js libs if required if ($jsdir != '') { $outStr .= ''.n; $outStr .= ''.n; $modsLoaded += 2; } // Find which scripts to auto-load if (($scripts != '') && ($modsLoaded < $modsRequired)) { $modsList = preg_split('/[,]+/',$scripts,$modsRequired); $jsprefix = "'.n; } else { $outStr .= ''.n; } } $modsLoaded++; } } // Include the css file if required if ($cssdir != '') { $outStr .= ''.n; $modsLoaded++; } // Set the flag to say the libs are ok. Shame there's no easy provision for // checking the files actually exist at the given locations, but hey if ($modsLoaded == $modsRequired) { $smd_sbox_libs = true; } else { $smd_sbox_libs = false; $outStr = smd_gTxt($smd_sbox_str,'incerr').n; } return $outStr; } function smd_slimbox($atts) { global $pretext, $thisarticle, $img_dir; global $smd_sbox_libs, $smd_sbox_str; if (is_array($atts)) extract($atts); $catidopts = (isset($category) || isset($imageid)) ? true : false; // Plugin options $libcheck = isset($libcheck) ? $libcheck: "1"; $imageid = isset($imageid) ? doSlash($imageid) : ''; $category = isset($category) ? doSlash($category) : (($imageid=="") ? $pretext['c']: ''); $subcats = isset($subcats) ? true : false; $catlabel = isset($catlabel) ? $catlabel: "article-"; $groupname = isset($groupname) ? $groupname: "smd"; $thumb = isset($thumb) ? true : false; $maxlimit = isset($maxlimit) ? $maxlimit: "99999"; $limit = isset($limit) ? $limit: "0"; $orderby = isset($orderby) ? $orderby: "category"; $showpagelinks = isset($showpagelinks) ? $showpagelinks: "1"; $galleryid = isset($galleryid) ? $galleryid: "?4:6"; $prevlabel= isset($prevlabel) ? $prevlabel: smd_gTxt($smd_sbox_str, 'prev_lbl'); $nextlabel= isset($nextlabel) ? $nextlabel: smd_gTxt($smd_sbox_str, 'next_lbl'); $showcaption = isset($showcaption) ? $showcaption: "0"; $showalt = isset($showalt) ? $showalt: "0"; $textpos = isset($textpos) ? $textpos: "below"; $wraptag = isset($wraptag) ? $wraptag: ""; $cellclass = isset($cellclass) ? $cellclass: ""; $imgclass = isset($imgclass) ? $imgclass: ""; $navclass = isset($navclass) ? $navclass: ""; $prevclass = isset($prevclass) ? $prevclass: "smd_slimbox_prev"; $nextclass = isset($nextclass) ? $nextclass: "smd_slimbox_next"; $captionclass = isset($captionclass) ? $captionclass: ""; $altclass = isset($altclass) ? $altclass: ""; $fixedOrder = false; $gallID = ""; // The gallery identifier is used for keeping track of next/prev thumbpage links if ($galleryid == "" || $galleryid[0] == "?") { // Generate a unique ID for this gallery instance $gallTmp = md5($category.$imageid.$orderby.$limit.$maxlimit.$wraptag); 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; } // Main code body if (($libcheck == 1) && ($smd_sbox_libs == false)) { $outStr = smd_gTxt($smd_sbox_str,'noinc'); } else { // The database fields required $fields = 'id,name,caption,alt,category,date,author,ext,w,h'; // Convert the category (possibly a comma-sep list) into an SQL-style 'in' list. $fullCatList = array(); $notCatList = array(); $catVars = array("?c", "!c", "?s", "!s", "?t", "!t", "?id", "!id", "?field", "!field"); $retArray = smd_getAtts($category, $catVars, $catlabel); $fullCatList = $retArray[0]; $notCatList = $retArray[1]; // Convert the imageid (possibly a comma-sep list) into an SQL-style 'in' list. $fullIDList = array(); $notIDList = array(); $idVars = array("?id", "!id", "?field", "!field"); $retArray = smd_getAtts($imageid, $idVars); $fullIDList = $retArray[0]; $notIDList = $retArray[1]; // Make up the WHERE statement from the combined lists. // The categories/image IDs are ORed together in brackets first // before the negation options are tacked on as ANDs afterwards $whereOR = array(); $whereAND = array(); // Start the WHERE statement with the combined list of image IDs if (count($fullIDList) > 0) { for ($idx = count($fullIDList); $idx >=0; $idx--) { if (empty($fullIDList[$idx])) { unset($fullIDList[$idx]); } else { $fullIDList[$idx] = "'" . $fullIDList[$idx] . "'"; } } if (count($fullIDList) > 0) { $whereOR[] = "id IN (" . implode(",", $fullIDList). ")"; } } // included categories - some may be subcats $tmpa = array(); for ($idx = 0; $idx < count($fullCatList); $idx++) { if ($subcats) { $categs = smd_getSubCats($fullCatList[$idx],'image'); for ($jdx = 0; $jdx < count($categs); $jdx++) { if ($categs[$jdx]['name'] != "root") { $tmpa[] = "'" .$categs[$jdx]['name']. "'"; } } } else { $tmpa[] = "'" .$fullCatList[$idx]. "'"; } } if (count($tmpa) > 0) { $whereOR[] = "category IN (" .implode(",", $tmpa). ")"; } if (count($whereOR) > 0) { $where = "(" . implode(" OR ", $whereOR) . ")"; } else { $where = ""; } // excluded categories $tmpa = array(); for ($idx = 0; $idx < count($notCatList); $idx++) { if ($subcats) { $categs = smd_getSubCats($notCatList[$idx],'image'); for ($jdx = 0; $jdx < count($categs); $jdx++) { if ($categs[$jdx]['name'] != "root") { $tmpa[] = "'" .$categs[$jdx]['name']. "'"; } } } else { $tmpa[] = "'" .$notCatList[$idx]. "'"; } } if (count($tmpa) > 0) { $whereAND[] = "category NOT IN (" .implode(",", $tmpa). ")"; } // Add to the WHERE statement the combined list of NOT image IDs if (count($notIDList) > 0) { for ($idx = count($notIDList); $idx >=0; $idx--) { if (empty($notIDList[$idx])) { unset($notIDList[$idx]); } else { $notIDList[$idx] = "'" . $notIDList[$idx] . "'"; } } if (count($notIDList) > 0) { $whereAND[] = "id NOT IN (" . implode(",", $notIDList). ")"; } } if (count($whereAND) > 0) { $where .= (($where=="") ? "" : " AND ") . implode(" AND ", $whereAND); } // If the reason nothing was returned is because no options were given if ($where == "" && !$catidopts) { $where = "1=1"; } // Convert the orderby 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 orderby 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 $whereOB = Array(); $postOrder = array(); $rule = "sql"; $postPrefix = "SORT_"; $randsort = false; $obList = preg_split('/[,\s]+/',$orderby,-1,PREG_SPLIT_NO_EMPTY); for ($idx = 0; $idx < count($obList); $idx++) { $ob_dir = explode(':',$obList[$idx]); $direction = ''; $colRef = ''; if (count($ob_dir) <= 1) { $ob_dir[1] = "asc"; } if ($rule == "sql") { $direction = ($ob_dir[1] == "desc") ? ' desc' : ' asc'; } else { $direction = ($ob_dir[1] == "desc") ? $postPrefix.'DESC' : $postPrefix.'ASC'; } switch ($ob_dir[0]) { case 'name': $colRef = 'name'; break; case 'id': $colRef = 'id'; break; case 'alt': $colRef = 'alt'; break; case 'caption': $colRef = 'caption'; break; case 'date': $colRef = 'date'; break; case 'ext': $colRef = 'ext'; break; case 'author': $colRef = 'author'; break; case 'width': $colRef = 'w'; break; case 'height': $colRef = 'h'; break; case 'random': $rule = "post"; if ($idx == 0) { $whereOB[] = 'rand()'; } else { $randsort = true; } break; case 'fixed': // 'fixed' only works on image ids if ($imageid != "") { $fixedOrder = true; } break; case 'category': default: $colRef = 'category'; break; } if ($rule == "sql") { if ($colRef != "") { $whereOB[] = $colRef.$direction; } } else { if (!$randsort) { if ($colRef != "") { $postOrder[] = array("col" => $colRef, "sort" => $direction); } } } } if (count($whereOB) > 0) { $where .= ' ORDER BY ' . implode(",",$whereOB); } // Handle paging if (($limit > 0) && $showpagelinks) { $rs = safe_rows($fields, 'txp_image', $where .' LIMIT 0,'.$maxlimit); $numthum = count($rs); $numPages = ($numthum > 0) ? ceil($numthum/$limit) : 1; $thumbpage = (!gps($gallID)) ? 1 : gps($gallID); $offset = ($thumbpage - 1) * $limit; $rs = safe_rows($fields, 'txp_image', $where .' LIMIT '.$offset.','.$limit); } else { // No paging required $numPages = 1; $thumbpage = 1; $rs = safe_rows($fields, 'txp_image', $where .' LIMIT 0,'. (($limit==0) ? $maxlimit : $limit)); } // 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']; } // 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 for ($idx = 0; $idx < count($fullIDList); $idx++) { foreach($rs as $row) { if ("'".$row['id']."'" == $fullIDList[$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); } // Construct the output $outStr = ''; if($rs) { foreach($rs as $row) { $theThumb = hu.$img_dir.'/' . $row['id'] . 't' . $row['ext']; $full = hu.$img_dir.'/' . $row['id'] . (($thumb) ? "t" : "") .$row['ext']; if ($groupname === "?c") { $grp = $row['category']; } else if ($groupname === "?id") { $grp = $row['id']; } else if ($groupname === "?author") { $grp = $row['author']; } else if ($groupname === "?date") { $grp = $row['date']; } else if ($groupname === "?alt") { $grp = $row['alt']; } else if ($groupname === "?caption") { $grp = $row['caption']; } else if ($groupname === "?ext") { $grp = $row['ext']; } else if ($groupname === "?name") { $grp = $row['name']; } else if ($groupname === "?width") { $grp = $row['w']; } else if ($groupname === "?height") { $grp = $row['h']; } else if ($groupname[0] === "?") { // Split off the field name from the question mark $fieldname = substr($groupname,1); if (isset($thisarticle[$fieldname])) { $grp = $thisarticle[$fieldname]; } else { $grp = ''; } } else { $grp = $groupname; } // Generate the caption/alt if required $capStr = ($showalt && $row['alt']) ? '' .$row['alt']. '' : ''; $capStr .= ($showcaption && $row['caption']) ? '' .$row['caption']. '' : ''; // Construct the link and put caption/alt in the appropriate position $outStr .= ($wraptag != "") ? '<' .$wraptag. (($cellclass != "") ? ' class="' .$cellclass. '"' : '') . '>' : ''; $outStr .= ($textpos == "above") ? $capStr : ''; $outStr .= '' .(($textpos == "before") ? $capStr : ''). '' .$row['alt']. '' .(($textpos == "after") ? $capStr : ''). ''.n; $outStr .= ($textpos == "below") ? $capStr : ''; $outStr .= ($wraptag != "") ? '' : ''; $outStr .= n; } // Add the paging features if required if (($limit > 0) && $showpagelinks) { $next = ($numPages > 1 && $thumbpage != $numPages); $prev = ($numPages > 1 && $thumbpage > 1); // Replace any paging info in the query string $prevPage = smd_addQSVar($pretext['request_uri'], $gallID, $thumbpage-1); $nextPage = smd_addQSVar($pretext['request_uri'], $gallID, $thumbpage+1); $outStr .= ($wraptag != "") ? '<' .$wraptag. (($navclass != "") ? ' class="' .$navclass. '"' : '') . '>' : ''; $outStr .= ($prev) ? '' .$prevlabel. ''.n : ''; $outStr .= ($next) ? '' .$nextlabel. ''.n : ''; $outStr .= ($wraptag != "") ? '' : ''; $outStr .= n; } } } return $outStr; } // Callback for MLP string replacement function smd_sbox_enum_str($event, $step='', $pre=0) { global $smd_sbox_str, $smdMLP; $r = array ( 'owner' => 'smd_slimbox', 'prefix' => $smdMLP['smd_slimbox'], 'lang' => 'en-gb', // Default language 'event' => 'public', // public/admin/common = which interface the strings will be loaded into 'strings' => $smd_sbox_str, ); return $r; }