yj-t
7/10/2016 - 9:14 AM

getResourcesColumns.snippet.php

<?php
/**
 * getResourcesColumns
 * @author @sepiariver
 * 
 * &parent optional         ID of Resource from which to fetch children. Defaults to current resource.
 * &fields optional         Resource field(s) from which to fetch values. Defaults to 'pagetitle,longtitle,introtext,parent,hidemenu'.
 * &columns optional        Number of columns to sort Resources into and wrap with colWrapper_n;
 * &columnDirection optionalVertical or horizontal column sorting. Defaults to horizontal
 * &depth optional          Depth to seek children via getChildIds(). Defaults to 1
 * &limit optional          Limit number to output. Defaults to 0 (no limit)
 * &offset optional         Offset to pass to query. Defaults to 0
 * &sortBy optional         Field to sort by. Defaults to 'publishedon'
 * &sortDir optional        Sort direction. Defaults to 'DESC'
 * &showUnpublished optionalFlag to show unpublished Resources. Defaults to 0
 * &showHidden optional     Flag to show hidden Resources. Defaults to 0
 * &showDeleted optional    Flag to show deleted Resources. Defaults to 0
 * &hideContainers optional Flag to hide container Resources. Defaults to 0
 * &toPlaceholder optional  Key of placeholder to which to send output
 * &includeTVList optional  List of TV names to include in output
 * &processTVList optional  List of TV names to process for output
 * &rowTpl                  Chunk name to use for each item
 * &rowTpl_colN optional    Override for rows inside column "N". Defaults to ''
 * &colWrapTpl optional     Chunk name to use for wrapping each column. Defaults to ''
 * &colWrapTpl_colN         Override for wrapping columns "N". Defaults to ''
 * &rowSeparator optional   Separator for each row within a column. Defaults to PHP_EOL
 * &colSeparator optional   Separator for each column. Defaults to PHP_EOL
 * &exclude optional        Comma-separated list of Resource IDs, optionally with "-" prefix, to exclude
 * 
 **/
// OPTIONS
$parent = $modx->getOption('parent', $scriptProperties, $modx->resource->get('id'));
// Can't do anything without a parent ID
if (empty($parent) || $parent < 0) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'getResourcesColumns requires a parent resource ID');
    return '';
}

$fields = array_filter(array_map('trim', explode(',', $modx->getOption('fields', $scriptProperties, 'pagetitle,longtitle,introtext,parent,hidemenu'))));
// If no fields are specified, we would never return anything anyways
if (empty($fields) || (count($fields) === 0)) return '';

$columns = (int) $modx->getOption('columns', $scriptProperties, 2);
// If columns are less than 1, we can't return them
if ($columns < 1) return '';
$colDir = strtolower(substr($modx->getOption('columnDirection', $scriptProperties,'h'), 0, 1));

$depth = $modx->getOption('depth', $scriptProperties, 1);
$limit = $modx->getOption('limit', $scriptProperties, 0);
$offset = $modx->getOption('offset', $scriptProperties, 0);
$sortBy = $modx->getOption('sortBy', $scriptProperties, 0);
$sortDir = $modx->getOption('sortDir', $scriptProperties, 0);

$showUnpublished = $modx->getOption('showUnpublished', $scriptProperties, 0);
$showHidden = $modx->getOption('showHidden', $scriptProperties, 0);
$showDeleted = $modx->getOption('showDeleted', $scriptProperties, 0);
$hideContainers = $modx->getOption('hideContainers', $scriptProperties, 0);

$where = $modx->fromJSON($modx->getOption('where', $scriptProperties, '[]'));
$exclude = array_filter(array_map('trim', explode(',', $modx->getOption('exclude', $scriptProperties, ''))));
$exclude = (is_array($exclude) && !empty($exclude)) ? $exclude : array();
foreach ($exclude as $k => $v) {
    $exclude[$k] = trim($v, '-');
}

$rowTpl = $modx->getOption('rowTpl', $scriptProperties, '');
$colWrapTpl = $modx->getOption('colWrapTpl', $scriptProperties, '');
$rowSeparator = $modx->getOption('rowSeparator', $scriptProperties, PHP_EOL);
$colSeparator = $modx->getOption('colSeparator', $scriptProperties, PHP_EOL);

$toPlaceholder = $modx->getOption('toPlaceholder', $scriptProperties, '');
$includeTVList = array_filter(array_map('trim', explode(',', $modx->getOption('includeTVList', $scriptProperties, ''))));
$processTVList = array_filter(array_map('trim', explode(',', $modx->getOption('processTVList', $scriptProperties, ''))));
$tvPrefix = $modx->getOption('tvPrefix', $scriptProperties, 'tv.');

// Get childIds
$resIds = $modx->getChildIds($parent, $depth);

// Query
$c = $modx->newQuery('modResource');

// Criteria
$criteria = array(
    'id:IN' => $resIds,
    );
if (!$showUnpublished) $criteria['published:='] = 1;
if (!$showHidden) $criteria['hidemenu:='] = 0;
if (!$showDeleted) $criteria['deleted:='] = 0;
if ($hideContainers) $criteria['isfolder:='] = 0;
if (!empty($exclude)) $criteria['id:NOT IN'] = $exclude;
$c->where($criteria);

// Always select pk
$fields = array_merge($fields, array('id'));
// Only take what we need
$c->select($fields);
$c->limit($limit, $offset);

// Support Tagger etc
if (is_array($where) && !empty($where)) $c->where($where);

// Sort
$c->sortby($sortBy, $sortDir);

// Debug only
//$c->prepare();
//return $c->toSQL();

// Get Total Count
$total = $modx->getCount('modResource', $c);
if ($total < 1) return '';

// Fetch Resources
$resources = $modx->getCollection('modResource', $c);

// Calculate columns based on idx
$idx = 0;
if ($colDir === 'v') {
    $eachColCount = round($total / $columns);
}
$output = array();

foreach ($resources as $resource) {
    // Set current column
    $col = ($colDir === 'v') ? (intval($idx / $eachColCount) + 1) : ($idx % $columns) + 1;

    // Set TPL
    $tpl = (isset($scriptProperties['rowTpl_col' . $col])) ? $scriptProperties['rowTpl_col' . $col] : $rowTpl;
    // Get Resource values
    $values = $resource->toArray('', false, true); // don't lazy-load
    
    // TODO: Better way to get TV values
    if (!empty($includeTVList)) {
        $tvc = $modx->newQuery('modTemplateVars');
        $tvc->where(array(
            'name:IN' => $includeTVList,
            ));
        $tvs = $resource->getMany('TemplateVars', $tvc);
        foreach ($tvs as $tv) {
            $tvname = $tv->get('name');
            $values[$tvPrefix . $tvname] = (in_array($tvname, $processTVList)) ? $tv->renderOutput($id) : $tv->getValue($id);
        }
    }
    // Populate column
    $output[$col][] = $modx->getChunk($tpl, $values);
    $idx++;
}
foreach ($output as $index => $column) {
    // Column output
    $columnOutput = implode($rowSeparator, $column);
    // Set tpl
    $cTpl = (isset($scriptProperties['colWrapTpl_col' . $index])) ? $scriptProperties['colWrapTpl_col' . $index] : $colWrapTpl;
    $output[$index] = (!empty($cTpl)) ? $modx->getChunk($cTpl, array('column' => $columnOutput)) : $columnOutput;
}
$output = implode($colSeparator, $output);
if (empty($toPlaceholder)) return $output;
$modx->setPlaceholder($toPlaceholder, $output);