Designed to keep all your records in one place, interfacing irrigation systems, weather data, and real-time moisture monitoring, based in Australia on local conditions.
Cloud based Soil, Plant and Water Analysis, Comprehensive Reporting based on Sustainable Agricultural Practices.
Grayscale is a free Bootstrap theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
[[!FormIt?
&hooks=`spam,email`
&submitVar=`enquiry-submit`
&emailTpl=`CMenquiryEmailTpl`
&emailTo=`enquiries@cropmonitor.info`
&successMessage=`Thankyou for contacting us, we will be in touch soon.`
&validationErrorMessage=`true`
&validate=`nospam:blank,
name:required,
email:email:required,
text:required:stripTags`
]]
[[!+fi.successMessage:notempty=`
[[!+fi.successMessage]]
`]]
[[!+fi.validation_error_message:notempty=`
[[+errors]] [[!+fi.validation_error_message]]
`]]
Try out our Soil Test Analysis Report
* required fields.
[[!soilformSubmit]]
Try out our Plant Analysis Report
* required fields.
[[!plantformSubmit]]
',
'_isForward' => false,
),
'contentType' =>
array (
'id' => 1,
'name' => 'HTML',
'description' => 'HTML content',
'mime_type' => 'text/html',
'file_extensions' => '.html',
'headers' => NULL,
'binary' => 0,
),
'policyCache' =>
array (
),
'elementCache' =>
array (
'[[*longtitle]]' => 'Crop Management Platform',
'[[*introtext]]' => 'crop management, irrigation alerts, weather reporting, moisture monitoring, realtime dashboard, agricultural monitoring.',
'[[*description]]' => 'Designed to keep all your records in one place, interfacing irrigation systems, weather data, and real-time moisture monitoring, based in Australia on local conditions.',
'[[$dash-header]]' => '
',
'[[~4]]' => 'login/',
'[[*id]]' => 1,
'[[blogit.lexicon_load]]' => '',
'[[~1]]' => '/',
'[[$analysis_Clientdetails]]' => '
\');
} else {
$output[]= $resourceTpl;
}
$idx++;
}
/* output */
$toSeparatePlaceholders = $modx->getOption(\'toSeparatePlaceholders\', $scriptProperties, false);
if (!empty($toSeparatePlaceholders)) {
$modx->setPlaceholders($output, $toSeparatePlaceholders);
return \'\';
}
$output = implode($outputSeparator, $output);
$tplWrapper = $modx->getOption(\'tplWrapper\', $scriptProperties, false);
$wrapIfEmpty = $modx->getOption(\'wrapIfEmpty\', $scriptProperties, false);
if (!empty($tplWrapper) && ($wrapIfEmpty || !empty($output))) {
$output = parseTpl($tplWrapper, array_merge($scriptProperties, array(\'output\' => $output)));
}
$toPlaceholder = $modx->getOption(\'toPlaceholder\', $scriptProperties, false);
if (!empty($toPlaceholder)) {
$modx->setPlaceholder($toPlaceholder, $output);
return \'\';
}
return $output;',
'locked' => false,
'properties' =>
array (
'tpl' =>
array (
'name' => 'tpl',
'desc' => 'Name of a chunk serving as a resource template. NOTE: if not provided, properties are dumped to output for each resource.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a chunk serving as a resource template. NOTE: if not provided, properties are dumped to output for each resource.',
'area_trans' => '',
),
'tplOdd' =>
array (
'name' => 'tplOdd',
'desc' => 'Name of a chunk serving as resource template for resources with an odd idx value (see idx property).',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a chunk serving as resource template for resources with an odd idx value (see idx property).',
'area_trans' => '',
),
'tplFirst' =>
array (
'name' => 'tplFirst',
'desc' => 'Name of a chunk serving as resource template for the first resource (see first property).',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a chunk serving as resource template for the first resource (see first property).',
'area_trans' => '',
),
'tplLast' =>
array (
'name' => 'tplLast',
'desc' => 'Name of a chunk serving as resource template for the last resource (see last property).',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a chunk serving as resource template for the last resource (see last property).',
'area_trans' => '',
),
'tplWrapper' =>
array (
'name' => 'tplWrapper',
'desc' => 'Name of a chunk serving as wrapper template for the Snippet output. This does not work with toSeparatePlaceholders.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a chunk serving as wrapper template for the Snippet output. This does not work with toSeparatePlaceholders.',
'area_trans' => '',
),
'wrapIfEmpty' =>
array (
'name' => 'wrapIfEmpty',
'desc' => 'Indicates if empty output should be wrapped by the tplWrapper, if specified. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if empty output should be wrapped by the tplWrapper, if specified. Defaults to false.',
'area_trans' => '',
),
'sortby' =>
array (
'name' => 'sortby',
'desc' => 'A field name to sort by or JSON object of field names and sortdir for each field, e.g. {"publishedon":"ASC","createdon":"DESC"}. Defaults to publishedon.',
'type' => 'textfield',
'options' => '',
'value' => 'publishedon',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A field name to sort by or JSON object of field names and sortdir for each field, e.g. {"publishedon":"ASC","createdon":"DESC"}. Defaults to publishedon.',
'area_trans' => '',
),
'sortbyTV' =>
array (
'name' => 'sortbyTV',
'desc' => 'Name of a Template Variable to sort by. Defaults to empty string.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Name of a Template Variable to sort by. Defaults to empty string.',
'area_trans' => '',
),
'sortbyTVType' =>
array (
'name' => 'sortbyTVType',
'desc' => 'An optional type to indicate how to sort on the Template Variable value.',
'type' => 'list',
'options' =>
array (
0 =>
array (
'text' => 'string',
'value' => 'string',
'name' => 'string',
),
1 =>
array (
'text' => 'integer',
'value' => 'integer',
'name' => 'integer',
),
2 =>
array (
'text' => 'decimal',
'value' => 'decimal',
'name' => 'decimal',
),
3 =>
array (
'text' => 'datetime',
'value' => 'datetime',
'name' => 'datetime',
),
),
'value' => 'string',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'An optional type to indicate how to sort on the Template Variable value.',
'area_trans' => '',
),
'sortbyAlias' =>
array (
'name' => 'sortbyAlias',
'desc' => 'Query alias for sortby field. Defaults to an empty string.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Query alias for sortby field. Defaults to an empty string.',
'area_trans' => '',
),
'sortbyEscaped' =>
array (
'name' => 'sortbyEscaped',
'desc' => 'Determines if the field name specified in sortby should be escaped. Defaults to 0.',
'type' => 'textfield',
'options' => '',
'value' => '0',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Determines if the field name specified in sortby should be escaped. Defaults to 0.',
'area_trans' => '',
),
'sortdir' =>
array (
'name' => 'sortdir',
'desc' => 'Order which to sort by. Defaults to DESC.',
'type' => 'list',
'options' =>
array (
0 =>
array (
'text' => 'ASC',
'value' => 'ASC',
'name' => 'ASC',
),
1 =>
array (
'text' => 'DESC',
'value' => 'DESC',
'name' => 'DESC',
),
),
'value' => 'DESC',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Order which to sort by. Defaults to DESC.',
'area_trans' => '',
),
'sortdirTV' =>
array (
'name' => 'sortdirTV',
'desc' => 'Order which to sort a Template Variable by. Defaults to DESC.',
'type' => 'list',
'options' =>
array (
0 =>
array (
'text' => 'ASC',
'value' => 'ASC',
'name' => 'ASC',
),
1 =>
array (
'text' => 'DESC',
'value' => 'DESC',
'name' => 'DESC',
),
),
'value' => 'DESC',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Order which to sort a Template Variable by. Defaults to DESC.',
'area_trans' => '',
),
'limit' =>
array (
'name' => 'limit',
'desc' => 'Limits the number of resources returned. Defaults to 5.',
'type' => 'textfield',
'options' => '',
'value' => '5',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Limits the number of resources returned. Defaults to 5.',
'area_trans' => '',
),
'offset' =>
array (
'name' => 'offset',
'desc' => 'An offset of resources returned by the criteria to skip.',
'type' => 'textfield',
'options' => '',
'value' => '0',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'An offset of resources returned by the criteria to skip.',
'area_trans' => '',
),
'tvFilters' =>
array (
'name' => 'tvFilters',
'desc' => 'Delimited-list of TemplateVar values to filter resources by. Supports two delimiters and two value search formats. THe first delimiter || represents a logical OR and the primary grouping mechanism. Within each group you can provide a comma-delimited list of values. These values can be either tied to a specific TemplateVar by name, e.g. myTV==value, or just the value, indicating you are searching for the value in any TemplateVar tied to the Resource. An example would be &tvFilters=`filter2==one,filter1==bar%||filter1==foo`. NOTE: filtering by values uses a LIKE query and % is considered a wildcard. ANOTHER NOTE: This only looks at the raw value set for specific Resource, i. e. there must be a value specifically set for the Resource and it is not evaluated.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Delimited-list of TemplateVar values to filter resources by. Supports two delimiters and two value search formats. THe first delimiter || represents a logical OR and the primary grouping mechanism. Within each group you can provide a comma-delimited list of values. These values can be either tied to a specific TemplateVar by name, e.g. myTV==value, or just the value, indicating you are searching for the value in any TemplateVar tied to the Resource. An example would be &tvFilters=`filter2==one,filter1==bar%||filter1==foo`. NOTE: filtering by values uses a LIKE query and % is considered a wildcard. ANOTHER NOTE: This only looks at the raw value set for specific Resource, i. e. there must be a value specifically set for the Resource and it is not evaluated.',
'area_trans' => '',
),
'tvFiltersAndDelimiter' =>
array (
'name' => 'tvFiltersAndDelimiter',
'desc' => 'The delimiter to use to separate logical AND expressions in tvFilters. Default is ,',
'type' => 'textfield',
'options' => '',
'value' => ',',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The delimiter to use to separate logical AND expressions in tvFilters. Default is ,',
'area_trans' => '',
),
'tvFiltersOrDelimiter' =>
array (
'name' => 'tvFiltersOrDelimiter',
'desc' => 'The delimiter to use to separate logical OR expressions in tvFilters. Default is ||',
'type' => 'textfield',
'options' => '',
'value' => '||',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The delimiter to use to separate logical OR expressions in tvFilters. Default is ||',
'area_trans' => '',
),
'depth' =>
array (
'name' => 'depth',
'desc' => 'Integer value indicating depth to search for resources from each parent. Defaults to 10.',
'type' => 'textfield',
'options' => '',
'value' => '10',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Integer value indicating depth to search for resources from each parent. Defaults to 10.',
'area_trans' => '',
),
'parents' =>
array (
'name' => 'parents',
'desc' => 'Optional. Comma-delimited list of ids serving as parents.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Optional. Comma-delimited list of ids serving as parents.',
'area_trans' => '',
),
'includeContent' =>
array (
'name' => 'includeContent',
'desc' => 'Indicates if the content of each resource should be returned in the results. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if the content of each resource should be returned in the results. Defaults to false.',
'area_trans' => '',
),
'includeTVs' =>
array (
'name' => 'includeTVs',
'desc' => 'Indicates if TemplateVar values should be included in the properties available to each resource template. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if TemplateVar values should be included in the properties available to each resource template. Defaults to false.',
'area_trans' => '',
),
'includeTVList' =>
array (
'name' => 'includeTVList',
'desc' => 'Limits included TVs to those specified as a comma-delimited list of TV names. Defaults to empty.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Limits included TVs to those specified as a comma-delimited list of TV names. Defaults to empty.',
'area_trans' => '',
),
'showHidden' =>
array (
'name' => 'showHidden',
'desc' => 'Indicates if Resources that are hidden from menus should be shown. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if Resources that are hidden from menus should be shown. Defaults to false.',
'area_trans' => '',
),
'showUnpublished' =>
array (
'name' => 'showUnpublished',
'desc' => 'Indicates if Resources that are unpublished should be shown. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if Resources that are unpublished should be shown. Defaults to false.',
'area_trans' => '',
),
'showDeleted' =>
array (
'name' => 'showDeleted',
'desc' => 'Indicates if Resources that are deleted should be shown. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if Resources that are deleted should be shown. Defaults to false.',
'area_trans' => '',
),
'resources' =>
array (
'name' => 'resources',
'desc' => 'A comma-separated list of resource IDs to exclude or include. IDs with a - in front mean to exclude. Ex: 123,-456 means to include Resource 123, but always exclude Resource 456.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A comma-separated list of resource IDs to exclude or include. IDs with a - in front mean to exclude. Ex: 123,-456 means to include Resource 123, but always exclude Resource 456.',
'area_trans' => '',
),
'processTVs' =>
array (
'name' => 'processTVs',
'desc' => 'Indicates if TemplateVar values should be rendered as they would on the resource being summarized. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if TemplateVar values should be rendered as they would on the resource being summarized. Defaults to false.',
'area_trans' => '',
),
'processTVList' =>
array (
'name' => 'processTVList',
'desc' => 'Limits processed TVs to those specified as a comma-delimited list of TV names; note only includedTVs will be available for processing if specified. Defaults to empty.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Limits processed TVs to those specified as a comma-delimited list of TV names; note only includedTVs will be available for processing if specified. Defaults to empty.',
'area_trans' => '',
),
'prepareTVs' =>
array (
'name' => 'prepareTVs',
'desc' => 'Indicates if TemplateVar values that are not processed fully should be prepared before being returned. Defaults to true.',
'type' => 'combo-boolean',
'options' => '',
'value' => true,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Indicates if TemplateVar values that are not processed fully should be prepared before being returned. Defaults to true.',
'area_trans' => '',
),
'prepareTVList' =>
array (
'name' => 'prepareTVList',
'desc' => 'Limits prepared TVs to those specified as a comma-delimited list of TV names; note only includedTVs will be available for preparing if specified. Defaults to empty.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Limits prepared TVs to those specified as a comma-delimited list of TV names; note only includedTVs will be available for preparing if specified. Defaults to empty.',
'area_trans' => '',
),
'tvPrefix' =>
array (
'name' => 'tvPrefix',
'desc' => 'The prefix for TemplateVar properties. Defaults to: tv.',
'type' => 'textfield',
'options' => '',
'value' => 'tv.',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The prefix for TemplateVar properties. Defaults to: tv.',
'area_trans' => '',
),
'idx' =>
array (
'name' => 'idx',
'desc' => 'You can define the starting idx of the resources, which is an property that is incremented as each resource is rendered.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'You can define the starting idx of the resources, which is an property that is incremented as each resource is rendered.',
'area_trans' => '',
),
'first' =>
array (
'name' => 'first',
'desc' => 'Define the idx which represents the first resource (see tplFirst). Defaults to 1.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Define the idx which represents the first resource (see tplFirst). Defaults to 1.',
'area_trans' => '',
),
'last' =>
array (
'name' => 'last',
'desc' => 'Define the idx which represents the last resource (see tplLast). Defaults to the number of resources being summarized + first - 1',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Define the idx which represents the last resource (see tplLast). Defaults to the number of resources being summarized + first - 1',
'area_trans' => '',
),
'toPlaceholder' =>
array (
'name' => 'toPlaceholder',
'desc' => 'If set, will assign the result to this placeholder instead of outputting it directly.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'If set, will assign the result to this placeholder instead of outputting it directly.',
'area_trans' => '',
),
'toSeparatePlaceholders' =>
array (
'name' => 'toSeparatePlaceholders',
'desc' => 'If set, will assign EACH result to a separate placeholder named by this param suffixed with a sequential number (starting from 0).',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'If set, will assign EACH result to a separate placeholder named by this param suffixed with a sequential number (starting from 0).',
'area_trans' => '',
),
'debug' =>
array (
'name' => 'debug',
'desc' => 'If true, will send the SQL query to the MODX log. Defaults to false.',
'type' => 'combo-boolean',
'options' => '',
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'If true, will send the SQL query to the MODX log. Defaults to false.',
'area_trans' => '',
),
'where' =>
array (
'name' => 'where',
'desc' => 'A JSON expression of criteria to build any additional where clauses from, e.g. &where=`{{"alias:LIKE":"foo%", "OR:alias:LIKE":"%bar"},{"OR:pagetitle:=":"foobar", "AND:description:=":"raboof"}}`',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A JSON expression of criteria to build any additional where clauses from, e.g. &where=`{{"alias:LIKE":"foo%", "OR:alias:LIKE":"%bar"},{"OR:pagetitle:=":"foobar", "AND:description:=":"raboof"}}`',
'area_trans' => '',
),
'dbCacheFlag' =>
array (
'name' => 'dbCacheFlag',
'desc' => 'Determines how result sets are cached if cache_db is enabled in MODX. 0|false = do not cache result set; 1 = cache result set according to cache settings, any other integer value = number of seconds to cache result set',
'type' => 'textfield',
'options' => '',
'value' => '0',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'Determines how result sets are cached if cache_db is enabled in MODX. 0|false = do not cache result set; 1 = cache result set according to cache settings, any other integer value = number of seconds to cache result set',
'area_trans' => '',
),
'context' =>
array (
'name' => 'context',
'desc' => 'A comma-delimited list of context keys for limiting results. Default is empty, i.e. do not limit results by context.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A comma-delimited list of context keys for limiting results. Default is empty, i.e. do not limit results by context.',
'area_trans' => '',
),
'tplCondition' =>
array (
'name' => 'tplCondition',
'desc' => 'A condition to compare against the conditionalTpls property to map Resources to different tpls based on custom conditional logic.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A condition to compare against the conditionalTpls property to map Resources to different tpls based on custom conditional logic.',
'area_trans' => '',
),
'tplOperator' =>
array (
'name' => 'tplOperator',
'desc' => 'An optional operator to use for the tplCondition when comparing against the conditionalTpls operands. Default is == (equals).',
'type' => 'list',
'options' =>
array (
0 =>
array (
'text' => 'is equal to',
'value' => '==',
'name' => 'is equal to',
),
1 =>
array (
'text' => 'is not equal to',
'value' => '!=',
'name' => 'is not equal to',
),
2 =>
array (
'text' => 'less than',
'value' => '<',
'name' => 'less than',
),
3 =>
array (
'text' => 'less than or equal to',
'value' => '<=',
'name' => 'less than or equal to',
),
4 =>
array (
'text' => 'greater than or equal to',
'value' => '>=',
'name' => 'greater than or equal to',
),
5 =>
array (
'text' => 'is empty',
'value' => 'empty',
'name' => 'is empty',
),
6 =>
array (
'text' => 'is not empty',
'value' => '!empty',
'name' => 'is not empty',
),
7 =>
array (
'text' => 'is null',
'value' => 'null',
'name' => 'is null',
),
8 =>
array (
'text' => 'is in array',
'value' => 'inarray',
'name' => 'is in array',
),
9 =>
array (
'text' => 'is between',
'value' => 'between',
'name' => 'is between',
),
),
'value' => '==',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'An optional operator to use for the tplCondition when comparing against the conditionalTpls operands. Default is == (equals).',
'area_trans' => '',
),
'conditionalTpls' =>
array (
'name' => 'conditionalTpls',
'desc' => 'A JSON map of conditional operands and tpls to compare against the tplCondition property using the specified tplOperator.',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'A JSON map of conditional operands and tpls to compare against the tplCondition property using the specified tplOperator.',
'area_trans' => '',
),
),
'moduleguid' => '',
'static' => false,
'static_file' => '',
'content' => '/**
* getResources
*
* A general purpose Resource listing and summarization snippet for MODX 2.x.
*
* @author Jason Coward
* @copyright Copyright 2010-2013, Jason Coward
*
* TEMPLATES
*
* tpl - Name of a chunk serving as a resource template
* [NOTE: if not provided, properties are dumped to output for each resource]
*
* tplOdd - (Opt) Name of a chunk serving as resource template for resources with an odd idx value
* (see idx property)
* tplFirst - (Opt) Name of a chunk serving as resource template for the first resource (see first
* property)
* tplLast - (Opt) Name of a chunk serving as resource template for the last resource (see last
* property)
* tpl_{n} - (Opt) Name of a chunk serving as resource template for the nth resource
*
* tplCondition - (Opt) Defines a field of the resource to evaluate against keys defined in the
* conditionalTpls property. Must be a resource field; does not work with Template Variables.
* conditionalTpls - (Opt) A JSON object defining a map of field values and the associated tpl to
* use when the field defined by tplCondition matches the value. [NOTE: tplOdd, tplFirst, tplLast,
* and tpl_{n} will take precedence over any defined conditionalTpls]
*
* tplWrapper - (Opt) Name of a chunk serving as a wrapper template for the output
* [NOTE: Does not work with toSeparatePlaceholders]
*
* SELECTION
*
* parents - Comma-delimited list of ids serving as parents
*
* context - (Opt) Comma-delimited list of context keys to limit results by; if empty, contexts for all specified
* parents will be used (all contexts if 0 is specified) [default=]
*
* depth - (Opt) Integer value indicating depth to search for resources from each parent [default=10]
*
* tvFilters - (Opt) Delimited-list of TemplateVar values to filter resources by. Supports two
* delimiters and two value search formats. The first delimiter || represents a logical OR and the
* primary grouping mechanism. Within each group you can provide a comma-delimited list of values.
* These values can be either tied to a specific TemplateVar by name, e.g. myTV==value, or just the
* value, indicating you are searching for the value in any TemplateVar tied to the Resource. An
* example would be &tvFilters=`filter2==one,filter1==bar%||filter1==foo`
* [NOTE: filtering by values uses a LIKE query and % is considered a wildcard.]
* [NOTE: this only looks at the raw value set for specific Resource, i. e. there must be a value
* specifically set for the Resource and it is not evaluated.]
*
* tvFiltersAndDelimiter - (Opt) Custom delimiter for logical AND, default \',\', in case you want to
* match a literal comma in the tvFilters. E.g. &tvFiltersAndDelimiter=`&&`
* &tvFilters=`filter1==foo,bar&&filter2==baz` [default=,]
*
* tvFiltersOrDelimiter - (Opt) Custom delimiter for logical OR, default \'||\', in case you want to
* match a literal \'||\' in the tvFilters. E.g. &tvFiltersOrDelimiter=`|OR|`
* &tvFilters=`filter1==foo||bar|OR|filter2==baz` [default=||]
*
* where - (Opt) A JSON expression of criteria to build any additional where clauses from. An example would be
* &where=`{{"alias:LIKE":"foo%", "OR:alias:LIKE":"%bar"},{"OR:pagetitle:=":"foobar", "AND:description:=":"raboof"}}`
*
* sortby - (Opt) Field to sort by or a JSON array, e.g. {"publishedon":"ASC","createdon":"DESC"} [default=publishedon]
* sortbyTV - (opt) A Template Variable name to sort by (if supplied, this precedes the sortby value) [default=]
* sortbyTVType - (Opt) A data type to CAST a TV Value to in order to sort on it properly [default=string]
* sortbyAlias - (Opt) Query alias for sortby field [default=]
* sortbyEscaped - (Opt) Escapes the field name(s) specified in sortby [default=0]
* sortdir - (Opt) Order which to sort by [default=DESC]
* sortdirTV - (Opt) Order which to sort by a TV [default=DESC]
* limit - (Opt) Limits the number of resources returned [default=5]
* offset - (Opt) An offset of resources returned by the criteria to skip [default=0]
* dbCacheFlag - (Opt) Controls caching of db queries; 0|false = do not cache result set; 1 = cache result set
* according to cache settings, any other integer value = number of seconds to cache result set [default=0]
*
* OPTIONS
*
* includeContent - (Opt) Indicates if the content of each resource should be returned in the
* results [default=0]
* includeTVs - (Opt) Indicates if TemplateVar values should be included in the properties available
* to each resource template [default=0]
* includeTVList - (Opt) Limits the TemplateVars that are included if includeTVs is true to those specified
* by name in a comma-delimited list [default=]
* prepareTVs - (Opt) Prepares media-source dependent TemplateVar values [default=1]
* prepareTVList - (Opt) Limits the TVs that are prepared to those specified by name in a comma-delimited
* list [default=]
* processTVs - (Opt) Indicates if TemplateVar values should be rendered as they would on the
* resource being summarized [default=0]
* processTVList - (opt) Limits the TemplateVars that are processed if included to those specified
* by name in a comma-delimited list [default=]
* tvPrefix - (Opt) The prefix for TemplateVar properties [default=tv.]
* idx - (Opt) You can define the starting idx of the resources, which is an property that is
* incremented as each resource is rendered [default=1]
* first - (Opt) Define the idx which represents the first resource (see tplFirst) [default=1]
* last - (Opt) Define the idx which represents the last resource (see tplLast) [default=# of
* resources being summarized + first - 1]
* outputSeparator - (Opt) An optional string to separate each tpl instance [default="\\n"]
* wrapIfEmpty - (Opt) Indicates if the tplWrapper should be applied if the output is empty [default=0]
*
*/
$output = array();
$outputSeparator = isset($outputSeparator) ? $outputSeparator : "\\n";
/* set default properties */
$tpl = !empty($tpl) ? $tpl : \'\';
$includeContent = !empty($includeContent) ? true : false;
$includeTVs = !empty($includeTVs) ? true : false;
$includeTVList = !empty($includeTVList) ? explode(\',\', $includeTVList) : array();
$processTVs = !empty($processTVs) ? true : false;
$processTVList = !empty($processTVList) ? explode(\',\', $processTVList) : array();
$prepareTVs = !empty($prepareTVs) ? true : false;
$prepareTVList = !empty($prepareTVList) ? explode(\',\', $prepareTVList) : array();
$tvPrefix = isset($tvPrefix) ? $tvPrefix : \'tv.\';
$parents = (!empty($parents) || $parents === \'0\') ? explode(\',\', $parents) : array($modx->resource->get(\'id\'));
array_walk($parents, \'trim\');
$parents = array_unique($parents);
$depth = isset($depth) ? (integer) $depth : 10;
$tvFiltersOrDelimiter = isset($tvFiltersOrDelimiter) ? $tvFiltersOrDelimiter : \'||\';
$tvFiltersAndDelimiter = isset($tvFiltersAndDelimiter) ? $tvFiltersAndDelimiter : \',\';
$tvFilters = !empty($tvFilters) ? explode($tvFiltersOrDelimiter, $tvFilters) : array();
$where = !empty($where) ? $modx->fromJSON($where) : array();
$showUnpublished = !empty($showUnpublished) ? true : false;
$showDeleted = !empty($showDeleted) ? true : false;
$sortby = isset($sortby) ? $sortby : \'publishedon\';
$sortbyTV = isset($sortbyTV) ? $sortbyTV : \'\';
$sortbyAlias = isset($sortbyAlias) ? $sortbyAlias : \'modResource\';
$sortbyEscaped = !empty($sortbyEscaped) ? true : false;
$sortdir = isset($sortdir) ? $sortdir : \'DESC\';
$sortdirTV = isset($sortdirTV) ? $sortdirTV : \'DESC\';
$limit = isset($limit) ? (integer) $limit : 5;
$offset = isset($offset) ? (integer) $offset : 0;
$totalVar = !empty($totalVar) ? $totalVar : \'total\';
$dbCacheFlag = !isset($dbCacheFlag) ? false : $dbCacheFlag;
if (is_string($dbCacheFlag) || is_numeric($dbCacheFlag)) {
if ($dbCacheFlag == \'0\') {
$dbCacheFlag = false;
} elseif ($dbCacheFlag == \'1\') {
$dbCacheFlag = true;
} else {
$dbCacheFlag = (integer) $dbCacheFlag;
}
}
/* multiple context support */
$contextArray = array();
$contextSpecified = false;
if (!empty($context)) {
$contextArray = explode(\',\',$context);
array_walk($contextArray, \'trim\');
$contexts = array();
foreach ($contextArray as $ctx) {
$contexts[] = $modx->quote($ctx);
}
$context = implode(\',\',$contexts);
$contextSpecified = true;
unset($contexts,$ctx);
} else {
$context = $modx->quote($modx->context->get(\'key\'));
}
$pcMap = array();
$pcQuery = $modx->newQuery(\'modResource\', array(\'id:IN\' => $parents), $dbCacheFlag);
$pcQuery->select(array(\'id\', \'context_key\'));
if ($pcQuery->prepare() && $pcQuery->stmt->execute()) {
foreach ($pcQuery->stmt->fetchAll(PDO::FETCH_ASSOC) as $pcRow) {
$pcMap[(integer) $pcRow[\'id\']] = $pcRow[\'context_key\'];
}
}
$children = array();
$parentArray = array();
foreach ($parents as $parent) {
$parent = (integer) $parent;
if ($parent === 0) {
$pchildren = array();
if ($contextSpecified) {
foreach ($contextArray as $pCtx) {
if (!in_array($pCtx, $contextArray)) {
continue;
}
$options = $pCtx !== $modx->context->get(\'key\') ? array(\'context\' => $pCtx) : array();
$pcchildren = $modx->getChildIds($parent, $depth, $options);
if (!empty($pcchildren)) $pchildren = array_merge($pchildren, $pcchildren);
}
} else {
$cQuery = $modx->newQuery(\'modContext\', array(\'key:!=\' => \'mgr\'));
$cQuery->select(array(\'key\'));
if ($cQuery->prepare() && $cQuery->stmt->execute()) {
foreach ($cQuery->stmt->fetchAll(PDO::FETCH_COLUMN) as $pCtx) {
$options = $pCtx !== $modx->context->get(\'key\') ? array(\'context\' => $pCtx) : array();
$pcchildren = $modx->getChildIds($parent, $depth, $options);
if (!empty($pcchildren)) $pchildren = array_merge($pchildren, $pcchildren);
}
}
}
$parentArray[] = $parent;
} else {
$pContext = array_key_exists($parent, $pcMap) ? $pcMap[$parent] : false;
if ($debug) $modx->log(modX::LOG_LEVEL_ERROR, "context for {$parent} is {$pContext}");
if ($pContext && $contextSpecified && !in_array($pContext, $contextArray, true)) {
$parent = next($parents);
continue;
}
$parentArray[] = $parent;
$options = !empty($pContext) && $pContext !== $modx->context->get(\'key\') ? array(\'context\' => $pContext) : array();
$pchildren = $modx->getChildIds($parent, $depth, $options);
}
if (!empty($pchildren)) $children = array_merge($children, $pchildren);
$parent = next($parents);
}
$parents = array_merge($parentArray, $children);
/* build query */
$criteria = array("modResource.parent IN (" . implode(\',\', $parents) . ")");
if ($contextSpecified) {
$contextResourceTbl = $modx->getTableName(\'modContextResource\');
$criteria[] = "(modResource.context_key IN ({$context}) OR EXISTS(SELECT 1 FROM {$contextResourceTbl} ctx WHERE ctx.resource = modResource.id AND ctx.context_key IN ({$context})))";
}
if (empty($showDeleted)) {
$criteria[\'deleted\'] = \'0\';
}
if (empty($showUnpublished)) {
$criteria[\'published\'] = \'1\';
}
if (empty($showHidden)) {
$criteria[\'hidemenu\'] = \'0\';
}
if (!empty($hideContainers)) {
$criteria[\'isfolder\'] = \'0\';
}
$criteria = $modx->newQuery(\'modResource\', $criteria);
if (!empty($tvFilters)) {
$tmplVarTbl = $modx->getTableName(\'modTemplateVar\');
$tmplVarResourceTbl = $modx->getTableName(\'modTemplateVarResource\');
$conditions = array();
$operators = array(
\'<=>\' => \'<=>\',
\'===\' => \'=\',
\'!==\' => \'!=\',
\'<>\' => \'<>\',
\'==\' => \'LIKE\',
\'!=\' => \'NOT LIKE\',
\'<<\' => \'<\',
\'<=\' => \'<=\',
\'=<\' => \'=<\',
\'>>\' => \'>\',
\'>=\' => \'>=\',
\'=>\' => \'=>\'
);
foreach ($tvFilters as $fGroup => $tvFilter) {
$filterGroup = array();
$filters = explode($tvFiltersAndDelimiter, $tvFilter);
$multiple = count($filters) > 0;
foreach ($filters as $filter) {
$operator = \'==\';
$sqlOperator = \'LIKE\';
foreach ($operators as $op => $opSymbol) {
if (strpos($filter, $op, 1) !== false) {
$operator = $op;
$sqlOperator = $opSymbol;
break;
}
}
$tvValueField = \'tvr.value\';
$tvDefaultField = \'tv.default_text\';
$f = explode($operator, $filter);
if (count($f) >= 2) {
if (count($f) > 2) {
$k = array_shift($f);
$b = join($operator, $f);
$f = array($k, $b);
}
$tvName = $modx->quote($f[0]);
if (is_numeric($f[1]) && !in_array($sqlOperator, array(\'LIKE\', \'NOT LIKE\'))) {
$tvValue = $f[1];
if ($f[1] == (integer)$f[1]) {
$tvValueField = "CAST({$tvValueField} AS SIGNED INTEGER)";
$tvDefaultField = "CAST({$tvDefaultField} AS SIGNED INTEGER)";
} else {
$tvValueField = "CAST({$tvValueField} AS DECIMAL)";
$tvDefaultField = "CAST({$tvDefaultField} AS DECIMAL)";
}
} else {
$tvValue = $modx->quote($f[1]);
}
if ($multiple) {
$filterGroup[] =
"(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) " .
"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)) " .
")";
} else {
$filterGroup =
"(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) " .
"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)) " .
")";
}
} elseif (count($f) == 1) {
$tvValue = $modx->quote($f[0]);
if ($multiple) {
$filterGroup[] = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
} else {
$filterGroup = "EXISTS (SELECT 1 FROM {$tmplVarResourceTbl} tvr JOIN {$tmplVarTbl} tv ON {$tvValueField} {$sqlOperator} {$tvValue} AND tv.id = tvr.tmplvarid WHERE tvr.contentid = modResource.id)";
}
}
}
$conditions[] = $filterGroup;
}
if (!empty($conditions)) {
$firstGroup = true;
foreach ($conditions as $cGroup => $c) {
if (is_array($c)) {
$first = true;
foreach ($c as $cond) {
if ($first && !$firstGroup) {
$criteria->condition($criteria->query[\'where\'][0][1], $cond, xPDOQuery::SQL_OR, null, $cGroup);
} else {
$criteria->condition($criteria->query[\'where\'][0][1], $cond, xPDOQuery::SQL_AND, null, $cGroup);
}
$first = false;
}
} else {
$criteria->condition($criteria->query[\'where\'][0][1], $c, $firstGroup ? xPDOQuery::SQL_AND : xPDOQuery::SQL_OR, null, $cGroup);
}
$firstGroup = false;
}
}
}
/* include/exclude resources, via &resources=`123,-456` prop */
if (!empty($resources)) {
$resourceConditions = array();
$resources = explode(\',\',$resources);
$include = array();
$exclude = array();
foreach ($resources as $resource) {
$resource = (int)$resource;
if ($resource == 0) continue;
if ($resource < 0) {
$exclude[] = abs($resource);
} else {
$include[] = $resource;
}
}
if (!empty($include)) {
$criteria->where(array(\'OR:modResource.id:IN\' => $include), xPDOQuery::SQL_OR);
}
if (!empty($exclude)) {
$criteria->where(array(\'modResource.id:NOT IN\' => $exclude), xPDOQuery::SQL_AND, null, 1);
}
}
if (!empty($where)) {
$criteria->where($where);
}
$total = $modx->getCount(\'modResource\', $criteria);
$modx->setPlaceholder($totalVar, $total);
$fields = array_keys($modx->getFields(\'modResource\'));
if (empty($includeContent)) {
$fields = array_diff($fields, array(\'content\'));
}
$columns = $includeContent ? $modx->getSelectColumns(\'modResource\', \'modResource\') : $modx->getSelectColumns(\'modResource\', \'modResource\', \'\', array(\'content\'), true);
$criteria->select($columns);
if (!empty($sortbyTV)) {
$criteria->leftJoin(\'modTemplateVar\', \'tvDefault\', array(
"tvDefault.name" => $sortbyTV
));
$criteria->leftJoin(\'modTemplateVarResource\', \'tvSort\', array(
"tvSort.contentid = modResource.id",
"tvSort.tmplvarid = tvDefault.id"
));
if (empty($sortbyTVType)) $sortbyTVType = \'string\';
if ($modx->getOption(\'dbtype\') === \'mysql\') {
switch ($sortbyTVType) {
case \'integer\':
$criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS SIGNED INTEGER) AS sortTV");
break;
case \'decimal\':
$criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS DECIMAL) AS sortTV");
break;
case \'datetime\':
$criteria->select("CAST(IFNULL(tvSort.value, tvDefault.default_text) AS DATETIME) AS sortTV");
break;
case \'string\':
default:
$criteria->select("IFNULL(tvSort.value, tvDefault.default_text) AS sortTV");
break;
}
} elseif ($modx->getOption(\'dbtype\') === \'sqlsrv\') {
switch ($sortbyTVType) {
case \'integer\':
$criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS BIGINT) AS sortTV");
break;
case \'decimal\':
$criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS DECIMAL) AS sortTV");
break;
case \'datetime\':
$criteria->select("CAST(ISNULL(tvSort.value, tvDefault.default_text) AS DATETIME) AS sortTV");
break;
case \'string\':
default:
$criteria->select("ISNULL(tvSort.value, tvDefault.default_text) AS sortTV");
break;
}
}
$criteria->sortby("sortTV", $sortdirTV);
}
if (!empty($sortby)) {
if (strpos($sortby, \'{\') === 0) {
$sorts = $modx->fromJSON($sortby);
} else {
$sorts = array($sortby => $sortdir);
}
if (is_array($sorts)) {
while (list($sort, $dir) = each($sorts)) {
if ($sortbyEscaped) $sort = $modx->escape($sort);
if (!empty($sortbyAlias)) $sort = $modx->escape($sortbyAlias) . ".{$sort}";
$criteria->sortby($sort, $dir);
}
}
}
if (!empty($limit)) $criteria->limit($limit, $offset);
if (!empty($debug)) {
$criteria->prepare();
$modx->log(modX::LOG_LEVEL_ERROR, $criteria->toSQL());
}
$collection = $modx->getCollection(\'modResource\', $criteria, $dbCacheFlag);
$idx = !empty($idx) || $idx === \'0\' ? (integer) $idx : 1;
$first = empty($first) && $first !== \'0\' ? 1 : (integer) $first;
$last = empty($last) ? (count($collection) + $idx - 1) : (integer) $last;
/* include parseTpl */
include_once $modx->getOption(\'getresources.core_path\',null,$modx->getOption(\'core_path\').\'components/getresources/\').\'include.parsetpl.php\';
$templateVars = array();
if (!empty($includeTVs) && !empty($includeTVList)) {
$templateVars = $modx->getCollection(\'modTemplateVar\', array(\'name:IN\' => $includeTVList));
}
/** @var modResource $resource */
foreach ($collection as $resourceId => $resource) {
$tvs = array();
if (!empty($includeTVs)) {
if (empty($includeTVList)) {
$templateVars = $resource->getMany(\'TemplateVars\');
}
/** @var modTemplateVar $templateVar */
foreach ($templateVars as $tvId => $templateVar) {
if (!empty($includeTVList) && !in_array($templateVar->get(\'name\'), $includeTVList)) continue;
if ($processTVs && (empty($processTVList) || in_array($templateVar->get(\'name\'), $processTVList))) {
$tvs[$tvPrefix . $templateVar->get(\'name\')] = $templateVar->renderOutput($resource->get(\'id\'));
} else {
$value = $templateVar->getValue($resource->get(\'id\'));
if ($prepareTVs && method_exists($templateVar, \'prepareOutput\') && (empty($prepareTVList) || in_array($templateVar->get(\'name\'), $prepareTVList))) {
$value = $templateVar->prepareOutput($value);
}
$tvs[$tvPrefix . $templateVar->get(\'name\')] = $value;
}
}
}
$odd = ($idx & 1);
$properties = array_merge(
$scriptProperties
,array(
\'idx\' => $idx
,\'first\' => $first
,\'last\' => $last
,\'odd\' => $odd
)
,$includeContent ? $resource->toArray() : $resource->get($fields)
,$tvs
);
$resourceTpl = false;
if ($idx == $first && !empty($tplFirst)) {
$resourceTpl = parseTpl($tplFirst, $properties);
}
if ($idx == $last && empty($resourceTpl) && !empty($tplLast)) {
$resourceTpl = parseTpl($tplLast, $properties);
}
$tplidx = \'tpl_\' . $idx;
if (empty($resourceTpl) && !empty($$tplidx)) {
$resourceTpl = parseTpl($$tplidx, $properties);
}
if ($idx > 1 && empty($resourceTpl)) {
$divisors = getDivisors($idx);
if (!empty($divisors)) {
foreach ($divisors as $divisor) {
$tplnth = \'tpl_n\' . $divisor;
if (!empty($$tplnth)) {
$resourceTpl = parseTpl($$tplnth, $properties);
if (!empty($resourceTpl)) {
break;
}
}
}
}
}
if ($odd && empty($resourceTpl) && !empty($tplOdd)) {
$resourceTpl = parseTpl($tplOdd, $properties);
}
if (!empty($tplCondition) && !empty($conditionalTpls) && empty($resourceTpl)) {
$conTpls = $modx->fromJSON($conditionalTpls);
$subject = $properties[$tplCondition];
$tplOperator = !empty($tplOperator) ? $tplOperator : \'=\';
$tplOperator = strtolower($tplOperator);
$tplCon = \'\';
foreach ($conTpls as $operand => $conditionalTpl) {
switch ($tplOperator) {
case \'!=\':
case \'neq\':
case \'not\':
case \'isnot\':
case \'isnt\':
case \'unequal\':
case \'notequal\':
$tplCon = (($subject != $operand) ? $conditionalTpl : $tplCon);
break;
case \'<\':
case \'lt\':
case \'less\':
case \'lessthan\':
$tplCon = (($subject < $operand) ? $conditionalTpl : $tplCon);
break;
case \'>\':
case \'gt\':
case \'greater\':
case \'greaterthan\':
$tplCon = (($subject > $operand) ? $conditionalTpl : $tplCon);
break;
case \'<=\':
case \'lte\':
case \'lessthanequals\':
case \'lessthanorequalto\':
$tplCon = (($subject <= $operand) ? $conditionalTpl : $tplCon);
break;
case \'>=\':
case \'gte\':
case \'greaterthanequals\':
case \'greaterthanequalto\':
$tplCon = (($subject >= $operand) ? $conditionalTpl : $tplCon);
break;
case \'isempty\':
case \'empty\':
$tplCon = empty($subject) ? $conditionalTpl : $tplCon;
break;
case \'!empty\':
case \'notempty\':
case \'isnotempty\':
$tplCon = !empty($subject) && $subject != \'\' ? $conditionalTpl : $tplCon;
break;
case \'isnull\':
case \'null\':
$tplCon = $subject == null || strtolower($subject) == \'null\' ? $conditionalTpl : $tplCon;
break;
case \'inarray\':
case \'in_array\':
case \'ia\':
$operand = explode(\',\', $operand);
$tplCon = in_array($subject, $operand) ? $conditionalTpl : $tplCon;
break;
case \'between\':
case \'range\':
case \'>=<\':
case \'><\':
$operand = explode(\',\', $operand);
$tplCon = ($subject >= min($operand) && $subject <= max($operand)) ? $conditionalTpl : $tplCon;
break;
case \'==\':
case \'=\':
case \'eq\':
case \'is\':
case \'equal\':
case \'equals\':
case \'equalto\':
default:
$tplCon = (($subject == $operand) ? $conditionalTpl : $tplCon);
break;
}
}
if (!empty($tplCon)) {
$resourceTpl = parseTpl($tplCon, $properties);
}
}
if (!empty($tpl) && empty($resourceTpl)) {
$resourceTpl = parseTpl($tpl, $properties);
}
if ($resourceTpl === false && !empty($debug)) {
$chunk = $modx->newObject(\'modChunk\');
$chunk->setCacheable(false);
$output[]= $chunk->process(array(), \'
\' . print_r($properties, true) .\'
\');
} else {
$output[]= $resourceTpl;
}
$idx++;
}
/* output */
$toSeparatePlaceholders = $modx->getOption(\'toSeparatePlaceholders\', $scriptProperties, false);
if (!empty($toSeparatePlaceholders)) {
$modx->setPlaceholders($output, $toSeparatePlaceholders);
return \'\';
}
$output = implode($outputSeparator, $output);
$tplWrapper = $modx->getOption(\'tplWrapper\', $scriptProperties, false);
$wrapIfEmpty = $modx->getOption(\'wrapIfEmpty\', $scriptProperties, false);
if (!empty($tplWrapper) && ($wrapIfEmpty || !empty($output))) {
$output = parseTpl($tplWrapper, array_merge($scriptProperties, array(\'output\' => $output)));
}
$toPlaceholder = $modx->getOption(\'toPlaceholder\', $scriptProperties, false);
if (!empty($toPlaceholder)) {
$modx->setPlaceholder($toPlaceholder, $output);
return \'\';
}
return $output;',
),
'policies' =>
array (
'web' =>
array (
),
),
'source' =>
array (
),
),
'TaggerGetResourcesWhere' =>
array (
'fields' =>
array (
'id' => 100,
'source' => 0,
'property_preprocess' => false,
'name' => 'TaggerGetResourcesWhere',
'description' => '',
'editor_type' => 0,
'category' => 35,
'cache_type' => 0,
'snippet' => '/**
* TaggerGetResourcesWhere
*
* DESCRIPTION
*
* This snippet generate SQL Query that can be used in WHERE condition in getResources snippet
*
* PROPERTIES:
*
* &tags string optional Comma separated list of Tags for which will be generated a Resource query. By default Tags from GET param will be loaded
* &groups string optional Comma separated list of Tagger Groups. Only from those groups will Tags be allowed
* &where string optional Original getResources where property. If you used where property in your current getResources call, move it here
* &likeComparison int optional If set to 1, tags will compare using LIKE
* &tagField string optional Field that will be used to compare with given tags. Default: alias
* &matchAll int optional If set to 1, resource must have all specified tags. Default: 0
* &field string optional modResource field that will be used to compare with assigned resource ID
*
* USAGE:
*
* [[!getResources? &where=`[[!TaggerGetResourcesWhere? &tags=`Books,Vehicles` &where=`{"isfolder": 0}`]]`]]
*
*/
$tagger = $modx->getService(\'tagger\',\'Tagger\',$modx->getOption(\'tagger.core_path\',null,$modx->getOption(\'core_path\').\'components/tagger/\').\'model/tagger/\',$scriptProperties);
if (!($tagger instanceof Tagger)) return \'\';
$tags = $modx->getOption(\'tags\', $scriptProperties, \'\');
$where = $modx->getOption(\'where\', $scriptProperties, \'\');
$tagField = $modx->getOption(\'tagField\', $scriptProperties, \'alias\');
$likeComparison = (int) $modx->getOption(\'likeComparison\', $scriptProperties, 0);
$matchAll = (int) $modx->getOption(\'matchAll\', $scriptProperties, 0);
$field = $modx->getOption(\'field\', $scriptProperties, \'id\');
$where = $modx->fromJSON($where);
if ($where == false) {
$where = array();
}
$tagsCount = 0;
if ($tags == \'\') {
$gc = $modx->newQuery(\'TaggerGroup\');
$gc->select($modx->getSelectColumns(\'TaggerGroup\', \'\', \'\', array(\'alias\')));
$groups = $modx->getOption(\'groups\', $scriptProperties, \'\');
$groups = $tagger->explodeAndClean($groups);
if (!empty($groups)) {
$gc->where(array(
\'name:IN\' => $groups,
\'OR:alias:IN\' => $groups,
\'OR:id:IN\' => $groups,
));
}
$gc->prepare();
$gc->stmt->execute();
$groups = $gc->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
$conditions = array();
foreach ($groups as $group) {
if (isset($_GET[$group])) {
$groupTags = $tagger->explodeAndClean($_GET[$group]);
if (!empty($groupTags)) {
$like = array(\'AND:alias:IN\' => $groupTags);
if ($likeComparison == 1) {
foreach ($groupTags as $tag) {
$like[] = array(\'OR:alias:LIKE\' => \'%\' . $tag . \'%\');
}
}
$conditions[] = array(
\'OR:Group.alias:=\' => $group,
$like
);
$tagsCount += count($groupTags);
}
}
}
if (count($conditions) == 0) {
return $modx->toJSON($where);
}
$c = $modx->newQuery(\'TaggerTag\');
$c->leftJoin(\'TaggerGroup\', \'Group\');
$c->where($conditions);
} else {
$tags = $tagger->explodeAndClean($tags);
if (empty($tags)) {
return $modx->toJSON($where);
}
$tagsCount = count($tags);
$groups = $modx->getOption(\'groups\', $scriptProperties, \'\');
$groups = $tagger->explodeAndClean($groups);
$c = $modx->newQuery(\'TaggerTag\');
$c->select($modx->getSelectColumns(\'TaggerTag\', \'TaggerTag\', \'\', array(\'id\')));
$compare = array(
$tagField . \':IN\' => $tags
);
if ($likeComparison == 1) {
foreach ($tags as $tag) {
$compare[] = array(\'OR:\' . $tagField . \':LIKE\' => \'%\' . $tag . \'%\');
}
}
$c->where($compare);
if (!empty($groups)) {
$c->leftJoin(\'TaggerGroup\', \'Group\');
$c->where(array(
\'Group.id:IN\' => $groups,
\'OR:Group.name:IN\' => $groups,
\'OR:Group.alias:IN\' => $groups,
));
}
}
$c->prepare();
$c->stmt->execute();
$tagIDs = $c->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
if (count($tagIDs) == 0) {
$tagIDs[] = 0;
}
if ($matchAll == 0) {
$where[] = "EXISTS (SELECT 1 FROM {$modx->getTableName(\'TaggerTagResource\')} r WHERE r.tag IN (" . implode(\',\', $tagIDs) . ") AND r.resource = modResource." . $field . ")";
} else {
$where[] = "EXISTS (SELECT 1 as found FROM {$modx->getTableName(\'TaggerTagResource\')} r WHERE r.tag IN (" . implode(\',\', $tagIDs) . ") AND r.resource = modResource." . $field . " GROUP BY found HAVING count(found) = " . $tagsCount . ")";
}
return $modx->toJSON($where);',
'locked' => false,
'properties' =>
array (
'tags' =>
array (
'name' => 'tags',
'desc' => 'tagger.getresourceswhere.tags_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'Comma separated list of Tags for which will be generated a Resource query. By default Tags from GET param will be loaded',
'area_trans' => '',
),
'groups' =>
array (
'name' => 'groups',
'desc' => 'tagger.getresourceswhere.groups_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'Comma separated list of Tagger Groups. Only from those groups will Tags be allowed',
'area_trans' => '',
),
'where' =>
array (
'name' => 'where',
'desc' => 'tagger.getresourceswhere.where_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'Original getResources where property. If you used where property in your current getResources call, move it here',
'area_trans' => '',
),
'likeComparison' =>
array (
'name' => 'likeComparison',
'desc' => 'tagger.getresourceswhere.likeComparison_desc',
'type' => 'numberfield',
'options' => '',
'value' => '0',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'If set to 1, tags will compare using LIKE',
'area_trans' => '',
),
'tagField' =>
array (
'name' => 'tagField',
'desc' => 'tagger.getresourceswhere.tagField_desc',
'type' => 'textfield',
'options' => '',
'value' => 'alias',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'Field that will be used to compare with given tags. Default: alias',
'area_trans' => '',
),
'matchAll' =>
array (
'name' => 'matchAll',
'desc' => 'tagger.getresourceswhere.matchAll_desc',
'type' => 'numberfield',
'options' => '',
'value' => '0',
'lexicon' => 'tagger:properties',
'area' => '',
'desc_trans' => 'If set to 1, resource must have all specified tags. Default: 0',
'area_trans' => '',
),
),
'moduleguid' => '',
'static' => false,
'static_file' => '',
'content' => '/**
* TaggerGetResourcesWhere
*
* DESCRIPTION
*
* This snippet generate SQL Query that can be used in WHERE condition in getResources snippet
*
* PROPERTIES:
*
* &tags string optional Comma separated list of Tags for which will be generated a Resource query. By default Tags from GET param will be loaded
* &groups string optional Comma separated list of Tagger Groups. Only from those groups will Tags be allowed
* &where string optional Original getResources where property. If you used where property in your current getResources call, move it here
* &likeComparison int optional If set to 1, tags will compare using LIKE
* &tagField string optional Field that will be used to compare with given tags. Default: alias
* &matchAll int optional If set to 1, resource must have all specified tags. Default: 0
* &field string optional modResource field that will be used to compare with assigned resource ID
*
* USAGE:
*
* [[!getResources? &where=`[[!TaggerGetResourcesWhere? &tags=`Books,Vehicles` &where=`{"isfolder": 0}`]]`]]
*
*/
$tagger = $modx->getService(\'tagger\',\'Tagger\',$modx->getOption(\'tagger.core_path\',null,$modx->getOption(\'core_path\').\'components/tagger/\').\'model/tagger/\',$scriptProperties);
if (!($tagger instanceof Tagger)) return \'\';
$tags = $modx->getOption(\'tags\', $scriptProperties, \'\');
$where = $modx->getOption(\'where\', $scriptProperties, \'\');
$tagField = $modx->getOption(\'tagField\', $scriptProperties, \'alias\');
$likeComparison = (int) $modx->getOption(\'likeComparison\', $scriptProperties, 0);
$matchAll = (int) $modx->getOption(\'matchAll\', $scriptProperties, 0);
$field = $modx->getOption(\'field\', $scriptProperties, \'id\');
$where = $modx->fromJSON($where);
if ($where == false) {
$where = array();
}
$tagsCount = 0;
if ($tags == \'\') {
$gc = $modx->newQuery(\'TaggerGroup\');
$gc->select($modx->getSelectColumns(\'TaggerGroup\', \'\', \'\', array(\'alias\')));
$groups = $modx->getOption(\'groups\', $scriptProperties, \'\');
$groups = $tagger->explodeAndClean($groups);
if (!empty($groups)) {
$gc->where(array(
\'name:IN\' => $groups,
\'OR:alias:IN\' => $groups,
\'OR:id:IN\' => $groups,
));
}
$gc->prepare();
$gc->stmt->execute();
$groups = $gc->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
$conditions = array();
foreach ($groups as $group) {
if (isset($_GET[$group])) {
$groupTags = $tagger->explodeAndClean($_GET[$group]);
if (!empty($groupTags)) {
$like = array(\'AND:alias:IN\' => $groupTags);
if ($likeComparison == 1) {
foreach ($groupTags as $tag) {
$like[] = array(\'OR:alias:LIKE\' => \'%\' . $tag . \'%\');
}
}
$conditions[] = array(
\'OR:Group.alias:=\' => $group,
$like
);
$tagsCount += count($groupTags);
}
}
}
if (count($conditions) == 0) {
return $modx->toJSON($where);
}
$c = $modx->newQuery(\'TaggerTag\');
$c->leftJoin(\'TaggerGroup\', \'Group\');
$c->where($conditions);
} else {
$tags = $tagger->explodeAndClean($tags);
if (empty($tags)) {
return $modx->toJSON($where);
}
$tagsCount = count($tags);
$groups = $modx->getOption(\'groups\', $scriptProperties, \'\');
$groups = $tagger->explodeAndClean($groups);
$c = $modx->newQuery(\'TaggerTag\');
$c->select($modx->getSelectColumns(\'TaggerTag\', \'TaggerTag\', \'\', array(\'id\')));
$compare = array(
$tagField . \':IN\' => $tags
);
if ($likeComparison == 1) {
foreach ($tags as $tag) {
$compare[] = array(\'OR:\' . $tagField . \':LIKE\' => \'%\' . $tag . \'%\');
}
}
$c->where($compare);
if (!empty($groups)) {
$c->leftJoin(\'TaggerGroup\', \'Group\');
$c->where(array(
\'Group.id:IN\' => $groups,
\'OR:Group.name:IN\' => $groups,
\'OR:Group.alias:IN\' => $groups,
));
}
}
$c->prepare();
$c->stmt->execute();
$tagIDs = $c->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
if (count($tagIDs) == 0) {
$tagIDs[] = 0;
}
if ($matchAll == 0) {
$where[] = "EXISTS (SELECT 1 FROM {$modx->getTableName(\'TaggerTagResource\')} r WHERE r.tag IN (" . implode(\',\', $tagIDs) . ") AND r.resource = modResource." . $field . ")";
} else {
$where[] = "EXISTS (SELECT 1 as found FROM {$modx->getTableName(\'TaggerTagResource\')} r WHERE r.tag IN (" . implode(\',\', $tagIDs) . ") AND r.resource = modResource." . $field . " GROUP BY found HAVING count(found) = " . $tagsCount . ")";
}
return $modx->toJSON($where);',
),
'policies' =>
array (
'web' =>
array (
),
),
'source' =>
array (
),
),
'getPage' =>
array (
'fields' =>
array (
'id' => 109,
'source' => 0,
'property_preprocess' => false,
'name' => 'getPage',
'description' => '1.2.4-pl A generic wrapper snippet for returning paged results and navigation from snippets that return limitable collections.',
'editor_type' => 0,
'category' => 0,
'cache_type' => 0,
'snippet' => '/**
* @package getpage
*/
$output = \'\';
$properties =& $scriptProperties;
$properties[\'page\'] = (isset($_GET[$properties[\'pageVarKey\']]) && ($page = intval($_GET[$properties[\'pageVarKey\']]))) ? $page : null;
if ($properties[\'page\'] === null) {
$properties[\'page\'] = (isset($_REQUEST[$properties[\'pageVarKey\']]) && ($page = intval($_REQUEST[$properties[\'pageVarKey\']]))) ? $page : 1;
}
$properties[\'limit\'] = (isset($_GET[\'limit\'])) ? intval($_GET[\'limit\']) : null;
if ($properties[\'limit\'] === null) {
$properties[\'limit\'] = (isset($_REQUEST[\'limit\'])) ? intval($_REQUEST[\'limit\']) : intval($limit);
}
$properties[\'offset\'] = (!empty($properties[\'limit\']) && !empty($properties[\'page\'])) ? ($properties[\'limit\'] * ($properties[\'page\'] - 1)) : 0;
$properties[\'totalVar\'] = empty($totalVar) ? "total" : $totalVar;
$properties[$properties[\'totalVar\']] = !empty($properties[$properties[\'totalVar\']]) && $total = intval($properties[$properties[\'totalVar\']]) ? $total : 0;
$properties[\'pageOneLimit\'] = (!empty($pageOneLimit) && $pageOneLimit = intval($pageOneLimit)) ? $pageOneLimit : $properties[\'limit\'];
$properties[\'actualLimit\'] = $properties[\'limit\'];
$properties[\'pageLimit\'] = isset($pageLimit) && is_numeric($pageLimit) ? intval($pageLimit) : 5;
$properties[\'element\'] = empty($element) ? \'\' : $element;
$properties[\'elementClass\'] = empty($elementClass) ? \'modChunk\' : $elementClass;
$properties[\'pageNavVar\'] = empty($pageNavVar) ? \'page.nav\' : $pageNavVar;
$properties[\'pageNavTpl\'] = !isset($pageNavTpl) ? "
" : $pageNextTpl;
$properties[\'toPlaceholder\'] = !empty($toPlaceholder) ? $toPlaceholder : \'\';
$properties[\'cache\'] = isset($cache) ? (boolean) $cache : (boolean) $modx->getOption(\'cache_resource\', null, false);
if (empty($cache_key)) $properties[xPDO::OPT_CACHE_KEY] = $modx->getOption(\'cache_resource_key\', null, \'resource\');
if (empty($cache_handler)) $properties[xPDO::OPT_CACHE_HANDLER] = $modx->getOption(\'cache_resource_handler\', null, \'xPDOFileCache\');
if (empty($cache_expires)) $properties[xPDO::OPT_CACHE_EXPIRES] = (integer) $modx->getOption(\'cache_resource_expires\', null, 0);
if ($properties[\'page\'] == 1 && $properties[\'pageOneLimit\'] !== $properties[\'actualLimit\']) {
$properties[\'limit\'] = $properties[\'pageOneLimit\'];
}
if ($properties[\'cache\']) {
$properties[\'cachePageKey\'] = $modx->resource->getCacheKey() . \'/\' . $properties[\'page\'] . \'/\' . md5(http_build_query($modx->request->getParameters()) . http_build_query($scriptProperties));
$properties[\'cacheOptions\'] = array(
xPDO::OPT_CACHE_KEY => $properties[xPDO::OPT_CACHE_KEY],
xPDO::OPT_CACHE_HANDLER => $properties[xPDO::OPT_CACHE_HANDLER],
xPDO::OPT_CACHE_EXPIRES => $properties[xPDO::OPT_CACHE_EXPIRES],
);
}
$cached = false;
if ($properties[\'cache\']) {
if ($modx->getCacheManager()) {
$cached = $modx->cacheManager->get($properties[\'cachePageKey\'], $properties[\'cacheOptions\']);
}
}
if (empty($cached) || !isset($cached[\'properties\']) || !isset($cached[\'output\'])) {
$elementObj = $modx->getObject($properties[\'elementClass\'], array(\'name\' => $properties[\'element\']));
if ($elementObj) {
$elementObj->setCacheable(false);
if (!empty($properties[\'toPlaceholder\'])) {
$elementObj->process($properties);
$output = $modx->getPlaceholder($properties[\'toPlaceholder\']);
} else {
$output = $elementObj->process($properties);
}
}
include_once $modx->getOption(\'getpage.core_path\',$properties,$modx->getOption(\'core_path\', $properties, MODX_CORE_PATH) . \'components/getpage/\').\'include.getpage.php\';
$qs = $modx->request->getParameters();
$properties[\'qs\'] =& $qs;
$totalSet = $modx->getPlaceholder($properties[\'totalVar\']);
$properties[$properties[\'totalVar\']] = (($totalSet = intval($totalSet)) ? $totalSet : $properties[$properties[\'totalVar\']]);
if (!empty($properties[$properties[\'totalVar\']]) && !empty($properties[\'actualLimit\'])) {
if ($properties[\'pageOneLimit\'] !== $properties[\'actualLimit\']) {
$adjustedTotal = $properties[$properties[\'totalVar\']] - $properties[\'pageOneLimit\'];
$properties[\'pageCount\'] = $adjustedTotal > 0 ? ceil($adjustedTotal / $properties[\'actualLimit\']) + 1 : 1;
} else {
$properties[\'pageCount\'] = ceil($properties[$properties[\'totalVar\']] / $properties[\'actualLimit\']);
}
} else {
$properties[\'pageCount\'] = 1;
}
if (empty($properties[$properties[\'totalVar\']]) || empty($properties[\'actualLimit\']) || $properties[$properties[\'totalVar\']] <= $properties[\'actualLimit\'] || ($properties[\'page\'] == 1 && $properties[$properties[\'totalVar\']] <= $properties[\'pageOneLimit\'])) {
$properties[\'page\'] = 1;
} else {
$pageNav = getpage_buildControls($modx, $properties);
$properties[$properties[\'pageNavVar\']] = $modx->newObject(\'modChunk\')->process(array_merge($properties, $pageNav), $properties[\'pageNavOuterTpl\']);
if ($properties[\'page\'] > 1) {
$qs[$properties[\'pageVarKey\']] = $properties[\'page\'];
}
}
$properties[\'firstItem\'] = $properties[\'offset\'] + 1;
$properties[\'lastItem\'] = ($properties[\'offset\'] + $properties[\'limit\']) < $totalSet ? ($properties[\'offset\'] + $properties[\'limit\']) : $totalSet;
$properties[\'pageUrl\'] = $modx->makeUrl($modx->resource->get(\'id\'), \'\', $qs);
if ($properties[\'cache\'] && $modx->getCacheManager()) {
$cached = array(\'properties\' => $properties, \'output\' => $output);
$modx->cacheManager->set($properties[\'cachePageKey\'], $cached, $properties[xPDO::OPT_CACHE_EXPIRES], $properties[\'cacheOptions\']);
}
} else {
$properties = $cached[\'properties\'];
$output = $cached[\'output\'];
}
$modx->setPlaceholders($properties, $properties[\'namespace\']);
if (!empty($properties[\'toPlaceholder\'])) {
$modx->setPlaceholder($properties[\'toPlaceholder\'], $output);
$output = \'\';
}
return $output;',
'locked' => false,
'properties' =>
array (
'cache' =>
array (
'name' => 'cache',
'desc' => 'If true, unique page requests will be cached according to addition cache properties.',
'type' => 'combo-boolean',
'options' =>
array (
),
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'If true, unique page requests will be cached according to addition cache properties.',
'area_trans' => '',
),
'cache_expires' =>
array (
'name' => 'cache_expires',
'desc' => 'The number of seconds before the cached pages expire and must be regenerated; leave empty to use the cache provider option for cache_expires.',
'type' => 'textfield',
'options' =>
array (
),
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The number of seconds before the cached pages expire and must be regenerated; leave empty to use the cache provider option for cache_expires.',
'area_trans' => '',
),
'cache_handler' =>
array (
'name' => 'cache_handler',
'desc' => 'The cache provider implementation to use; leave empty unless you are caching to a custom cache_key.',
'type' => 'textfield',
'options' =>
array (
),
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The cache provider implementation to use; leave empty unless you are caching to a custom cache_key.',
'area_trans' => '',
),
'cache_key' =>
array (
'name' => 'cache_key',
'desc' => 'The key of the cache provider to use; leave empty to use the cache_resource_key cache partition (default is "resource").',
'type' => 'textfield',
'options' =>
array (
),
'value' => false,
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The key of the cache provider to use; leave empty to use the cache_resource_key cache partition (default is "resource").',
'area_trans' => '',
),
'elementClass' =>
array (
'name' => 'elementClass',
'desc' => 'The class of element that will be called by the getPage snippet instance.',
'type' => 'textfield',
'options' =>
array (
),
'value' => 'modSnippet',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The class of element that will be called by the getPage snippet instance.',
'area_trans' => '',
),
'limit' =>
array (
'name' => 'limit',
'desc' => 'The result limit per page; can be overridden in the $_REQUEST.',
'type' => 'textfield',
'options' =>
array (
),
'value' => '10',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The result limit per page; can be overridden in the $_REQUEST.',
'area_trans' => '',
),
'namespace' =>
array (
'name' => 'namespace',
'desc' => 'An execution namespace that serves as a prefix for placeholders set by a specific instance of the getPage snippet.',
'type' => 'textfield',
'options' =>
array (
),
'value' => '',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'An execution namespace that serves as a prefix for placeholders set by a specific instance of the getPage snippet.',
'area_trans' => '',
),
'offset' =>
array (
'name' => 'offset',
'desc' => 'The offset, or record position to start at within the collection for rendering results for the current page; should be calculated based on page variable set in pageVarKey.',
'type' => 'textfield',
'options' =>
array (
),
'value' => '0',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The offset, or record position to start at within the collection for rendering results for the current page; should be calculated based on page variable set in pageVarKey.',
'area_trans' => '',
),
'page' =>
array (
'name' => 'page',
'desc' => 'The page to display; this is determined based on the value indicated by the page variable set in pageVarKey, typically in the $_REQUEST.',
'type' => 'textfield',
'options' =>
array (
),
'value' => '0',
'lexicon' => NULL,
'area' => '',
'desc_trans' => 'The page to display; this is determined based on the value indicated by the page variable set in pageVarKey, typically in the $_REQUEST.',
'area_trans' => '',
),
'pageActiveTpl' =>
array (
'name' => 'pageActiveTpl',
'desc' => 'Content representing the current page navigation control.',
'type' => 'textfield',
'options' =>
array (
),
'value' => '
" : $pageNextTpl;
$properties[\'toPlaceholder\'] = !empty($toPlaceholder) ? $toPlaceholder : \'\';
$properties[\'cache\'] = isset($cache) ? (boolean) $cache : (boolean) $modx->getOption(\'cache_resource\', null, false);
if (empty($cache_key)) $properties[xPDO::OPT_CACHE_KEY] = $modx->getOption(\'cache_resource_key\', null, \'resource\');
if (empty($cache_handler)) $properties[xPDO::OPT_CACHE_HANDLER] = $modx->getOption(\'cache_resource_handler\', null, \'xPDOFileCache\');
if (empty($cache_expires)) $properties[xPDO::OPT_CACHE_EXPIRES] = (integer) $modx->getOption(\'cache_resource_expires\', null, 0);
if ($properties[\'page\'] == 1 && $properties[\'pageOneLimit\'] !== $properties[\'actualLimit\']) {
$properties[\'limit\'] = $properties[\'pageOneLimit\'];
}
if ($properties[\'cache\']) {
$properties[\'cachePageKey\'] = $modx->resource->getCacheKey() . \'/\' . $properties[\'page\'] . \'/\' . md5(http_build_query($modx->request->getParameters()) . http_build_query($scriptProperties));
$properties[\'cacheOptions\'] = array(
xPDO::OPT_CACHE_KEY => $properties[xPDO::OPT_CACHE_KEY],
xPDO::OPT_CACHE_HANDLER => $properties[xPDO::OPT_CACHE_HANDLER],
xPDO::OPT_CACHE_EXPIRES => $properties[xPDO::OPT_CACHE_EXPIRES],
);
}
$cached = false;
if ($properties[\'cache\']) {
if ($modx->getCacheManager()) {
$cached = $modx->cacheManager->get($properties[\'cachePageKey\'], $properties[\'cacheOptions\']);
}
}
if (empty($cached) || !isset($cached[\'properties\']) || !isset($cached[\'output\'])) {
$elementObj = $modx->getObject($properties[\'elementClass\'], array(\'name\' => $properties[\'element\']));
if ($elementObj) {
$elementObj->setCacheable(false);
if (!empty($properties[\'toPlaceholder\'])) {
$elementObj->process($properties);
$output = $modx->getPlaceholder($properties[\'toPlaceholder\']);
} else {
$output = $elementObj->process($properties);
}
}
include_once $modx->getOption(\'getpage.core_path\',$properties,$modx->getOption(\'core_path\', $properties, MODX_CORE_PATH) . \'components/getpage/\').\'include.getpage.php\';
$qs = $modx->request->getParameters();
$properties[\'qs\'] =& $qs;
$totalSet = $modx->getPlaceholder($properties[\'totalVar\']);
$properties[$properties[\'totalVar\']] = (($totalSet = intval($totalSet)) ? $totalSet : $properties[$properties[\'totalVar\']]);
if (!empty($properties[$properties[\'totalVar\']]) && !empty($properties[\'actualLimit\'])) {
if ($properties[\'pageOneLimit\'] !== $properties[\'actualLimit\']) {
$adjustedTotal = $properties[$properties[\'totalVar\']] - $properties[\'pageOneLimit\'];
$properties[\'pageCount\'] = $adjustedTotal > 0 ? ceil($adjustedTotal / $properties[\'actualLimit\']) + 1 : 1;
} else {
$properties[\'pageCount\'] = ceil($properties[$properties[\'totalVar\']] / $properties[\'actualLimit\']);
}
} else {
$properties[\'pageCount\'] = 1;
}
if (empty($properties[$properties[\'totalVar\']]) || empty($properties[\'actualLimit\']) || $properties[$properties[\'totalVar\']] <= $properties[\'actualLimit\'] || ($properties[\'page\'] == 1 && $properties[$properties[\'totalVar\']] <= $properties[\'pageOneLimit\'])) {
$properties[\'page\'] = 1;
} else {
$pageNav = getpage_buildControls($modx, $properties);
$properties[$properties[\'pageNavVar\']] = $modx->newObject(\'modChunk\')->process(array_merge($properties, $pageNav), $properties[\'pageNavOuterTpl\']);
if ($properties[\'page\'] > 1) {
$qs[$properties[\'pageVarKey\']] = $properties[\'page\'];
}
}
$properties[\'firstItem\'] = $properties[\'offset\'] + 1;
$properties[\'lastItem\'] = ($properties[\'offset\'] + $properties[\'limit\']) < $totalSet ? ($properties[\'offset\'] + $properties[\'limit\']) : $totalSet;
$properties[\'pageUrl\'] = $modx->makeUrl($modx->resource->get(\'id\'), \'\', $qs);
if ($properties[\'cache\'] && $modx->getCacheManager()) {
$cached = array(\'properties\' => $properties, \'output\' => $output);
$modx->cacheManager->set($properties[\'cachePageKey\'], $cached, $properties[xPDO::OPT_CACHE_EXPIRES], $properties[\'cacheOptions\']);
}
} else {
$properties = $cached[\'properties\'];
$output = $cached[\'output\'];
}
$modx->setPlaceholders($properties, $properties[\'namespace\']);
if (!empty($properties[\'toPlaceholder\'])) {
$modx->setPlaceholder($properties[\'toPlaceholder\'], $output);
$output = \'\';
}
return $output;',
),
'policies' =>
array (
'web' =>
array (
),
),
'source' =>
array (
),
),
'phpthumbof' =>
array (
'fields' =>
array (
'id' => 97,
'source' => 0,
'property_preprocess' => false,
'name' => 'phpthumbof',
'description' => 'Identical to pthumb. Retained for backwards compatibility.
Documentation: https://github.com/oo12/phpThumbOf',
'editor_type' => 0,
'category' => 33,
'cache_type' => 0,
'snippet' => '/**
* pThumb
* Copyright 2013-2014 Jason Grant
*
* Please see the GitHub page for documentation or to report bugs:
* https://github.com/oo12/phpThumbOf
*
* Forked from phpThumbOf 1.4.0
* Copyright 2009-2012 by Shaun McCormick
*
* pThumb is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* pThumb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* phpThumbOf; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/**
*
* @var modX $modx
* @var array $scriptProperties
* @var string $input
* @var string|array $options
*
*/
if (empty($input)) { // Exit quietly if no file name given
return;
}
$scriptProperties[\'debug\'] = isset($debug) ? $debug : false;
static $pt_settings = array();
if (empty($pt_settings)) {
if (!$modx->loadClass(\'phpThumbOf\', MODX_CORE_PATH . \'components/phpthumbof/model/\', true, true)) {
$modx->log(modX::LOG_LEVEL_ERROR, \'[pThumb] Could not load phpThumbOf class.\');
return $input;
}
}
$pThumb = new phpThumbOf($modx, $pt_settings, $scriptProperties);
$result = $pThumb->createThumbnail($input, $options);
if (!empty($toPlaceholder) || $result[\'outputDims\']) {
if ($result[\'width\'] === \'\' && $result[\'file\'] && $dims = getimagesize($result[\'file\']) ) {
$result[\'width\'] = $dims[0];
$result[\'height\'] = $dims[1];
}
if (!empty($toPlaceholder)) {
$modx->setPlaceholders(array(
$toPlaceholder => $result[\'src\'],
"$toPlaceholder.width" => $result[\'width\'],
"$toPlaceholder.height" => $result[\'height\']
));
$output = \'\';
}
if ($result[\'outputDims\']) {
$output = "src=\\"{$result[\'src\']}\\"" . ($result[\'width\'] ? " width=\\"{$result[\'width\']}\\" height=\\"{$result[\'height\']}\\"" : \'\');
}
}
else {
$output = $result[\'src\'];
}
if ($debug && $result[\'success\']) { // if debugging is on and createThumbnail was successful, log the debug info
$pThumb->debugmsg(isset($pThumb->phpThumb->debugmessages) ? \':: Processed ::\' : ":: Loaded from cache: {$result[\'src\']}", true);
}
return $output;',
'locked' => false,
'properties' =>
array (
'debug' =>
array (
'name' => 'debug',
'desc' => 'prop_pthumb.debug_desc',
'type' => 'combo-boolean',
'options' =>
array (
),
'value' => false,
'lexicon' => 'phpthumbof:default',
'area' => '',
'desc_trans' => 'Write debug messages to the MODX error log.',
'area_trans' => '',
),
),
'moduleguid' => '',
'static' => false,
'static_file' => '',
'content' => '/**
* pThumb
* Copyright 2013-2014 Jason Grant
*
* Please see the GitHub page for documentation or to report bugs:
* https://github.com/oo12/phpThumbOf
*
* Forked from phpThumbOf 1.4.0
* Copyright 2009-2012 by Shaun McCormick
*
* pThumb is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* pThumb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* phpThumbOf; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/**
*
* @var modX $modx
* @var array $scriptProperties
* @var string $input
* @var string|array $options
*
*/
if (empty($input)) { // Exit quietly if no file name given
return;
}
$scriptProperties[\'debug\'] = isset($debug) ? $debug : false;
static $pt_settings = array();
if (empty($pt_settings)) {
if (!$modx->loadClass(\'phpThumbOf\', MODX_CORE_PATH . \'components/phpthumbof/model/\', true, true)) {
$modx->log(modX::LOG_LEVEL_ERROR, \'[pThumb] Could not load phpThumbOf class.\');
return $input;
}
}
$pThumb = new phpThumbOf($modx, $pt_settings, $scriptProperties);
$result = $pThumb->createThumbnail($input, $options);
if (!empty($toPlaceholder) || $result[\'outputDims\']) {
if ($result[\'width\'] === \'\' && $result[\'file\'] && $dims = getimagesize($result[\'file\']) ) {
$result[\'width\'] = $dims[0];
$result[\'height\'] = $dims[1];
}
if (!empty($toPlaceholder)) {
$modx->setPlaceholders(array(
$toPlaceholder => $result[\'src\'],
"$toPlaceholder.width" => $result[\'width\'],
"$toPlaceholder.height" => $result[\'height\']
));
$output = \'\';
}
if ($result[\'outputDims\']) {
$output = "src=\\"{$result[\'src\']}\\"" . ($result[\'width\'] ? " width=\\"{$result[\'width\']}\\" height=\\"{$result[\'height\']}\\"" : \'\');
}
}
else {
$output = $result[\'src\'];
}
if ($debug && $result[\'success\']) { // if debugging is on and createThumbnail was successful, log the debug info
$pThumb->debugmsg(isset($pThumb->phpThumb->debugmessages) ? \':: Processed ::\' : ":: Loaded from cache: {$result[\'src\']}", true);
}
return $output;',
),
'policies' =>
array (
'web' =>
array (
),
),
'source' =>
array (
),
),
'FormIt' =>
array (
'fields' =>
array (
'id' => 16,
'source' => 0,
'property_preprocess' => false,
'name' => 'FormIt',
'description' => 'A dynamic form processing snippet.',
'editor_type' => 0,
'category' => 8,
'cache_type' => 0,
'snippet' => '/**
* FormIt
*
* Copyright 2009-2012 by Shaun McCormick
*
* FormIt is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* FormIt is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* FormIt; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*
* @package formit
*/
/**
* FormIt
*
* A dynamic form processing Snippet for MODx Revolution.
*
* @var modX $modx
* @var array $scriptProperties
*
* @package formit
*/
$modelPath = $modx->getOption(
\'formit.core_path\',
null,
$modx->getOption(\'core_path\', null, MODX_CORE_PATH) . \'components/formit/\'
) . \'model/formit/\';
$modx->loadClass(\'FormIt\', $modelPath, true, true);
$fi = new FormIt($modx, $scriptProperties);
$fi->initialize($modx->context->get(\'key\'));
$fi->loadRequest();
$fields = $fi->request->prepare();
return $fi->request->handle($fields);',
'locked' => false,
'properties' =>
array (
'hooks' =>
array (
'name' => 'hooks',
'desc' => 'prop_formit.hooks_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'What scripts to fire, if any, after the form passes validation. This can be a comma-separated list of hooks, and if the first fails, the proceeding ones will not fire. A hook can also be a Snippet name that will execute that Snippet.',
'area_trans' => '',
),
'preHooks' =>
array (
'name' => 'preHooks',
'desc' => 'prop_formit.prehooks_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'What scripts to fire, if any, once the form loads. You can pre-set form fields via $scriptProperties[`hook`]->fields[`fieldname`]. This can be a comma-separated list of hooks, and if the first fails, the proceeding ones will not fire. A hook can also be a Snippet name that will execute that Snippet.',
'area_trans' => '',
),
'submitVar' =>
array (
'name' => 'submitVar',
'desc' => 'prop_formit.submitvar_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'If set, will not begin form processing if this POST variable is not passed.',
'area_trans' => '',
),
'validate' =>
array (
'name' => 'validate',
'desc' => 'prop_formit.validate_desc',
'type' => 'textfield',
'options' => '',
'value' => '',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'A comma-separated list of fields to validate, with each field name as name:validator (eg: username:required,email:required). Validators can also be chained, like email:email:required. This property can be specified on multiple lines.',
'area_trans' => '',
),
'errTpl' =>
array (
'name' => 'errTpl',
'desc' => 'prop_formit.errtpl_desc',
'type' => 'textfield',
'options' => '',
'value' => '[[+error]]',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'The wrapper template for error messages.',
'area_trans' => '',
),
'validationErrorMessage' =>
array (
'name' => 'validationErrorMessage',
'desc' => 'prop_formit.validationerrormessage_desc',
'type' => 'textfield',
'options' => '',
'value' => '
A form validation error occurred. Please check the values you have entered.
',
'lexicon' => 'formit:properties',
'area' => '',
'desc_trans' => 'A general error message to set to a placeholder if validation fails. Can contain [[+errors]] if you want to display a list of all errors at the top.',
'area_trans' => '',
),
'validationErrorBulkTpl' =>
array (
'name' => 'validationErrorBulkTpl',
'desc' => 'prop_formit.validationerrorbulktpl_desc',
'type' => 'textfield',
'options' => '',
'value' => '