26.cache.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. <?php return '/**
  2. * getResources
  3. *
  4. * A general purpose Resource listing and summarization snippet for MODX 2.x.
  5. *
  6. * @author Jason Coward
  7. * @copyright Copyright 2010-2013, Jason Coward
  8. *
  9. * TEMPLATES
  10. *
  11. * tpl - Name of a chunk serving as a resource template
  12. * [NOTE: if not provided, properties are dumped to output for each resource]
  13. *
  14. * tplOdd - (Opt) Name of a chunk serving as resource template for resources with an odd idx value
  15. * (see idx property)
  16. * tplFirst - (Opt) Name of a chunk serving as resource template for the first resource (see first
  17. * property)
  18. * tplLast - (Opt) Name of a chunk serving as resource template for the last resource (see last
  19. * property)
  20. * tpl_{n} - (Opt) Name of a chunk serving as resource template for the nth resource
  21. *
  22. * tplCondition - (Opt) Defines a field of the resource to evaluate against keys defined in the
  23. * conditionalTpls property. Must be a resource field; does not work with Template Variables.
  24. * conditionalTpls - (Opt) A JSON object defining a map of field values and the associated tpl to
  25. * use when the field defined by tplCondition matches the value. [NOTE: tplOdd, tplFirst, tplLast,
  26. * and tpl_{n} will take precedence over any defined conditionalTpls]
  27. *
  28. * tplWrapper - (Opt) Name of a chunk serving as a wrapper template for the output
  29. * [NOTE: Does not work with toSeparatePlaceholders]
  30. *
  31. * SELECTION
  32. *
  33. * parents - Comma-delimited list of ids serving as parents
  34. *
  35. * context - (Opt) Comma-delimited list of context keys to limit results by; if empty, contexts for all specified
  36. * parents will be used (all contexts if 0 is specified) [default=]
  37. *
  38. * depth - (Opt) Integer value indicating depth to search for resources from each parent [default=10]
  39. *
  40. * tvFilters - (Opt) Delimited-list of TemplateVar values to filter resources by. Supports two
  41. * delimiters and two value search formats. The first delimiter || represents a logical OR and the
  42. * primary grouping mechanism. Within each group you can provide a comma-delimited list of values.
  43. * These values can be either tied to a specific TemplateVar by name, e.g. myTV==value, or just the
  44. * value, indicating you are searching for the value in any TemplateVar tied to the Resource. An
  45. * example would be &tvFilters=`filter2==one,filter1==bar%||filter1==foo`
  46. * [NOTE: filtering by values uses a LIKE query and % is considered a wildcard.]
  47. * [NOTE: this only looks at the raw value set for specific Resource, i. e. there must be a value
  48. * specifically set for the Resource and it is not evaluated.]
  49. *
  50. * tvFiltersAndDelimiter - (Opt) Custom delimiter for logical AND, default \',\', in case you want to
  51. * match a literal comma in the tvFilters. E.g. &tvFiltersAndDelimiter=`&&`
  52. * &tvFilters=`filter1==foo,bar&&filter2==baz` [default=,]
  53. *
  54. * tvFiltersOrDelimiter - (Opt) Custom delimiter for logical OR, default \'||\', in case you want to
  55. * match a literal \'||\' in the tvFilters. E.g. &tvFiltersOrDelimiter=`|OR|`
  56. * &tvFilters=`filter1==foo||bar|OR|filter2==baz` [default=||]
  57. *
  58. * where - (Opt) A JSON expression of criteria to build any additional where clauses from. An example would be
  59. * &where=`{{"alias:LIKE":"foo%", "OR:alias:LIKE":"%bar"},{"OR:pagetitle:=":"foobar", "AND:description:=":"raboof"}}`
  60. *
  61. * sortby - (Opt) Field to sort by or a JSON array, e.g. {"publishedon":"ASC","createdon":"DESC"} [default=publishedon]
  62. * sortbyTV - (opt) A Template Variable name to sort by (if supplied, this precedes the sortby value) [default=]
  63. * sortbyTVType - (Opt) A data type to CAST a TV Value to in order to sort on it properly [default=string]
  64. * sortbyAlias - (Opt) Query alias for sortby field [default=]
  65. * sortbyEscaped - (Opt) Escapes the field name(s) specified in sortby [default=0]
  66. * sortdir - (Opt) Order which to sort by [default=DESC]
  67. * sortdirTV - (Opt) Order which to sort by a TV [default=DESC]
  68. * limit - (Opt) Limits the number of resources returned [default=5]
  69. * offset - (Opt) An offset of resources returned by the criteria to skip [default=0]
  70. * dbCacheFlag - (Opt) Controls caching of db queries; 0|false = do not cache result set; 1 = cache result set
  71. * according to cache settings, any other integer value = number of seconds to cache result set [default=0]
  72. *
  73. * OPTIONS
  74. *
  75. * includeContent - (Opt) Indicates if the content of each resource should be returned in the
  76. * results [default=0]
  77. * includeTVs - (Opt) Indicates if TemplateVar values should be included in the properties available
  78. * to each resource template [default=0]
  79. * includeTVList - (Opt) Limits the TemplateVars that are included if includeTVs is true to those specified
  80. * by name in a comma-delimited list [default=]
  81. * prepareTVs - (Opt) Prepares media-source dependent TemplateVar values [default=1]
  82. * prepareTVList - (Opt) Limits the TVs that are prepared to those specified by name in a comma-delimited
  83. * list [default=]
  84. * processTVs - (Opt) Indicates if TemplateVar values should be rendered as they would on the
  85. * resource being summarized [default=0]
  86. * processTVList - (opt) Limits the TemplateVars that are processed if included to those specified
  87. * by name in a comma-delimited list [default=]
  88. * tvPrefix - (Opt) The prefix for TemplateVar properties [default=tv.]
  89. * idx - (Opt) You can define the starting idx of the resources, which is an property that is
  90. * incremented as each resource is rendered [default=1]
  91. * first - (Opt) Define the idx which represents the first resource (see tplFirst) [default=1]
  92. * last - (Opt) Define the idx which represents the last resource (see tplLast) [default=# of
  93. * resources being summarized + first - 1]
  94. * outputSeparator - (Opt) An optional string to separate each tpl instance [default="\\n"]
  95. * wrapIfEmpty - (Opt) Indicates if the tplWrapper should be applied if the output is empty [default=0]
  96. *
  97. */
  98. $output = array();
  99. $outputSeparator = isset($outputSeparator) ? $outputSeparator : "\\n";
  100. /* set default properties */
  101. $tpl = !empty($tpl) ? $tpl : \'\';
  102. $includeContent = !empty($includeContent) ? true : false;
  103. $includeTVs = !empty($includeTVs) ? true : false;
  104. $includeTVList = !empty($includeTVList) ? explode(\',\', $includeTVList) : array();
  105. $processTVs = !empty($processTVs) ? true : false;
  106. $processTVList = !empty($processTVList) ? explode(\',\', $processTVList) : array();
  107. $prepareTVs = !empty($prepareTVs) ? true : false;
  108. $prepareTVList = !empty($prepareTVList) ? explode(\',\', $prepareTVList) : array();
  109. $tvPrefix = isset($tvPrefix) ? $tvPrefix : \'tv.\';
  110. $parents = (!empty($parents) || $parents === \'0\') ? explode(\',\', $parents) : array($modx->resource->get(\'id\'));
  111. array_walk($parents, \'trim\');
  112. $parents = array_unique($parents);
  113. $depth = isset($depth) ? (integer) $depth : 10;
  114. $tvFiltersOrDelimiter = isset($tvFiltersOrDelimiter) ? $tvFiltersOrDelimiter : \'||\';
  115. $tvFiltersAndDelimiter = isset($tvFiltersAndDelimiter) ? $tvFiltersAndDelimiter : \',\';
  116. $tvFilters = !empty($tvFilters) ? explode($tvFiltersOrDelimiter, $tvFilters) : array();
  117. $where = !empty($where) ? $modx->fromJSON($where) : array();
  118. $showUnpublished = !empty($showUnpublished) ? true : false;
  119. $showDeleted = !empty($showDeleted) ? true : false;
  120. $sortby = isset($sortby) ? $sortby : \'publishedon\';
  121. $sortbyTV = isset($sortbyTV) ? $sortbyTV : \'\';
  122. $sortbyAlias = isset($sortbyAlias) ? $sortbyAlias : \'modResource\';
  123. $sortbyEscaped = !empty($sortbyEscaped) ? true : false;
  124. $sortdir = isset($sortdir) ? $sortdir : \'DESC\';
  125. $sortdirTV = isset($sortdirTV) ? $sortdirTV : \'DESC\';
  126. $limit = isset($limit) ? (integer) $limit : 5;
  127. $offset = isset($offset) ? (integer) $offset : 0;
  128. $totalVar = !empty($totalVar) ? $totalVar : \'total\';
  129. $dbCacheFlag = !isset($dbCacheFlag) ? false : $dbCacheFlag;
  130. if (is_string($dbCacheFlag) || is_numeric($dbCacheFlag)) {
  131. if ($dbCacheFlag == \'0\') {
  132. $dbCacheFlag = false;
  133. } elseif ($dbCacheFlag == \'1\') {
  134. $dbCacheFlag = true;
  135. } else {
  136. $dbCacheFlag = (integer) $dbCacheFlag;
  137. }
  138. }
  139. /* multiple context support */
  140. $contextArray = array();
  141. $contextSpecified = false;
  142. if (!empty($context)) {
  143. $contextArray = explode(\',\',$context);
  144. array_walk($contextArray, \'trim\');
  145. $contexts = array();
  146. foreach ($contextArray as $ctx) {
  147. $contexts[] = $modx->quote($ctx);
  148. }
  149. $context = implode(\',\',$contexts);
  150. $contextSpecified = true;
  151. unset($contexts,$ctx);
  152. } else {
  153. $context = $modx->quote($modx->context->get(\'key\'));
  154. }
  155. $pcMap = array();
  156. $pcQuery = $modx->newQuery(\'modResource\', array(\'id:IN\' => $parents), $dbCacheFlag);
  157. $pcQuery->select(array(\'id\', \'context_key\'));
  158. if ($pcQuery->prepare() && $pcQuery->stmt->execute()) {
  159. foreach ($pcQuery->stmt->fetchAll(PDO::FETCH_ASSOC) as $pcRow) {
  160. $pcMap[(integer) $pcRow[\'id\']] = $pcRow[\'context_key\'];
  161. }
  162. }
  163. $children = array();
  164. $parentArray = array();
  165. foreach ($parents as $parent) {
  166. $parent = (integer) $parent;
  167. if ($parent === 0) {
  168. $pchildren = array();
  169. if ($contextSpecified) {
  170. foreach ($contextArray as $pCtx) {
  171. if (!in_array($pCtx, $contextArray)) {
  172. continue;
  173. }
  174. $options = $pCtx !== $modx->context->get(\'key\') ? array(\'context\' => $pCtx) : array();
  175. $pcchildren = $modx->getChildIds($parent, $depth, $options);
  176. if (!empty($pcchildren)) $pchildren = array_merge($pchildren, $pcchildren);
  177. }
  178. } else {
  179. $cQuery = $modx->newQuery(\'modContext\', array(\'key:!=\' => \'mgr\'));
  180. $cQuery->select(array(\'key\'));
  181. if ($cQuery->prepare() && $cQuery->stmt->execute()) {
  182. foreach ($cQuery->stmt->fetchAll(PDO::FETCH_COLUMN) as $pCtx) {
  183. $options = $pCtx !== $modx->context->get(\'key\') ? array(\'context\' => $pCtx) : array();
  184. $pcchildren = $modx->getChildIds($parent, $depth, $options);
  185. if (!empty($pcchildren)) $pchildren = array_merge($pchildren, $pcchildren);
  186. }
  187. }
  188. }
  189. $parentArray[] = $parent;
  190. } else {
  191. $pContext = array_key_exists($parent, $pcMap) ? $pcMap[$parent] : false;
  192. if ($debug) $modx->log(modX::LOG_LEVEL_ERROR, "context for {$parent} is {$pContext}");
  193. if ($pContext && $contextSpecified && !in_array($pContext, $contextArray, true)) {
  194. $parent = next($parents);
  195. continue;
  196. }
  197. $parentArray[] = $parent;
  198. $options = !empty($pContext) && $pContext !== $modx->context->get(\'key\') ? array(\'context\' => $pContext) : array();
  199. $pchildren = $modx->getChildIds($parent, $depth, $options);
  200. }
  201. if (!empty($pchildren)) $children = array_merge($children, $pchildren);
  202. $parent = next($parents);
  203. }
  204. $parents = array_merge($parentArray, $children);
  205. /* build query */
  206. $criteria = array("modResource.parent IN (" . implode(\',\', $parents) . ")");
  207. if ($contextSpecified) {
  208. $contextResourceTbl = $modx->getTableName(\'modContextResource\');
  209. $criteria[] = "(modResource.context_key IN ({$context}) OR EXISTS(SELECT 1 FROM {$contextResourceTbl} ctx WHERE ctx.resource = modResource.id AND ctx.context_key IN ({$context})))";
  210. }
  211. if (empty($showDeleted)) {
  212. $criteria[\'deleted\'] = \'0\';
  213. }
  214. if (empty($showUnpublished)) {
  215. $criteria[\'published\'] = \'1\';
  216. }
  217. if (empty($showHidden)) {
  218. $criteria[\'hidemenu\'] = \'0\';
  219. }
  220. if (!empty($hideContainers)) {
  221. $criteria[\'isfolder\'] = \'0\';
  222. }
  223. $criteria = $modx->newQuery(\'modResource\', $criteria);
  224. if (!empty($tvFilters)) {
  225. $tmplVarTbl = $modx->getTableName(\'modTemplateVar\');
  226. $tmplVarResourceTbl = $modx->getTableName(\'modTemplateVarResource\');
  227. $conditions = array();
  228. $operators = array(
  229. \'<=>\' => \'<=>\',
  230. \'===\' => \'=\',
  231. \'!==\' => \'!=\',
  232. \'<>\' => \'<>\',
  233. \'==\' => \'LIKE\',
  234. \'!=\' => \'NOT LIKE\',
  235. \'<<\' => \'<\',
  236. \'<=\' => \'<=\',
  237. \'=<\' => \'=<\',
  238. \'>>\' => \'>\',
  239. \'>=\' => \'>=\',
  240. \'=>\' => \'=>\'
  241. );
  242. foreach ($tvFilters as $fGroup => $tvFilter) {
  243. $filterGroup = array();
  244. $filters = explode($tvFiltersAndDelimiter, $tvFilter);
  245. $multiple = count($filters) > 0;
  246. foreach ($filters as $filter) {
  247. $operator = \'==\';
  248. $sqlOperator = \'LIKE\';
  249. foreach ($operators as $op => $opSymbol) {
  250. if (strpos($filter, $op, 1) !== false) {
  251. $operator = $op;
  252. $sqlOperator = $opSymbol;
  253. break;
  254. }
  255. }
  256. $tvValueField = \'tvr.value\';
  257. $tvDefaultField = \'tv.default_text\';
  258. $f = explode($operator, $filter);
  259. if (count($f) >= 2) {
  260. if (count($f) > 2) {
  261. $k = array_shift($f);
  262. $b = join($operator, $f);
  263. $f = array($k, $b);
  264. }
  265. $tvName = $modx->quote($f[0]);
  266. if (is_numeric($f[1]) && !in_array($sqlOperator, array(\'LIKE\', \'NOT LIKE\'))) {
  267. $tvValue = $f[1];
  268. if ($f[1] == (integer)$f[1]) {
  269. $tvValueField = "CAST({$tvValueField} AS SIGNED INTEGER)";
  270. $tvDefaultField = "CAST({$tvDefaultField} AS SIGNED INTEGER)";
  271. } else {
  272. $tvValueField = "CAST({$tvValueField} AS DECIMAL)";
  273. $tvDefaultField = "CAST({$tvDefaultField} AS DECIMAL)";
  274. }
  275. } else {
  276. $tvValue = $modx->quote($f[1]);
  277. }
  278. if ($multiple) {
  279. $filterGroup[] =
  280. "(EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.name = {$tvName} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id) " .
  281. "OR EXISTS (SELECT 1 FROM {$tmplVarTbl} tv WHERE tv.name = {$tvName} AND {$tvDefaultField} {$sqlOperator} {$tvValue} AND tv.id NOT IN (SELECT tmplvarid FROM {$tmplVarResourceTbl} WHERE contentid = modResource.id)) " .
  282. ")";
  283. } else {
  284. $filterGroup =
  285. "(EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.name = {$tvName} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id) " .
  286. "OR EXISTS (SELECT 1 FROM {$tmplVarTbl} tv WHERE tv.name = {$tvName} AND {$tvDefaultField} {$sqlOperator} {$tvValue} AND tv.id NOT IN (SELECT tmplvarid FROM {$tmplVarResourceTbl} WHERE contentid = modResource.id)) " .
  287. ")";
  288. }
  289. } elseif (count($f) == 1) {
  290. $tvValue = $modx->quote($f[0]);
  291. if ($multiple) {
  292. $filterGroup[] = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
  293. } else {
  294. $filterGroup = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
  295. }
  296. }
  297. }
  298. $conditions[] = $filterGroup;
  299. }
  300. if (!empty($conditions)) {
  301. $firstGroup = true;
  302. foreach ($conditions as $cGroup => $c) {
  303. if (is_array($c)) {
  304. $first = true;
  305. foreach ($c as $cond) {
  306. if ($first && !$firstGroup) {
  307. $criteria->condition($criteria->query[\'where\'][0][1], $cond, xPDOQuery::SQL_OR, null, $cGroup);
  308. } else {
  309. $criteria->condition($criteria->query[\'where\'][0][1], $cond, xPDOQuery::SQL_AND, null, $cGroup);
  310. }
  311. $first = false;
  312. }
  313. } else {
  314. $criteria->condition($criteria->query[\'where\'][0][1], $c, $firstGroup ? xPDOQuery::SQL_AND : xPDOQuery::SQL_OR, null, $cGroup);
  315. }
  316. $firstGroup = false;
  317. }
  318. }
  319. }
  320. /* include/exclude resources, via &resources=`123,-456` prop */
  321. if (!empty($resources)) {
  322. $resourceConditions = array();
  323. $resources = explode(\',\',$resources);
  324. $include = array();
  325. $exclude = array();
  326. foreach ($resources as $resource) {
  327. $resource = (int)$resource;
  328. if ($resource == 0) continue;
  329. if ($resource < 0) {
  330. $exclude[] = abs($resource);
  331. } else {
  332. $include[] = $resource;
  333. }
  334. }
  335. if (!empty($include)) {
  336. $criteria->where(array(\'OR:modResource.id:IN\' => $include), xPDOQuery::SQL_OR);
  337. }
  338. if (!empty($exclude)) {
  339. $criteria->where(array(\'modResource.id:NOT IN\' => $exclude), xPDOQuery::SQL_AND, null, 1);
  340. }
  341. }
  342. if (!empty($where)) {
  343. $criteria->where($where);
  344. }
  345. $total = $modx->getCount(\'modResource\', $criteria);
  346. $modx->setPlaceholder($totalVar, $total);
  347. $fields = array_keys($modx->getFields(\'modResource\'));
  348. if (empty($includeContent)) {
  349. $fields = array_diff($fields, array(\'content\'));
  350. }
  351. $columns = $includeContent ? $modx->getSelectColumns(\'modResource\', \'modResource\') : $modx->getSelectColumns(\'modResource\', \'modResource\', \'\', array(\'content\'), true);
  352. $criteria->select($columns);
  353. if (!empty($sortbyTV)) {
  354. $criteria->leftJoin(\'modTemplateVar\', \'tvDefault\', array(
  355. "tvDefault.name" => $sortbyTV
  356. ));
  357. $criteria->leftJoin(\'modTemplateVarResource\', \'tvSort\', array(
  358. "tvSort.contentid = modResource.id",
  359. "tvSort.tmplvarid = tvDefault.id"
  360. ));
  361. if (empty($sortbyTVType)) $sortbyTVType = \'string\';
  362. if ($modx->getOption(\'dbtype\') === \'mysql\') {
  363. switch ($sortbyTVType) {
  364. case \'integer\':
  365. $criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS SIGNED INTEGER) AS sortTV");
  366. break;
  367. case \'decimal\':
  368. $criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS DECIMAL) AS sortTV");
  369. break;
  370. case \'datetime\':
  371. $criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS DATETIME) AS sortTV");
  372. break;
  373. case \'string\':
  374. default:
  375. $criteria->select("IFNULL(tvSort.value, tvDefault.default_text) AS sortTV");
  376. break;
  377. }
  378. } elseif ($modx->getOption(\'dbtype\') === \'sqlsrv\') {
  379. switch ($sortbyTVType) {
  380. case \'integer\':
  381. $criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS BIGINT) AS sortTV");
  382. break;
  383. case \'decimal\':
  384. $criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS DECIMAL) AS sortTV");
  385. break;
  386. case \'datetime\':
  387. $criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS DATETIME) AS sortTV");
  388. break;
  389. case \'string\':
  390. default:
  391. $criteria->select("ISNULL(tvSort.value, tvDefault.default_text) AS sortTV");
  392. break;
  393. }
  394. }
  395. $criteria->sortby("sortTV", $sortdirTV);
  396. }
  397. if (!empty($sortby)) {
  398. if (strpos($sortby, \'{\') === 0) {
  399. $sorts = $modx->fromJSON($sortby);
  400. } else {
  401. $sorts = array($sortby => $sortdir);
  402. }
  403. if (is_array($sorts)) {
  404. while (list($sort, $dir) = each($sorts)) {
  405. if ($sortbyEscaped) $sort = $modx->escape($sort);
  406. if (!empty($sortbyAlias)) $sort = $modx->escape($sortbyAlias) . ".{$sort}";
  407. $criteria->sortby($sort, $dir);
  408. }
  409. }
  410. }
  411. if (!empty($limit)) $criteria->limit($limit, $offset);
  412. if (!empty($debug)) {
  413. $criteria->prepare();
  414. $modx->log(modX::LOG_LEVEL_ERROR, $criteria->toSQL());
  415. }
  416. $collection = $modx->getCollection(\'modResource\', $criteria, $dbCacheFlag);
  417. $idx = !empty($idx) || $idx === \'0\' ? (integer) $idx : 1;
  418. $first = empty($first) && $first !== \'0\' ? 1 : (integer) $first;
  419. $last = empty($last) ? (count($collection) + $idx - 1) : (integer) $last;
  420. /* include parseTpl */
  421. include_once $modx->getOption(\'getresources.core_path\',null,$modx->getOption(\'core_path\').\'components/getresources/\').\'include.parsetpl.php\';
  422. $templateVars = array();
  423. if (!empty($includeTVs) && !empty($includeTVList)) {
  424. $templateVars = $modx->getCollection(\'modTemplateVar\', array(\'name:IN\' => $includeTVList));
  425. }
  426. /** @var modResource $resource */
  427. foreach ($collection as $resourceId => $resource) {
  428. $tvs = array();
  429. if (!empty($includeTVs)) {
  430. if (empty($includeTVList)) {
  431. $templateVars = $resource->getMany(\'TemplateVars\');
  432. }
  433. /** @var modTemplateVar $templateVar */
  434. foreach ($templateVars as $tvId => $templateVar) {
  435. if (!empty($includeTVList) && !in_array($templateVar->get(\'name\'), $includeTVList)) continue;
  436. if ($processTVs && (empty($processTVList) || in_array($templateVar->get(\'name\'), $processTVList))) {
  437. $tvs[$tvPrefix . $templateVar->get(\'name\')] = $templateVar->renderOutput($resource->get(\'id\'));
  438. } else {
  439. $value = $templateVar->getValue($resource->get(\'id\'));
  440. if ($prepareTVs && method_exists($templateVar, \'prepareOutput\') && (empty($prepareTVList) || in_array($templateVar->get(\'name\'), $prepareTVList))) {
  441. $value = $templateVar->prepareOutput($value);
  442. }
  443. $tvs[$tvPrefix . $templateVar->get(\'name\')] = $value;
  444. }
  445. }
  446. }
  447. $odd = ($idx & 1);
  448. $properties = array_merge(
  449. $scriptProperties
  450. ,array(
  451. \'idx\' => $idx
  452. ,\'first\' => $first
  453. ,\'last\' => $last
  454. ,\'odd\' => $odd
  455. )
  456. ,$includeContent ? $resource->toArray() : $resource->get($fields)
  457. ,$tvs
  458. );
  459. $resourceTpl = false;
  460. if ($idx == $first && !empty($tplFirst)) {
  461. $resourceTpl = parseTpl($tplFirst, $properties);
  462. }
  463. if ($idx == $last && empty($resourceTpl) && !empty($tplLast)) {
  464. $resourceTpl = parseTpl($tplLast, $properties);
  465. }
  466. $tplidx = \'tpl_\' . $idx;
  467. if (empty($resourceTpl) && !empty($$tplidx)) {
  468. $resourceTpl = parseTpl($$tplidx, $properties);
  469. }
  470. if ($idx > 1 && empty($resourceTpl)) {
  471. $divisors = getDivisors($idx);
  472. if (!empty($divisors)) {
  473. foreach ($divisors as $divisor) {
  474. $tplnth = \'tpl_n\' . $divisor;
  475. if (!empty($$tplnth)) {
  476. $resourceTpl = parseTpl($$tplnth, $properties);
  477. if (!empty($resourceTpl)) {
  478. break;
  479. }
  480. }
  481. }
  482. }
  483. }
  484. if ($odd && empty($resourceTpl) && !empty($tplOdd)) {
  485. $resourceTpl = parseTpl($tplOdd, $properties);
  486. }
  487. if (!empty($tplCondition) && !empty($conditionalTpls) && empty($resourceTpl)) {
  488. $conTpls = $modx->fromJSON($conditionalTpls);
  489. $subject = $properties[$tplCondition];
  490. $tplOperator = !empty($tplOperator) ? $tplOperator : \'=\';
  491. $tplOperator = strtolower($tplOperator);
  492. $tplCon = \'\';
  493. foreach ($conTpls as $operand => $conditionalTpl) {
  494. switch ($tplOperator) {
  495. case \'!=\':
  496. case \'neq\':
  497. case \'not\':
  498. case \'isnot\':
  499. case \'isnt\':
  500. case \'unequal\':
  501. case \'notequal\':
  502. $tplCon = (($subject != $operand) ? $conditionalTpl : $tplCon);
  503. break;
  504. case \'<\':
  505. case \'lt\':
  506. case \'less\':
  507. case \'lessthan\':
  508. $tplCon = (($subject < $operand) ? $conditionalTpl : $tplCon);
  509. break;
  510. case \'>\':
  511. case \'gt\':
  512. case \'greater\':
  513. case \'greaterthan\':
  514. $tplCon = (($subject > $operand) ? $conditionalTpl : $tplCon);
  515. break;
  516. case \'<=\':
  517. case \'lte\':
  518. case \'lessthanequals\':
  519. case \'lessthanorequalto\':
  520. $tplCon = (($subject <= $operand) ? $conditionalTpl : $tplCon);
  521. break;
  522. case \'>=\':
  523. case \'gte\':
  524. case \'greaterthanequals\':
  525. case \'greaterthanequalto\':
  526. $tplCon = (($subject >= $operand) ? $conditionalTpl : $tplCon);
  527. break;
  528. case \'isempty\':
  529. case \'empty\':
  530. $tplCon = empty($subject) ? $conditionalTpl : $tplCon;
  531. break;
  532. case \'!empty\':
  533. case \'notempty\':
  534. case \'isnotempty\':
  535. $tplCon = !empty($subject) && $subject != \'\' ? $conditionalTpl : $tplCon;
  536. break;
  537. case \'isnull\':
  538. case \'null\':
  539. $tplCon = $subject == null || strtolower($subject) == \'null\' ? $conditionalTpl : $tplCon;
  540. break;
  541. case \'inarray\':
  542. case \'in_array\':
  543. case \'ia\':
  544. $operand = explode(\',\', $operand);
  545. $tplCon = in_array($subject, $operand) ? $conditionalTpl : $tplCon;
  546. break;
  547. case \'between\':
  548. case \'range\':
  549. case \'>=<\':
  550. case \'><\':
  551. $operand = explode(\',\', $operand);
  552. $tplCon = ($subject >= min($operand) && $subject <= max($operand)) ? $conditionalTpl : $tplCon;
  553. break;
  554. case \'==\':
  555. case \'=\':
  556. case \'eq\':
  557. case \'is\':
  558. case \'equal\':
  559. case \'equals\':
  560. case \'equalto\':
  561. default:
  562. $tplCon = (($subject == $operand) ? $conditionalTpl : $tplCon);
  563. break;
  564. }
  565. }
  566. if (!empty($tplCon)) {
  567. $resourceTpl = parseTpl($tplCon, $properties);
  568. }
  569. }
  570. if (!empty($tpl) && empty($resourceTpl)) {
  571. $resourceTpl = parseTpl($tpl, $properties);
  572. }
  573. if ($resourceTpl === false && !empty($debug)) {
  574. $chunk = $modx->newObject(\'modChunk\');
  575. $chunk->setCacheable(false);
  576. $output[]= $chunk->process(array(), \'<pre>\' . print_r($properties, true) .\'</pre>\');
  577. } else {
  578. $output[]= $resourceTpl;
  579. }
  580. $idx++;
  581. }
  582. /* output */
  583. $toSeparatePlaceholders = $modx->getOption(\'toSeparatePlaceholders\', $scriptProperties, false);
  584. if (!empty($toSeparatePlaceholders)) {
  585. $modx->setPlaceholders($output, $toSeparatePlaceholders);
  586. return \'\';
  587. }
  588. $output = implode($outputSeparator, $output);
  589. $tplWrapper = $modx->getOption(\'tplWrapper\', $scriptProperties, false);
  590. $wrapIfEmpty = $modx->getOption(\'wrapIfEmpty\', $scriptProperties, false);
  591. if (!empty($tplWrapper) && ($wrapIfEmpty || !empty($output))) {
  592. $output = parseTpl($tplWrapper, array_merge($scriptProperties, array(\'output\' => $output)));
  593. }
  594. $toPlaceholder = $modx->getOption(\'toPlaceholder\', $scriptProperties, false);
  595. if (!empty($toPlaceholder)) {
  596. $modx->setPlaceholder($toPlaceholder, $output);
  597. return \'\';
  598. }
  599. return $output;
  600. return;
  601. ';