Skip to content

Instantly share code, notes, and snippets.

Created August 14, 2017 14:11
Show Gist options
  • Save anonymous/7e307e73e6842fd6d94f28ba62ab2a7d to your computer and use it in GitHub Desktop.
Save anonymous/7e307e73e6842fd6d94f28ba62ab2a7d to your computer and use it in GitHub Desktop.
Typo3 Abstract Item Provider workaround
<?php
abstract class AbstractItemProvider
{
/**
* Replace markers in a where clause from TCA foreign_table_where
*
* ###REC_FIELD_[field name]###
* ###THIS_UID### - is current element uid (zero if new).
* ###CURRENT_PID### - is the current page id (pid of the record).
* ###SITEROOT###
* ###PAGE_TSCONFIG_ID### - a value you can set from Page TSconfig dynamically.
* ###PAGE_TSCONFIG_IDLIST### - a value you can set from Page TSconfig dynamically.
* ###PAGE_TSCONFIG_STR### - a value you can set from Page TSconfig dynamically.
*
* @param array $result Result array
* @param string $foreignTableName Name of foreign table
* @param string $localFieldName Current handle field name
* @return array Query parts with keys WHERE, ORDERBY, GROUPBY, LIMIT
*/
protected function processForeignTableClause(array $result, $foreignTableName, $localFieldName)
{
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($foreignTableName);
$localTable = $result['tableName'];
$effectivePid = $result['effectivePid'];
$foreignTableClause = '';
if (!empty($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
&& is_string($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
) {
$foreignTableClause = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'];
// Replace possible markers in query
if (strstr($foreignTableClause, '###REC_FIELD_')) {
// " AND table.field='###REC_FIELD_field1###' AND ..." -> array(" AND table.field='", "field1###' AND ...")
$whereClauseParts = explode('###REC_FIELD_', $foreignTableClause);
foreach ($whereClauseParts as $key => $value) {
if ($key !== 0) {
// "field1###' AND ..." -> array("field1", "' AND ...")
$whereClauseSubParts = explode('###', $value, 2);
// @todo: Throw exception if there is no value? What happens for NEW records?
$databaseRowKey = empty($result['flexParentDatabaseRow']) ? 'databaseRow' : 'flexParentDatabaseRow';
$rowFieldValue = isset($result[$databaseRowKey][$whereClauseSubParts[0]]) ? $result[$databaseRowKey][$whereClauseSubParts[0]] : '';
if (is_array($rowFieldValue)) {
// If a select or group field is used here, it may have been processed already and
// is now an array. Use first selected value in this case.
$rowFieldValue = $rowFieldValue[0];
}
if (substr($whereClauseParts[0], -1) === '\'' && $whereClauseSubParts[1][0] === '\'') {
$whereClauseParts[0] = substr($whereClauseParts[0], 0, -1);
$whereClauseSubParts[1] = substr($whereClauseSubParts[1], 1);
}
$whereClauseParts[$key] = $connection->quote($rowFieldValue) . $whereClauseSubParts[1];
}
}
$foreignTableClause = implode('', $whereClauseParts);
}
if (strpos($foreignTableClause, '###CURRENT_PID###') !== false) {
// Use pid from parent page clause if in flex form context
if (!empty($result['flexParentDatabaseRow']['pid'])) {
$effectivePid = $result['flexParentDatabaseRow']['pid'];
// Use pid from database row if in inline context
} elseif (!$effectivePid && !empty($result['databaseRow']['pid'])) {
$effectivePid = $result['databaseRow']['pid'];
}
}
$siteRootUid = 0;
foreach ($result['rootline'] as $rootlinePage) {
if (!empty($rootlinePage['is_siteroot'])) {
$siteRootUid = (int)$rootlinePage['uid'];
break;
}
}
$pageTsConfigId = 0;
if ($result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_ID']) {
// @deprecated since TYPO3 v8, will be removed in TYPO3 v9 - see also the flexHack part in TcaFlexProcess
$pageTsConfigId = (int)$result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_ID'];
}
if ($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID']) {
$pageTsConfigId = (int)$result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'];
}
$pageTsConfigIdList = 0;
if ($result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_IDLIST']) {
// @deprecated since TYPO3 v8, will be removed in TYPO3 v9 - see also the flexHack part in TcaFlexProcess
$pageTsConfigIdList = $result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_IDLIST'];
}
if ($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST']) {
$pageTsConfigIdList = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'];
}
$pageTsConfigIdListArray = GeneralUtility::trimExplode(',', $pageTsConfigIdList, true);
$pageTsConfigIdList = [];
foreach ($pageTsConfigIdListArray as $pageTsConfigIdListElement) {
if (MathUtility::canBeInterpretedAsInteger($pageTsConfigIdListElement)) {
$pageTsConfigIdList[] = (int)$pageTsConfigIdListElement;
}
}
$pageTsConfigIdList = implode(',', $pageTsConfigIdList);
$pageTsConfigString = '';
if ($result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_STR']) {
// @deprecated since TYPO3 v8, will be removed in TYPO3 v9 - see also the flexHack part in TcaFlexProcess
$pageTsConfigString = $connection->quote($result['pageTsConfig']['flexHack.']['PAGE_TSCONFIG_STR']);
}
if ($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR']) {
$pageTsConfigString = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'];
$pageTsConfigString = $connection->quote($pageTsConfigString);
}
$foreignTableClause = str_replace(
[
'###CURRENT_PID###',
'###THIS_UID###',
'###SITEROOT###',
'###PAGE_TSCONFIG_ID###',
'###PAGE_TSCONFIG_IDLIST###',
'\'###PAGE_TSCONFIG_STR###\'',
'###PAGE_TSCONFIG_STR###'
],
[
(int)$effectivePid,
(int)$result['databaseRow']['uid'],
$siteRootUid,
$pageTsConfigId,
$pageTsConfigIdList,
$pageTsConfigString,
$pageTsConfigString
],
$foreignTableClause
);
}
if (!empty($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where']) &&
!empty($result['isInlineChild']) &&
!empty($result['inlineParentConfig']['foreign_table']) &&
!empty($result['inlineParentConfig']['foreign_field']) &&
!empty($result['inlineParentUid'])
) {
$parentUid = $result['inlineParentUid'];
$foreignTable = $result['inlineParentConfig']['foreign_table'];
$foreignField = $result['inlineParentConfig']['foreign_field'];
$foreignTableClause .= ' AND (' . $foreignTable . '.'.$foreignField . '=' .$parentUid.')';
}
// Split the clause into an array with keys WHERE, GROUPBY, ORDERBY, LIMIT
// Prepend a space to make sure "[[:space:]]+" will find a space there for the first element.
$foreignTableClause = ' ' . $foreignTableClause;
$foreignTableClauseArray = [
'WHERE' => '',
'GROUPBY' => '',
'ORDERBY' => '',
'LIMIT' => '',
];
// Find LIMIT
$reg = [];
if (preg_match('/^(.*)[[:space:]]+LIMIT[[:space:]]+([[:alnum:][:space:],._]+)$/i', $foreignTableClause, $reg)) {
$foreignTableClauseArray['LIMIT'] = GeneralUtility::intExplode(',', trim($reg[2]), true);
$foreignTableClause = $reg[1];
}
// Find ORDER BY
$reg = [];
if (preg_match('/^(.*)[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._]+)$/i', $foreignTableClause, $reg)) {
$foreignTableClauseArray['ORDERBY'] = QueryHelper::parseOrderBy(trim($reg[2]));
$foreignTableClause = $reg[1];
}
// Find GROUP BY
$reg = [];
if (preg_match('/^(.*)[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._]+)$/i', $foreignTableClause, $reg)) {
$foreignTableClauseArray['GROUPBY'] = QueryHelper::parseGroupBy(trim($reg[2]));
$foreignTableClause = $reg[1];
}
// Rest is assumed to be "WHERE" clause
$foreignTableClauseArray['WHERE'] = QueryHelper::stripLogicalOperatorPrefix($foreignTableClause);
return $foreignTableClauseArray;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment