/**
  * Find relations pointing to non-existing records
  * Fix methods: API in \TYPO3\CMS\Core\Database\ReferenceIndex that allows to
  * change the value of a reference (or remove it) [Only for managed relations!]
  *
  * @return array
  * @todo Define visibility
  */
 public function main()
 {
     global $TYPO3_DB;
     // Initialize result array:
     $listExplain = ' Shows the missing record as header and underneath a list of record fields in which the references are found. ' . $this->label_infoString;
     $resultArray = array('message' => $this->cli_help['name'] . LF . LF . $this->cli_help['description'], 'headers' => array('offlineVersionRecords_m' => array('Offline version records (managed)', 'These records are offline versions having a pid=-1 and references should never occur directly to their uids.' . $listExplain, 3), 'deletedRecords_m' => array('Deleted-flagged records (managed)', 'These records are deleted with a flag but references are still pointing at them. Keeping the references is useful if you undelete the referenced records later, otherwise the references are lost completely when the deleted records are flushed at some point. Notice that if those records listed are themselves deleted (marked with "DELETED") it is not a problem.' . $listExplain, 2), 'nonExistingRecords_m' => array('Non-existing records to which there are references (managed)', 'These references can safely be removed since there is no record found in the database at all.' . $listExplain, 3), 'offlineVersionRecords_s' => array('Offline version records (softref)', 'See above.' . $listExplain, 2), 'deletedRecords_s' => array('Deleted-flagged records (softref)', 'See above.' . $listExplain, 2), 'nonExistingRecords_s' => array('Non-existing records to which there are references (softref)', 'See above.' . $listExplain, 2)), 'offlineVersionRecords_m' => array(), 'deletedRecords_m' => array(), 'nonExistingRecords_m' => array(), 'offlineVersionRecords_s' => array(), 'deletedRecords_s' => array(), 'nonExistingRecords_s' => array());
     // Select DB relations from reference table
     $recs = $TYPO3_DB->exec_SELECTgetRows('*', 'sys_refindex', 'ref_table<>' . $TYPO3_DB->fullQuoteStr('_FILE', 'sys_refindex') . ' AND ref_uid>0' . $filterClause, '', 'sorting DESC');
     // Traverse the records
     $tempExists = array();
     if (is_array($recs)) {
         foreach ($recs as $rec) {
             $suffix = $rec['softref_key'] != '' ? '_s' : '_m';
             $idx = $rec['ref_table'] . ':' . $rec['ref_uid'];
             // Get referenced record:
             if (!isset($tempExists[$idx])) {
                 $tempExists[$idx] = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordRaw($rec['ref_table'], 'uid=' . (int) $rec['ref_uid'], 'uid,pid' . ($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete'] : ''));
             }
             // Compile info string for location of reference:
             $infoString = $this->infoStr($rec);
             // Handle missing file:
             if ($tempExists[$idx]['uid']) {
                 if ($tempExists[$idx]['pid'] == -1) {
                     $resultArray['offlineVersionRecords' . $suffix][$idx][$rec['hash']] = $infoString;
                     ksort($resultArray['offlineVersionRecords' . $suffix][$idx]);
                 } elseif ($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete'] && $tempExists[$idx][$GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']]) {
                     $resultArray['deletedRecords' . $suffix][$idx][$rec['hash']] = $infoString;
                     ksort($resultArray['deletedRecords' . $suffix][$idx]);
                 }
             } else {
                 $resultArray['nonExistingRecords' . $suffix][$idx][$rec['hash']] = $infoString;
                 ksort($resultArray['nonExistingRecords' . $suffix][$idx]);
             }
         }
     }
     ksort($resultArray['offlineVersionRecords_m']);
     ksort($resultArray['deletedRecords_m']);
     ksort($resultArray['nonExistingRecords_m']);
     ksort($resultArray['offlineVersionRecords_s']);
     ksort($resultArray['deletedRecords_s']);
     ksort($resultArray['nonExistingRecords_s']);
     return $resultArray;
 }
 /**
  * Main method
  *
  * @param CLickMenu $backRef
  * @param array $menuItems
  * @param string $table
  * @param int $uid
  *
  * @return array
  */
 public function main($backRef, array $menuItems, $table = '', $uid = 0)
 {
     if ($table === 'tt_content') {
         $this->setLanguageService($GLOBALS['LANG']);
         // add "paste reference after" if user is allowed to use CType shortcut
         if ($this->getBackendUser()->checkAuthMode('tt_content', 'CType', 'shortcut', 'explicitAllow')) {
             if ($menuItems['pasteafter']) {
                 unset($menuItems['pasteafter']);
                 $selItem = $backRef->clipObj->getSelectedRecord();
                 $targetItem = BackendUtility::getRecordRaw('tt_content', 'uid = ' . $uid, 'colPos,tx_gridelements_container,tx_gridelements_columns');
                 $elInfo = array(GeneralUtility::fixed_lgd_cs($selItem['_RECORD_TITLE'], $this->getBackendUser()->uc['titleLen']), $backRef->root ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $backRef->rec), $this->getBackendUser()->uc['titleLen']), $backRef->clipObj->currentMode());
                 $menuItems['pasteafter'] = $this->DB_paste($backRef, $table, -$uid, 'after', $elInfo, $targetItem, false);
                 if ($backRef->clipObj->currentMode() === 'copy') {
                     $menuItems['pastereference'] = $this->DB_paste($backRef, $table, -$uid, 'after', $elInfo, $targetItem, true);
                 }
             }
         }
     }
     return $menuItems;
 }
 /**
  * Creates ADMCMD parameters for the "viewpage" extension / frontend
  *
  * @param array $pageInfo Page record
  * @return string Query-parameters
  * @internal
  */
 public static function ADMCMD_previewCmds($pageInfo)
 {
     $simUser = '';
     $simTime = '';
     if ($pageInfo['fe_group'] > 0) {
         $simUser = '******' . $pageInfo['fe_group'];
     } elseif ((int) $pageInfo['fe_group'] === -2) {
         // -2 means "show at any login". We simulate first available fe_group.
         /** @var PageRepository $sysPage */
         $sysPage = GeneralUtility::makeInstance(PageRepository::class);
         $activeFeGroupRow = BackendUtility::getRecordRaw('fe_groups', '1=1' . $sysPage->enableFields('fe_groups'), 'uid');
         if (!empty($activeFeGroupRow)) {
             $simUser = '******' . $activeFeGroupRow['uid'];
         }
     }
     if ($pageInfo['starttime'] > $GLOBALS['EXEC_TIME']) {
         $simTime = '&ADMCMD_simTime=' . $pageInfo['starttime'];
     }
     if ($pageInfo['endtime'] < $GLOBALS['EXEC_TIME'] && $pageInfo['endtime'] != 0) {
         $simTime = '&ADMCMD_simTime=' . ($pageInfo['endtime'] - 1);
     }
     return $simUser . $simTime;
 }
 /**
  * Checks if record can be selected based on given permission criteria
  *
  * @param string $table Record table name
  * @param int $id Record UID
  * @param int|string $perms Permission restrictions to observe: Either an integer that will be bitwise AND'ed or a string, which points to a key in the ->pMap array
  * @return bool Returns TRUE if the record given by $table, $id and $perms can be selected
  *
  * @throws \RuntimeException
  */
 public function doesRecordExist($table, $id, $perms)
 {
     $id = (int) $id;
     if ($this->bypassAccessCheckForRecords) {
         return is_array(BackendUtility::getRecordRaw($table, 'uid=' . $id, 'uid'));
     }
     // Processing the incoming $perms (from possible string to integer that can be AND'ed)
     if (!MathUtility::canBeInterpretedAsInteger($perms)) {
         if ($table != 'pages') {
             switch ($perms) {
                 case 'edit':
                 case 'delete':
                 case 'new':
                     // This holds it all in case the record is not page!!
                     if ($table === 'sys_file_reference' && array_key_exists('pages', $this->datamap)) {
                         $perms = 'edit';
                     } else {
                         $perms = 'editcontent';
                     }
                     break;
             }
         }
         $perms = (int) $this->pMap[$perms];
     } else {
         $perms = (int) $perms;
     }
     if (!$perms) {
         throw new \RuntimeException('Internal ERROR: no permissions to check for non-admin user', 1270853920);
     }
     // For all tables: Check if record exists:
     $isWebMountRestrictionIgnored = BackendUtility::isWebMountRestrictionIgnored($table);
     if (is_array($GLOBALS['TCA'][$table]) && $id > 0 && ($isWebMountRestrictionIgnored || $this->isRecordInWebMount($table, $id) || $this->admin)) {
         if ($table != 'pages') {
             // Find record without checking page:
             $mres = $this->databaseConnection->exec_SELECTquery('uid,pid', $table, 'uid=' . (int) $id . $this->deleteClause($table));
             // THIS SHOULD CHECK FOR editlock I think!
             $output = $this->databaseConnection->sql_fetch_assoc($mres);
             BackendUtility::fixVersioningPid($table, $output, true);
             // If record found, check page as well:
             if (is_array($output)) {
                 // Looking up the page for record:
                 $mres = $this->doesRecordExist_pageLookUp($output['pid'], $perms);
                 $pageRec = $this->databaseConnection->sql_fetch_assoc($mres);
                 // Return TRUE if either a page was found OR if the PID is zero AND the user is ADMIN (in which case the record is at root-level):
                 $isRootLevelRestrictionIgnored = BackendUtility::isRootLevelRestrictionIgnored($table);
                 if (is_array($pageRec) || !$output['pid'] && ($isRootLevelRestrictionIgnored || $this->admin)) {
                     return true;
                 }
             }
             return false;
         } else {
             $mres = $this->doesRecordExist_pageLookUp($id, $perms);
             return $this->databaseConnection->sql_num_rows($mres);
         }
     }
     return false;
 }
Exemple #5
0
 function createExceptionRule($pid, $cruserId, $eventUid, $exceptionRuleDescription)
 {
     $event = BackendUtility::getRecordRaw('tx_cal_event', 'uid=' . $eventUid);
     $insertFields = array();
     $insertFields['tstamp'] = time();
     $insertFields['crdate'] = time();
     $insertFields['pid'] = $pid;
     $insertFields['cruser_id'] = $cruserId;
     $insertFields['title'] = 'Exception rule for event ' . $eventUid;
     $insertFields['start_date'] = $event['start_date'];
     $this->insertRuleValues($exceptionRuleDescription, $insertFields);
     $result = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_cal_exception_event', $insertFields);
     if (FALSE === $result) {
         throw new \RuntimeException('Could not write tx_cal_exception_event_mm record to database: ' . $GLOBALS['TYPO3_DB']->sql_error(), 1431458149);
     }
     $result = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_cal_exception_event_mm', array('tablenames' => 'tx_cal_exception_event', 'uid_local' => $eventUid, 'uid_foreign' => $GLOBALS['TYPO3_DB']->sql_insert_id()));
     if (FALSE === $result) {
         throw new \RuntimeException('Could not write tx_cal_exception_event_mm record to database: ' . $GLOBALS['TYPO3_DB']->sql_error(), 1431458150);
     }
 }
Exemple #6
0
 /**
  * Find relations pointing to non-existing records (in managed references or soft-references)
  *
  * @return array an array of records within sys_refindex
  */
 protected function findRelationsToNonExistingRecords() : array
 {
     $deletedRecords = [];
     $deletedRecordsInSoftReferenceRelations = [];
     $nonExistingRecords = [];
     $nonExistingRecordsInSoftReferenceRelations = [];
     $offlineVersionRecords = [];
     $offlineVersionRecordsInSoftReferenceRelations = [];
     // Select DB relations from reference table
     $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
     $rowIterator = $queryBuilder->select('ref_uid', 'ref_table', 'softref_key', 'hash', 'tablename', 'recuid', 'field', 'flexpointer', 'deleted')->from('sys_refindex')->where($queryBuilder->expr()->neq('ref_table', $queryBuilder->createNamedParameter('_FILE', \PDO::PARAM_STR)), $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)))->execute();
     $existingRecords = [];
     while ($rec = $rowIterator->fetch()) {
         $isSoftReference = !empty($rec['softref_key']);
         $idx = $rec['ref_table'] . ':' . $rec['ref_uid'];
         // Get referenced record:
         if (!isset($existingRecords[$idx])) {
             $existingRecords[$idx] = BackendUtility::getRecordRaw($rec['ref_table'], 'uid=' . (int) $rec['ref_uid'], 'uid,pid' . (isset($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']) ? ',' . $GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete'] : ''));
         }
         // Compile info string for location of reference:
         $infoString = $this->formatReferenceIndexEntryToString($rec);
         // Handle missing file:
         if ($existingRecords[$idx]['uid']) {
             // Record exists, but is a reference to an offline version
             if ((int) $existingRecords[$idx]['pid'] === -1) {
                 if ($isSoftReference) {
                     $offlineVersionRecordsInSoftReferenceRelations[] = $infoString;
                 } else {
                     $offlineVersionRecords[$idx][$rec['hash']] = $infoString;
                 }
                 // reference to a deleted record
             } elseif (isset($GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']) && $existingRecords[$idx][$GLOBALS['TCA'][$rec['ref_table']]['ctrl']['delete']]) {
                 if ($isSoftReference) {
                     $deletedRecordsInSoftReferenceRelations[] = $infoString;
                 } else {
                     $deletedRecords[] = $infoString;
                 }
             }
         } else {
             if ($isSoftReference) {
                 $nonExistingRecordsInSoftReferenceRelations[] = $infoString;
             } else {
                 $nonExistingRecords[$idx][$rec['hash']] = $infoString;
             }
         }
     }
     return ['nonExistingRecords' => ArrayUtility::sortByKeyRecursive($nonExistingRecords), 'nonExistingRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($nonExistingRecordsInSoftReferenceRelations), 'offlineVersionRecords' => ArrayUtility::sortByKeyRecursive($offlineVersionRecords), 'offlineVersionRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($offlineVersionRecordsInSoftReferenceRelations), 'deletedRecords' => ArrayUtility::sortByKeyRecursive($deletedRecords), 'deletedRecordsInSoftReferenceRelations' => ArrayUtility::sortByKeyRecursive($deletedRecordsInSoftReferenceRelations)];
 }
    /**
     * Creates the listing of records from a single table
     *
     * @param string $table Table name
     * @param int $id Page id
     * @param string $rowlist List of fields to show in the listing.
     * 	Pseudo fields will be added including the record header.
     *
     * @return string HTML table with the listing for the record.
     * @throws UnexpectedValueException If hook was of wrong interface
     */
    public function getTable($table, $id, $rowlist)
    {
        $database = $this->getDatabaseConnection();
        $language = $this->getLanguageService();
        $backendUser = $this->getBackendUser();
        // Init
        $addWhere = '';
        $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label'];
        $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail'];
        $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'];
        $tableCollapsed = !$this->tablesCollapsed[$table] ? FALSE : TRUE;
        // prepare space icon
        $this->spaceIcon = IconUtility::getSpriteIcon('empty-empty', array('style' => 'background-position: 0 10px;'));
        // Cleaning rowlist for duplicates and place the $titleCol
        // as the first column always!
        $this->fieldArray = array();
        // title Column
        // Add title column
        $this->fieldArray[] = $titleCol;
        // Control-Panel
        if (!GeneralUtility::inList($rowlist, '_CONTROL_')) {
            $this->fieldArray[] = '_CONTROL_';
            $this->fieldArray[] = '_AFTERCONTROL_';
        }
        // Clipboard
        if ($this->showClipboard) {
            $this->fieldArray[] = '_CLIPBOARD_';
        }
        // Ref
        if (!$this->dontShowClipControlPanels) {
            $this->fieldArray[] = '_REF_';
            $this->fieldArray[] = '_AFTERREF_';
        }
        // Path
        if ($this->searchLevels) {
            $this->fieldArray[] = '_PATH_';
        }
        // Localization
        if ($this->localizationView && $l10nEnabled) {
            $this->fieldArray[] = '_LOCALIZATION_';
            $this->fieldArray[] = '_LOCALIZATION_b';
            $addWhere .= ' AND (
				' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . ' <= 0
				OR
				' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0
			)';
        }
        // Cleaning up:
        $this->fieldArray = array_unique(array_merge($this->fieldArray, GeneralUtility::trimExplode(',', $rowlist, 1)));
        if ($this->noControlPanels) {
            $tempArray = array_flip($this->fieldArray);
            unset($tempArray['_CONTROL_']);
            unset($tempArray['_CLIPBOARD_']);
            $this->fieldArray = array_keys($tempArray);
        }
        // Creating the list of fields to include in the SQL query:
        $selectFields = $this->fieldArray;
        $selectFields[] = 'uid';
        $selectFields[] = 'pid';
        // adding column for thumbnails
        if ($thumbsCol) {
            $selectFields[] = $thumbsCol;
        }
        if ($table == 'pages') {
            if (ExtensionManagementUtility::isLoaded('cms')) {
                $selectFields[] = 'module';
                $selectFields[] = 'extendToSubpages';
                $selectFields[] = 'nav_hide';
            }
            $selectFields[] = 'doktype';
        }
        if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
            $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['type']) {
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['type'];
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['typeicon_column']) {
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['typeicon_column'];
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
            $selectFields[] = 't3ver_id';
            $selectFields[] = 't3ver_state';
            $selectFields[] = 't3ver_wsid';
            // Filtered out when tx_commerce_categories in makeFieldList()
            $selectFields[] = 't3ver_swapmode';
        }
        if ($l10nEnabled) {
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) {
            $selectFields = array_merge($selectFields, GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], 1));
        }
        // Unique list!
        $selectFields = array_unique($selectFields);
        // Making sure that the fields in the field-list ARE in the field-list from TCA!
        $selectFields = array_intersect($selectFields, $this->makeFieldList($table, 1));
        // implode it into a list of fields for the SQL-statement.
        $selFieldList = implode(',', $selectFields);
        $this->selFieldList = $selFieldList;
        /**
         * DB-List getTable
         *
         * @date 2007-11-16
         * @request Malte Jansen <*****@*****.**>
         */
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
                $hookObject = GeneralUtility::getUserObj($classData);
                if (!$hookObject instanceof \TYPO3\CMS\Backend\RecordList\RecordListGetTableHookInterface) {
                    throw new UnexpectedValueException('$hookObject must implement interface \\TYPO3\\CMS\\Backend\\RecordList\\RecordListGetTableHookInterface', 1195114460);
                }
                $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
            }
        }
        // Create the SQL query for selecting the elements in the listing:
        // do not do paging when outputting as CSV
        if ($this->csvOutput) {
            $this->iLimit = 0;
        }
        if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
            // Get the two previous rows for sorting if displaying page > 1
            $this->firstElementNumber = $this->firstElementNumber - 2;
            $this->iLimit = $this->iLimit + 2;
            // (API function from class.db_list.inc)
            $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList);
            $this->firstElementNumber = $this->firstElementNumber + 2;
            $this->iLimit = $this->iLimit - 2;
        } else {
            // (API function from class.db_list.inc)
            $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList);
        }
        // Finding the total amount of records on the page
        $this->setTotalItems($queryParts);
        // Init:
        $dbCount = 0;
        $out = '';
        $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table;
        $result = FALSE;
        // If the count query returned any number of records,
        // we perform the real query, selecting records.
        if ($this->totalItems) {
            // Fetch records only if not in single table mode or
            // if in multi table mode and not collapsed
            if ($listOnlyInSingleTableMode || !$this->table && $tableCollapsed) {
                $dbCount = $this->totalItems;
            } else {
                // set the showLimit to the number of records when outputting as CSV
                if ($this->csvOutput) {
                    $this->showLimit = $this->totalItems;
                    $this->iLimit = $this->totalItems;
                }
                $result = $database->exec_SELECT_queryArray($queryParts);
                $dbCount = $database->sql_num_rows($result);
            }
        }
        // If any records was selected, render the list:
        if ($dbCount) {
            // Half line is drawn between tables:
            if (!$listOnlyInSingleTableMode) {
                $theData = array();
                if (!$this->table && !$rowlist) {
                    $theData[$titleCol] = '<img src="/' . TYPO3_mainDir . '/clear.gif" width="' . ($GLOBALS['SOBE']->MOD_SETTINGS['bigControlPanel'] ? '230' : '350') . '" height="1" alt="" />';
                    if (in_array('_CONTROL_', $this->fieldArray)) {
                        $theData['_CONTROL_'] = '';
                    }
                    if (in_array('_CLIPBOARD_', $this->fieldArray)) {
                        $theData['_CLIPBOARD_'] = '';
                    }
                }
                $out .= $this->addelement(0, '', $theData, 'class="c-table-row-spacer"', $this->leftMargin);
            }
            // Header line is drawn
            $theData = array();
            if ($this->disableSingleTableView) {
                $theData[$titleCol] = '<span class="c-table">' . BackendUtility::wrapInHelp($table, '', $language->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE)) . '</span> (' . $this->totalItems . ')';
            } else {
                $theData[$titleCol] = $this->linkWrapTable($table, '<span class="c-table">' . $language->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE) . '</span> (' . $this->totalItems . ') ' . ($this->table ? IconUtility::getSpriteIcon('actions-view-table-collapse', array('title' => $language->getLL('contractView', TRUE))) : IconUtility::getSpriteIcon('actions-view-table-expand', array('title' => $language->getLL('expandView', TRUE)))));
            }
            if ($listOnlyInSingleTableMode) {
                $out .= '
					<tr>
						<td class="t3-row-header" style="width: 95%;">' . BackendUtility::wrapInHelp($table, '', $theData[$titleCol]) . '</td>
					</tr>';
            } else {
                // Render collapse button if in multi table mode
                $collapseIcon = '';
                if (!$this->table) {
                    if ($tableCollapsed) {
                        $options = array('class' => 'collapseIcon', 'title' => $language->sL('LLL:EXT:lang/locallang_core.php:labels.expandTable', TRUE));
                    } else {
                        $options = array('class' => 'collapseIcon', 'title' => $language->sL('LLL:EXT:lang/locallang_core.php:labels.collapseTable', TRUE));
                    }
                    $value = $tableCollapsed ? '0' : '1';
                    $collapseIcon = '<a href="' . htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . $value) . '">' . ($tableCollapsed ? IconUtility::getSpriteIcon('actions-view-list-expand', $options) : IconUtility::getSpriteIcon('actions-view-list-collapse', $options)) . '</a>';
                }
                $out .= $this->addElement(1, $collapseIcon, $theData, ' class="t3-row-header"', '');
            }
            $iOut = '';
            // Render table rows only if in multi table view
            // and not collapsed or if in single table view
            if (!$listOnlyInSingleTableMode && (!$tableCollapsed || $this->table)) {
                // Fixing a order table for sortby tables
                $this->currentTable = array();
                $currentIdList = array();
                $doSort = $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField;
                $prevUid = 0;
                $prevPrevUid = 0;
                // Get first two rows and initialize prevPrevUid and prevUid if on page > 1
                if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
                    $row = $database->sql_fetch_assoc($result);
                    $prevPrevUid = -(int) $row['uid'];
                    $row = $database->sql_fetch_assoc($result);
                    $prevUid = $row['uid'];
                }
                // Accumulate rows here
                $accRows = array();
                while ($row = $database->sql_fetch_assoc($result)) {
                    // In offline workspace, look for alternative record:
                    BackendUtility::workspaceOL($table, $row, $this->getBackendUser()->workspace, TRUE);
                    if (is_array($row)) {
                        $accRows[] = $row;
                        $currentIdList[] = $row['uid'];
                        if ($doSort) {
                            if ($prevUid) {
                                $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
                                $this->currentTable['next'][$prevUid] = '-' . $row['uid'];
                                $this->currentTable['prevUid'][$row['uid']] = $prevUid;
                            }
                            $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
                            $prevUid = $row['uid'];
                        }
                    }
                }
                $database->sql_free_result($result);
                $this->totalRowCount = count($accRows);
                // CSV initiated
                if ($this->csvOutput) {
                    $this->initCSV();
                }
                // Render items:
                $this->CBnames = array();
                $this->duplicateStack = array();
                $this->eCounter = $this->firstElementNumber;
                $iOut = '';
                $cc = 0;
                foreach ($accRows as $row) {
                    // Render item row if counter < limit
                    if ($cc < $this->iLimit) {
                        $cc++;
                        $this->translations = FALSE;
                        $iOut .= $this->renderListRow($table, $row, $cc, $titleCol, $thumbsCol);
                        // If localization view is enabled it means that the selected records are
                        // either default or All language and here we will not select translations
                        // which point to the main record:
                        if ($this->localizationView && $l10nEnabled) {
                            // For each available translation, render the record:
                            if (is_array($this->translations)) {
                                foreach ($this->translations as $lRow) {
                                    // $lRow isn't always what we want - if record was moved we've to work with the
                                    // placeholder records otherwise the list is messed up a bit
                                    if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) {
                                        $tmpRow = BackendUtility::getRecordRaw($table, 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table), $selFieldList);
                                        $lRow = is_array($tmpRow) ? $tmpRow : $lRow;
                                    }
                                    // In offline workspace, look for alternative record:
                                    BackendUtility::workspaceOL($table, $lRow, $this->getBackendUser()->workspace, TRUE);
                                    if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
                                        $currentIdList[] = $lRow['uid'];
                                        $iOut .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18);
                                    }
                                }
                            }
                        }
                    }
                    // Counter of total rows incremented:
                    $this->eCounter++;
                }
                // Record navigation is added to the beginning and
                // end of the table if in single table mode
                if ($this->table) {
                    $iOut = $this->renderListNavigation('top') . $iOut . $this->renderListNavigation('bottom');
                } else {
                    // show that there are more records than shown
                    if ($this->totalItems > $this->itemsLimitPerTable) {
                        $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
                        $hasMore = $this->totalItems > $this->itemsLimitSingleTable;
                        $iOut .= '<tr><td colspan="' . count($this->fieldArray) . '" style="padding: 5px;">
							<a href="' . htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '">' . '<img' . IconUtility::skinImg($this->backPath, 'gfx/pildown.gif', 'width="14" height="14"') . ' alt="" />' . ' <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a>
							</td></tr>';
                    }
                }
                // The header row for the table is now created:
                $out .= $this->renderListHeader($table, $currentIdList);
            }
            // The list of records is added after the header:
            $out .= $iOut;
            unset($iOut);
            // ... and it is all wrapped in a table:
            $out = '



			<!--
				DB listing of elements:	"' . htmlspecialchars($table) . '"
			-->
				<table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist' . ($listOnlyInSingleTableMode ? ' typo3-dblist-overview' : '') . '">
					' . $out . '
				</table>';
            // Output csv if...
            if ($this->csvOutput) {
                // This ends the page with exit.
                $this->outputCSV($table);
            }
        }
        // Return content:
        return $out;
    }
 /**
  * Call this function to update the sys_refindex table for a record (even one just deleted)
  * NOTICE: Currently, references updated for a deleted-flagged record will not include those from within flexform fields in some cases where the data structure is defined by another record since the resolving process ignores deleted records! This will also result in bad cleaning up in tcemain I think... Anyway, thats the story of flexforms; as long as the DS can change, lots of references can get lost in no time.
  *
  * @param string $tableName Table name
  * @param int $uid UID of record
  * @param bool $testOnly If set, nothing will be written to the index but the result value will still report statistics on what is added, deleted and kept. Can be used for mere analysis.
  * @return array Array with statistics about how many index records were added, deleted and not altered plus the complete reference set for the record.
  * @todo Define visibility
  */
 public function updateRefIndexTable($tableName, $uid, $testOnly = FALSE)
 {
     // First, secure that the index table is not updated with workspace tainted relations:
     $this->WSOL = FALSE;
     // Init:
     $result = array('keptNodes' => 0, 'deletedNodes' => 0, 'addedNodes' => 0);
     // If this table cannot contain relations, skip it
     if (isset(static::$nonRelationTables[$tableName])) {
         return $result;
     }
     // Fetch tableRelationFields and save them in cache if not there yet
     $cacheId = static::$cachePrefixTableRelationFields . $tableName;
     if (!$this->runtimeCache->has($cacheId)) {
         $tableRelationFields = $this->fetchTableRelationFields($tableName);
         $this->runtimeCache->set($cacheId, $tableRelationFields);
     } else {
         $tableRelationFields = $this->runtimeCache->get($cacheId);
     }
     // Get current index from Database with hash as index using $uidIndexField
     $currentRelations = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_refindex', 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tableName, 'sys_refindex') . ' AND recuid=' . (int) $uid . ' AND workspace=' . (int) $this->getWorkspaceId(), '', '', '', 'hash');
     // If the table has fields which could contain relations and the record does exist (including deleted-flagged)
     if ($tableRelationFields !== '' && BackendUtility::getRecordRaw($tableName, 'uid=' . (int) $uid, 'uid')) {
         // Then, get relations:
         $relations = $this->generateRefIndexData($tableName, $uid);
         if (is_array($relations)) {
             // Traverse the generated index:
             foreach ($relations as $k => $datRec) {
                 if (!is_array($relations[$k])) {
                     continue;
                 }
                 $relations[$k]['hash'] = md5(implode('///', $relations[$k]) . '///' . $this->hashVersion);
                 // First, check if already indexed and if so, unset that row (so in the end we know which rows to remove!)
                 if (isset($currentRelations[$relations[$k]['hash']])) {
                     unset($currentRelations[$relations[$k]['hash']]);
                     $result['keptNodes']++;
                     $relations[$k]['_ACTION'] = 'KEPT';
                 } else {
                     // If new, add it:
                     if (!$testOnly) {
                         $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_refindex', $relations[$k]);
                     }
                     $result['addedNodes']++;
                     $relations[$k]['_ACTION'] = 'ADDED';
                 }
             }
             $result['relations'] = $relations;
         } else {
             return FALSE;
         }
     }
     // If any old are left, remove them:
     if (!empty($currentRelations)) {
         $hashList = array_keys($currentRelations);
         if (!empty($hashList)) {
             $result['deletedNodes'] = count($hashList);
             $result['deletedNodes_hashList'] = implode(',', $hashList);
             if (!$testOnly) {
                 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_refindex', 'hash IN (' . implode(',', $GLOBALS['TYPO3_DB']->fullQuoteArray($hashList, 'sys_refindex')) . ')');
             }
         }
     }
     return $result;
 }
 /**
  * Gets a placeholder for a given page
  *
  * @param array $page
  * @return array
  */
 protected function getPositionPlaceholder($page)
 {
     if (-1 !== intval($page['pid'])) {
         // original, dont do anything
         return $page;
     } elseif (0 === intval($page['t3ver_state'])) {
         // page has changed, but not moved
         $page = BackendUtility::getRecord('pages', $page['t3ver_oid']);
     } elseif (4 === intval($page['t3ver_state'])) {
         // page has moved. get placeholder for new position
         $page = BackendUtility::getRecordRaw('pages', $where = sprintf('t3ver_move_id=%d AND t3ver_state=3', $page['t3ver_oid']), $fields = '*');
     }
     return $page;
 }
 /**
  * Generates the title and puts the record title behind
  *
  * @param string $table
  * @param string $uid
  * @return string
  * @todo Define visibility
  */
 public function generateTitle($table, $uid)
 {
     $out = $table . ':' . $uid;
     if ($labelField = $GLOBALS['TCA'][$table]['ctrl']['label']) {
         $record = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordRaw($table, 'uid=' . intval($uid));
         $out .= ' (' . \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordTitle($table, $record, TRUE) . ')';
     }
     return $out;
 }
Exemple #11
0
 /**
  * Check a specific record on all TCA columns if they are FlexForms and if the FlexForm values
  * don't match to the newly defined ones.
  *
  * @param string $tableName Table name
  * @param int $uid UID of record in processing
  * @param array $dirtyFlexFormFields the existing FlexForm fields
  * @return array the updated list of dirty FlexForm fields
  */
 protected function compareAllFlexFormsInRecord(string $tableName, int $uid, array $dirtyFlexFormFields = []) : array
 {
     $flexObj = GeneralUtility::makeInstance(FlexFormTools::class);
     foreach ($GLOBALS['TCA'][$tableName]['columns'] as $columnName => $columnConfiguration) {
         if ($columnConfiguration['config']['type'] === 'flex') {
             $fullRecord = BackendUtility::getRecordRaw($tableName, 'uid=' . (int) $uid);
             if ($fullRecord[$columnName]) {
                 // Clean XML and check against the record fetched from the database
                 $newXML = $flexObj->cleanFlexFormXML($tableName, $columnName, $fullRecord);
                 if (md5($fullRecord[$columnName]) !== md5($newXML)) {
                     $dirtyFlexFormFields[$tableName . ':' . $uid . ':' . $columnName] = $fullRecord;
                 }
             }
         }
     }
     return $dirtyFlexFormFields;
 }
 /**
  * Rendering a single row for the list
  *
  * @param string $table Table name
  * @param mixed[] $row Current record
  * @param int $cc Counter, counting for each time an element is rendered (used for alternating colors)
  * @param string $titleCol Table field (column) where header value is found
  * @param string $thumbsCol Table field (column) where (possible) thumbnails can be found
  * @param int $indent Indent from left.
  * @param integer $level
  * @param string $expanded
  *
  * @return string Table row for the element
  * @access private
  * @see getTable()
  */
 public function renderListRow($table, $row, $cc, $titleCol, $thumbsCol, $indent = 0, $level = 0, $expanded = '')
 {
     if (!is_array($row)) {
         return '';
     }
     $rowOutput = '';
     $id_orig = null;
     // If in search mode, make sure the preview will show the correct page
     if ((string) $this->searchString !== '') {
         $id_orig = $this->id;
         $this->id = $row['pid'];
     }
     // Add special classes for first and last row
     $rowSpecial = '';
     if ($cc == 1 && $indent == 0) {
         $rowSpecial .= ' firstcol';
     }
     if ($cc == $this->totalRowCount || $cc == $this->iLimit) {
         $rowSpecial .= ' lastcol';
     }
     $row_bgColor = ' class="' . $rowSpecial . '"';
     // Overriding with versions background color if any:
     $row_bgColor = $row['_CSSCLASS'] ? ' class="' . $row['_CSSCLASS'] . '"' : $row_bgColor;
     // Incr. counter.
     $this->counter++;
     // The icon with link
     $altText = BackendUtility::getRecordIconAltText($row, $table);
     $additionalStyle = $indent ? ' style="margin-left: ' . $indent . 'px;"' : '';
     $iconImg = '<span title="' . $altText . '" ' . $additionalStyle . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
     $theIcon = $this->clickMenuEnabled ? BackendUtility::wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg;
     // Preparing and getting the data-array
     $theData = array();
     $localizationMarkerClass = '';
     $lC2 = '';
     foreach ($this->fieldArray as $fCol) {
         if ($fCol == $titleCol) {
             $recTitle = BackendUtility::getRecordTitle($table, $row, false, true);
             $warning = '';
             // If the record is edit-locked	by another user, we will show a little warning sign:
             $lockInfo = BackendUtility::isRecordLocked($table, $row['uid']);
             if ($lockInfo) {
                 $warning = '<a href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . '); return false;" title="' . htmlspecialchars($lockInfo['msg']) . '">' . $this->iconFactory->getIcon('status-warning-in-use', Icon::SIZE_SMALL)->render() . '</a>';
             }
             $theData[$fCol] = $theData['__label'] = $warning . $this->linkWrapItems($table, $row['uid'], $recTitle, $row);
             // Render thumbnails, if:
             // - a thumbnail column exists
             // - there is content in it
             // - the thumbnail column is visible for the current type
             $type = 0;
             if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) {
                 $typeColumn = $GLOBALS['TCA'][$table]['ctrl']['type'];
                 $type = $row[$typeColumn];
             }
             // If current type doesn't exist, set it to 0 (or to 1 for historical reasons,
             // if 0 doesn't exist)
             if (!isset($GLOBALS['TCA'][$table]['types'][$type])) {
                 $type = isset($GLOBALS['TCA'][$table]['types'][0]) ? 0 : 1;
             }
             $visibleColumns = $GLOBALS['TCA'][$table]['types'][$type]['showitem'];
             if ($this->thumbs && trim($row[$thumbsCol]) && preg_match('/(^|(.*(;|,)?))' . $thumbsCol . '(((;|,).*)|$)/', $visibleColumns) === 1) {
                 $theData[$fCol] .= '<br />' . $this->thumbCode($row, $table, $thumbsCol);
             }
             if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] != 0 && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) {
                 // It's a translated record with a language parent
                 $localizationMarkerClass = ' localization';
             }
         } elseif ($fCol == 'pid') {
             $theData[$fCol] = $row[$fCol];
         } elseif ($fCol == '_PATH_') {
             $theData[$fCol] = $this->recPath($row['pid']);
         } elseif ($fCol == '_REF_') {
             $theData[$fCol] = $this->createReferenceHtml($table, $row['uid']);
         } elseif ($fCol == '_CONTROL_') {
             $theData[$fCol] = $this->makeControl($table, $row, $level);
         } elseif ($fCol == '_CLIPBOARD_') {
             $theData[$fCol] = $this->makeClip($table, $row);
         } elseif ($fCol == '_LOCALIZATION_') {
             list($lC1, $lC2) = $this->makeLocalizationPanel($table, $row);
             $theData[$fCol] = $lC1;
         } elseif ($fCol != '_LOCALIZATION_b') {
             $tmpProc = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 100, $row['uid']);
             $theData[$fCol] = $this->linkUrlMail(htmlspecialchars($tmpProc), $row[$fCol]);
             if ($this->csvOutput) {
                 $row[$fCol] = BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']);
             }
         } elseif ($fCol == '_LOCALIZATION_b') {
             $theData[$fCol] = $lC2;
         } else {
             $theData[$fCol] = htmlspecialchars(BackendUtility::getProcessedValueExtra($table, $fCol, $row[$fCol], 0, $row['uid']));
         }
     }
     // Reset the ID if it was overwritten
     if ((string) $this->searchString !== '') {
         $this->id = $id_orig;
     }
     // Add row to CSV list:
     if ($this->csvOutput) {
         $this->addToCSV($row);
     }
     // Add classes to table cells
     $this->addElement_tdCssClass[$titleCol] = 'col-title' . $localizationMarkerClass;
     $this->addElement_tdCssClass['_CONTROL_'] = 'col-control';
     if ($this->getModule()->MOD_SETTINGS['clipBoard']) {
         $this->addElement_tdCssClass['_CLIPBOARD_'] = 'col-clipboard';
     }
     $this->addElement_tdCssClass['_PATH_'] = 'col-path';
     $this->addElement_tdCssClass['_LOCALIZATION_'] = 'col-localizationa';
     $this->addElement_tdCssClass['_LOCALIZATION_b'] = 'col-localizationb';
     /**
      * @hook checkChildren
      * @date 2014-02-11
      * @request Alexander Grein <*****@*****.**>
      */
     if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'])) {
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['actions'] as $classData) {
             $hookObject = GeneralUtility::getUserObj($classData);
             if (is_object($hookObject) && method_exists($hookObject, 'checkChildren')) {
                 $hookObject->checkChildren($table, $row, $level, $theData, $this);
             }
         }
     }
     // Create element in table cells:
     $theData['uid'] = $row['uid'];
     if ($table === 'tt_content') {
         $theData['tx_gridelements_container'] = $row['tx_gridelements_container'];
     }
     if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && !isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'])) {
         $theData['parent'] = $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']];
     }
     $rowOutput .= $this->addElement(1, $theIcon, $theData, $row_bgColor, '', '', '', $level);
     if ($this->localizationView && $this->l10nEnabled) {
         // For each available translation, render the record:
         if (is_array($this->translations)) {
             foreach ($this->translations as $lRow) {
                 // $lRow isn't always what we want - if record was moved we've to work with the
                 // placeholder records otherwise the list is messed up a bit
                 if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) {
                     $where = 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table);
                     $tmpRow = BackendUtility::getRecordRaw($table, $where, $this->selFieldList);
                     $lRow = is_array($tmpRow) ? $tmpRow : $lRow;
                 }
                 // In offline workspace, look for alternative record:
                 BackendUtility::workspaceOL($table, $lRow, $this->backendUser->workspace, true);
                 if (is_array($lRow) && $this->backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
                     $this->currentIdList[] = $lRow['uid'];
                     if ($row['tx_gridelements_container']) {
                         $lRow['_CSSCLASS'] = 't3-gridelements-child" data-trigger-container="' . $row['tx_gridelements_container'] . $expanded;
                     }
                     $rowOutput .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 20, $level);
                 }
             }
         }
     }
     if ($theData['_EXPANDABLE_'] && $level < 8 && ($row['l18n_parent'] == 0 || !$this->localizationView)) {
         if (!empty($theData['_CHILDREN_'])) {
             $expanded = $this->expandedGridelements[$row['uid']] ? '" style="display: table-row;' : '';
             $lastGridColumn = '';
             $originalMoveUp = $this->showMoveUp;
             $originalMoveDown = $this->showMoveDown;
             $prevPrevUid = (int) $theData['_CHILDREN_'][0]['uid'];
             $prevUid = (int) $theData['_CHILDREN_'][1]['uid'];
             foreach ($theData['_CHILDREN_'] as $key => $child) {
                 if ($key > 1) {
                     if ($prevUid) {
                         $this->currentTable['prev'][$child['uid']] = $prevPrevUid;
                         $this->currentTable['next'][$prevUid] = -(int) $child['uid'];
                         $this->currentTable['prevUid'][$child['uid']] = $prevUid;
                     }
                     $prevPrevUid = isset($this->currentTable['prev'][$child['uid']]) ? -$prevUid : $row['pid'];
                     $prevUid = $child['uid'];
                 }
             }
             foreach ($theData['_CHILDREN_'] as $key => $child) {
                 if (isset($child['tx_gridelements_columns']) && $child['tx_gridelements_columns'] != $lastGridColumn) {
                     $lastGridColumn = $child['tx_gridelements_columns'];
                     $this->showMoveUp = false;
                     $rowOutput .= '<tr class="t3-gridelements-child" data-trigger-container="' . ($this->localizationView && $row['l18n_parent'] ? $row['l18n_parent'] : $row['uid']) . $expanded . '" data-grid-container="' . $row['uid'] . '">
                                 <td colspan="2"></td>
                                 <td colspan="' . (count($this->fieldArray) - 1 + $this->maxDepth) . '" style="padding:5px;">
                                     <br />
                                     <strong>' . $this->getLanguageService()->sL('LLL:EXT:gridelements/Resources/Private/Language/locallang_db.xml:list.columnName') . ' ' . ($backendLayoutColumns[$child['tx_gridelements_columns']] ? $backendLayoutColumns[$child['tx_gridelements_columns']] : (int) $child['tx_gridelements_columns']) . '</strong>
                                 </td>
                             </tr>';
                 } else {
                     $this->showMoveUp = true;
                 }
                 if (isset($child['tx_gridelements_columns']) && isset($theData['_CHILDREN_'][$key + 1]) && $child['tx_gridelements_columns'] != $theData['_CHILDREN_'][$key + 1]['tx_gridelements_columns']) {
                     $this->showMoveDown = false;
                 } else {
                     $this->showMoveDown = true;
                 }
                 $this->currentIdList[] = $child['uid'];
                 if ($row['CType'] === 'gridelements_pi1') {
                     $this->currentContainerIdList[] = $row['uid'];
                 }
                 $child['_CSSCLASS'] = 't3-gridelements-child" data-trigger-container="' . ($this->localizationView && $row['l18n_parent'] ? $row['l18n_parent'] : $row['uid']) . $expanded;
                 $rowOutput .= $this->renderListRow($table, $child, $cc, $titleCol, $thumbsCol, 0, $level + 1, $expanded);
             }
             $this->showMoveUp = $originalMoveUp;
             $this->showMoveDown = $originalMoveDown;
         }
     }
     // Finally, return table row element:
     return $rowOutput;
 }
 function processCmdmap_postProcess(&$command, &$table, &$id, &$value, &$tce)
 {
     switch ($table) {
         case 'tx_cal_event':
             $select = '*';
             $table = 'tx_cal_event';
             $where = 'uid = ' . $id;
             $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $table, $where);
             if ($result) {
                 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
                     /* If we're in a workspace, don't notify anyone about the event */
                     if ($row['pid'] > 0 && !$GLOBALS['BE_USER']->workspace) {
                         /* Check Page TSConfig for a preview page that we should use */
                         $pageIDForPlugin = $this->getPageIDForPlugin($row['pid']);
                         $page = BackendUtility::getRecord('pages', intval($pageIDForPlugin), "doktype");
                         if ($page['doktype'] != 254) {
                             $tx_cal_api = GeneralUtility::makeInstance('TYPO3\\CMS\\Cal\\Controller\\Api');
                             $tx_cal_api =& $tx_cal_api->tx_cal_api_without($pageIDForPlugin);
                             $notificationService =& \TYPO3\CMS\Cal\Utility\Functions::getNotificationService();
                             if ($command == 'delete') {
                                 /* If the deleted event is temporary, reset the MD5 of the parent calendar */
                                 if ($row['isTemp']) {
                                     $calendar_id = $row['calendar_id'];
                                     $insertFields = array('md5' => '');
                                     $GLOBALS['TYPO3_DB']->exec_UPDATEquery('tx_cal_calendar', 'uid=' . $calendar_id, $insertFields);
                                 }
                                 /** @var \TYPO3\CMS\Cal\Utility\RecurrenceGenerator $rgc */
                                 $rgc = GeneralUtility::makeInstance('TYPO3\\CMS\\Cal\\Utility\\RecurrenceGenerator');
                                 $rgc->cleanIndexTableOfUid($id, $table);
                                 /* Delete all deviations of the event */
                                 $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_cal_event_deviation', 'parentid=' . $id);
                             } else {
                                 $notificationService->notifyOfChanges($row, array($command => $value));
                             }
                         }
                     }
                 }
                 $GLOBALS['TYPO3_DB']->sql_free_result($result);
             }
             break;
         case 'tx_cal_calendar':
             /* If a calendar has been deleted, we might need to clean up. */
             if ($command == 'delete') {
                 /* Using getRecordRaw rather than getRecord since the record has already been deleted. */
                 $calendarRow = BackendUtility::getRecordRaw('tx_cal_calendar', 'uid=' . $id);
                 /* If the calendar is an External URL or ICS file, then we need to clean up */
                 if ($calendarRow['type'] == 1 or $calendarRow['type'] == 2) {
                     $service = new \TYPO3\CMS\Cal\Service\ICalendarService();
                     $service->deleteTemporaryEvents($id);
                     $service->deleteTemporaryCategories($id);
                     $service->deleteScheduledUpdates($id);
                     $service->deleteSchedulerTask($id);
                 }
             }
             if ($command == 'copy') {
                 $newCalendarIds = $tce->copyMappingArray['tx_cal_calendar'];
                 // check if source of copy has a scheduler task attached
                 $calendarRow = BackendUtility::getRecord('tx_cal_calendar', $id);
                 if ($calendarRow['schedulerId'] > 0) {
                     $scheduler = new \TYPO3\CMS\Scheduler\Scheduler();
                     $service = new \TYPO3\CMS\Cal\Service\ICalendarService();
                     foreach ($newCalendarIds as $newCalendarId) {
                         $service->createSchedulerTask($scheduler, 0, $newCalendarId);
                     }
                 }
             }
             break;
         case 'tx_cal_exception_event_group':
         case 'tx_cal_exception_event':
             if ($command == 'delete') {
                 $select = '*';
                 $where = 'uid = ' . $id;
                 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $table, $where);
                 if ($result) {
                     while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
                         /* If we're in a workspace, don't notify anyone about the event */
                         if ($row['pid'] > 0 && !$GLOBALS['BE_USER']->workspace) {
                             /* Check Page TSConfig for a preview page that we should use */
                             $pageIDForPlugin = $this->getPageIDForPlugin($row['pid']);
                             $page = BackendUtility::getRecord('pages', intval($pageIDForPlugin), "doktype");
                             if ($page['doktype'] != 254) {
                                 $tx_cal_api = new \TYPO3\CMS\Cal\Controller\Api();
                                 $tx_cal_api =& $tx_cal_api->tx_cal_api_without($pageIDForPlugin);
                                 /** @var \TYPO3\CMS\Cal\Utility\RecurrenceGenerator $rgc */
                                 $rgc = GeneralUtility::makeInstance('TYPO3\\CMS\\Cal\\Utility\\RecurrenceGenerator');
                                 $rgc->cleanIndexTableOfUid($id, $table);
                             }
                         }
                     }
                     $GLOBALS['TYPO3_DB']->sql_free_result($result);
                 }
             }
             break;
         case 'tx_cal_event_deviation':
             if ($command == 'delete') {
                 $select = 'tx_cal_event.uid, tx_cal_event.pid';
                 $where = 'tx_cal_index.event_uid = tx_cal_event.uid and tx_cal_index.event_deviation_uid = ' . $id;
                 $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, 'tx_cal_index, tx_cal_event', $where);
                 if ($result) {
                     while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
                         $this->reindexEvent($row['uid'], $row['pid']);
                     }
                 }
             }
             break;
     }
 }
Exemple #14
0
 /**
  * Recursive traversal of page tree:
  *
  * @param int $rootID Page root id (must be online, valid page record - or zero for page tree root)
  * @param int $depth Depth
  * @param int $echoLevel Echo Level
  * @param string $callBack Call back function (from this class or subclass)
  * @param bool $versionSwapmode DON'T set from outside, internal. (indicates we are inside a version of a page)
  * @param int $rootIsVersion DON'T set from outside, internal. (1: Indicates that rootID is a version of a page, 2: ...that it is even a version of a version (which triggers a warning!)
  * @param string $accumulatedPath Internal string that accumulates the path
  * @return void
  * @access private
  */
 public function genTree_traverse($rootID, $depth, $echoLevel = 0, $callBack = '', $versionSwapmode = false, $rootIsVersion = 0, $accumulatedPath = '')
 {
     // Register page:
     $this->recStats['all']['pages'][$rootID] = $rootID;
     $pageRecord = BackendUtility::getRecordRaw('pages', 'uid=' . (int) $rootID, 'deleted,title,t3ver_count,t3ver_wsid');
     $accumulatedPath .= '/' . $pageRecord['title'];
     // Register if page is deleted:
     if ($pageRecord['deleted']) {
         $this->recStats['deleted']['pages'][$rootID] = $rootID;
     }
     // If rootIsVersion is set it means that the input rootID is that of a version of a page. See below where the recursive call is made.
     if ($rootIsVersion) {
         $this->recStats['versions']['pages'][$rootID] = $rootID;
         // If it has been published and is in archive now...
         if ($pageRecord['t3ver_count'] >= 1 && $pageRecord['t3ver_wsid'] == 0) {
             $this->recStats['versions_published']['pages'][$rootID] = $rootID;
         }
         // If it has been published and is in archive now...
         if ($pageRecord['t3ver_wsid'] == 0) {
             $this->recStats['versions_liveWS']['pages'][$rootID] = $rootID;
         }
         // If it doesn't belong to a workspace...
         if (!isset($this->workspaceIndex[$pageRecord['t3ver_wsid']])) {
             $this->recStats['versions_lost_workspace']['pages'][$rootID] = $rootID;
         }
         // In case the rootID is a version inside a versioned page
         if ($rootIsVersion == 2) {
             $this->recStats['versions_inside_versioned_page']['pages'][$rootID] = $rootID;
         }
     }
     if ($echoLevel > 0) {
         echo LF . $accumulatedPath . ' [' . $rootID . ']' . ($pageRecord['deleted'] ? ' (DELETED)' : '') . ($this->recStats['versions_published']['pages'][$rootID] ? ' (PUBLISHED)' : '');
     }
     if ($echoLevel > 1 && $this->recStats['versions_lost_workspace']['pages'][$rootID]) {
         echo LF . '	ERROR! This version belongs to non-existing workspace (' . $pageRecord['t3ver_wsid'] . ')!';
     }
     if ($echoLevel > 1 && $this->recStats['versions_inside_versioned_page']['pages'][$rootID]) {
         echo LF . '	WARNING! This version is inside an already versioned page or branch!';
     }
     // Call back:
     if ($callBack) {
         $this->{$callBack}('pages', $rootID, $echoLevel, $versionSwapmode, $rootIsVersion);
     }
     // Traverse tables of records that belongs to page:
     foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
         if ($tableName !== 'pages') {
             // Select all records belonging to page:
             $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
             $queryBuilder->getRestrictions()->removeAll();
             $queryBuilder->select('uid')->from($tableName)->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($rootID, \PDO::PARAM_INT)));
             if ($GLOBALS['TCA'][$tableName]['ctrl']['delete']) {
                 $queryBuilder->addSelect($GLOBALS['TCA'][$tableName]['ctrl']['delete']);
             }
             if (!$this->genTree_traverseDeleted) {
                 $queryBuilder->getRestrictions()->add(DeletedRestriction::class);
             }
             $result = $queryBuilder->execute();
             $count = $result->rowCount();
             if ($count) {
                 if ($echoLevel == 2) {
                     echo LF . '	\\-' . $tableName . ' (' . $count . ')';
                 }
             }
             while ($rowSub = $result->fetch()) {
                 if ($echoLevel == 3) {
                     echo LF . '	\\-' . $tableName . ':' . $rowSub['uid'];
                 }
                 // If the rootID represents an "element" or "page" version type, we must check if the record from this table is allowed to belong to this:
                 if ($versionSwapmode) {
                     // This is illegal records under a versioned page - therefore not registered in $this->recStats['all'] so they should be orphaned:
                     $this->recStats['illegal_record_under_versioned_page'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                     if ($echoLevel > 1) {
                         echo LF . '		ERROR! Illegal record (' . $tableName . ':' . $rowSub['uid'] . ') under versioned page!';
                     }
                 } else {
                     $this->recStats['all'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                     // Register deleted:
                     if ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] && $rowSub[$GLOBALS['TCA'][$tableName]['ctrl']['delete']]) {
                         $this->recStats['deleted'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel == 3) {
                             echo ' (DELETED)';
                         }
                     }
                     // Check location of records regarding tree root:
                     if (!$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] && $rootID == 0) {
                         $this->recStats['misplaced_at_rootlevel'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel > 1) {
                             echo LF . '		ERROR! Misplaced record (' . $tableName . ':' . $rowSub['uid'] . ') on rootlevel!';
                         }
                     }
                     if ($GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] == 1 && $rootID > 0) {
                         $this->recStats['misplaced_inside_tree'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel > 1) {
                             echo LF . '		ERROR! Misplaced record (' . $tableName . ':' . $rowSub['uid'] . ') inside page tree!';
                         }
                     }
                     // Traverse plugins:
                     if ($callBack) {
                         $this->{$callBack}($tableName, $rowSub['uid'], $echoLevel, $versionSwapmode, $rootIsVersion);
                     }
                     // Add any versions of those records:
                     if ($this->genTree_traverseVersions) {
                         $versions = BackendUtility::selectVersionsOfRecord($tableName, $rowSub['uid'], 'uid,t3ver_wsid,t3ver_count' . ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] : ''), null, true);
                         if (is_array($versions)) {
                             foreach ($versions as $verRec) {
                                 if (!$verRec['_CURRENT_VERSION']) {
                                     if ($echoLevel == 3) {
                                         echo LF . '		\\-[#OFFLINE VERSION: WS#' . $verRec['t3ver_wsid'] . '/Cnt:' . $verRec['t3ver_count'] . '] ' . $tableName . ':' . $verRec['uid'] . ')';
                                     }
                                     $this->recStats['all'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     // Register deleted:
                                     if ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] && $verRec[$GLOBALS['TCA'][$tableName]['ctrl']['delete']]) {
                                         $this->recStats['deleted'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel == 3) {
                                             echo ' (DELETED)';
                                         }
                                     }
                                     // Register version:
                                     $this->recStats['versions'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     if ($verRec['t3ver_count'] >= 1 && $verRec['t3ver_wsid'] == 0) {
                                         // Only register published versions in LIVE workspace (published versions in draft workspaces are allowed)
                                         $this->recStats['versions_published'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel == 3) {
                                             echo ' (PUBLISHED)';
                                         }
                                     }
                                     if ($verRec['t3ver_wsid'] == 0) {
                                         $this->recStats['versions_liveWS'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     }
                                     if (!isset($this->workspaceIndex[$verRec['t3ver_wsid']])) {
                                         $this->recStats['versions_lost_workspace'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel > 1) {
                                             echo LF . '		ERROR! Version (' . $tableName . ':' . $verRec['uid'] . ') belongs to non-existing workspace (' . $verRec['t3ver_wsid'] . ')!';
                                         }
                                     }
                                     // In case we are inside a versioned branch, there should not exists versions inside that "branch".
                                     if ($versionSwapmode) {
                                         $this->recStats['versions_inside_versioned_page'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel > 1) {
                                             echo LF . '		ERROR! This version (' . $tableName . ':' . $verRec['uid'] . ') is inside an already versioned page or branch!';
                                         }
                                     }
                                     // Traverse plugins:
                                     if ($callBack) {
                                         $this->{$callBack}($tableName, $verRec['uid'], $echoLevel, $versionSwapmode, $rootIsVersion);
                                     }
                                 }
                             }
                         }
                         unset($versions);
                     }
                 }
             }
         }
     }
     unset($resSub);
     unset($rowSub);
     // Find subpages to root ID and traverse (only when rootID is not a version or is a branch-version):
     if ($depth > 0) {
         $depth--;
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
         $queryBuilder->getRestrictions()->removeAll();
         if (!$this->genTree_traverseDeleted) {
             $queryBuilder->getRestrictions()->add(DeletedRestriction::class);
         }
         $queryBuilder->select('uid')->from('pages')->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($rootID, \PDO::PARAM_INT)))->orderBy('sorting');
         $result = $queryBuilder->execute();
         while ($row = $result->fetch()) {
             $this->genTree_traverse($row['uid'], $depth, $echoLevel, $callBack, $versionSwapmode, 0, $accumulatedPath);
         }
     }
     // Add any versions of pages
     if ($rootID > 0 && $this->genTree_traverseVersions) {
         $versions = BackendUtility::selectVersionsOfRecord('pages', $rootID, 'uid,t3ver_oid,t3ver_wsid,t3ver_count', null, true);
         if (is_array($versions)) {
             foreach ($versions as $verRec) {
                 if (!$verRec['_CURRENT_VERSION']) {
                     $this->genTree_traverse($verRec['uid'], $depth, $echoLevel, $callBack, true, $versionSwapmode ? 2 : 1, $accumulatedPath . ' [#OFFLINE VERSION: WS#' . $verRec['t3ver_wsid'] . '/Cnt:' . $verRec['t3ver_count'] . ']');
                 }
             }
         }
     }
 }
 /**
  * Recursive traversal of page tree:
  *
  * @param integer $rootID Page root id (must be online, valid page record - or zero for page tree root)
  * @param integer $depth Depth
  * @param integer $echoLevel Echo Level
  * @param string $callBack Call back function (from this class or subclass)
  * @param string $versionSwapmode DON'T set from outside, internal. (indicates we are inside a version of a page) - will be "SWAPMODE:-1" or empty
  * @param integer $rootIsVersion DON'T set from outside, internal. (1: Indicates that rootID is a version of a page, 2: ...that it is even a version of a version (which triggers a warning!)
  * @param string $accumulatedPath Internal string that accumulates the path
  * @return void
  * @access private
  * @todo $versionSwapmode needs to be cleaned up, since page and branch version (0, 1) does not exist anymore
  * @todo Define visibility
  */
 public function genTree_traverse($rootID, $depth, $echoLevel = 0, $callBack = '', $versionSwapmode = '', $rootIsVersion = 0, $accumulatedPath = '')
 {
     // Register page:
     $this->recStats['all']['pages'][$rootID] = $rootID;
     $pageRecord = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordRaw('pages', 'uid=' . intval($rootID), 'deleted,title,t3ver_count,t3ver_wsid');
     $accumulatedPath .= '/' . $pageRecord['title'];
     // Register if page is deleted:
     if ($pageRecord['deleted']) {
         $this->recStats['deleted']['pages'][$rootID] = $rootID;
     }
     // If rootIsVersion is set it means that the input rootID is that of a version of a page. See below where the recursive call is made.
     if ($rootIsVersion) {
         $this->recStats['versions']['pages'][$rootID] = $rootID;
         // If it has been published and is in archive now...
         if ($pageRecord['t3ver_count'] >= 1 && $pageRecord['t3ver_wsid'] == 0) {
             $this->recStats['versions_published']['pages'][$rootID] = $rootID;
         }
         // If it has been published and is in archive now...
         if ($pageRecord['t3ver_wsid'] == 0) {
             $this->recStats['versions_liveWS']['pages'][$rootID] = $rootID;
         }
         // If it doesn't belong to a workspace...
         if (!isset($this->workspaceIndex[$pageRecord['t3ver_wsid']])) {
             $this->recStats['versions_lost_workspace']['pages'][$rootID] = $rootID;
         }
         // In case the rootID is a version inside a versioned page
         if ($rootIsVersion == 2) {
             $this->recStats['versions_inside_versioned_page']['pages'][$rootID] = $rootID;
         }
     }
     if ($echoLevel > 0) {
         echo LF . $accumulatedPath . ' [' . $rootID . ']' . ($pageRecord['deleted'] ? ' (DELETED)' : '') . ($this->recStats['versions_published']['pages'][$rootID] ? ' (PUBLISHED)' : '');
     }
     if ($echoLevel > 1 && $this->recStats['versions_lost_workspace']['pages'][$rootID]) {
         echo LF . '	ERROR! This version belongs to non-existing workspace (' . $pageRecord['t3ver_wsid'] . ')!';
     }
     if ($echoLevel > 1 && $this->recStats['versions_inside_versioned_page']['pages'][$rootID]) {
         echo LF . '	WARNING! This version is inside an already versioned page or branch!';
     }
     // Call back:
     if ($callBack) {
         $this->{$callBack}('pages', $rootID, $echoLevel, $versionSwapmode, $rootIsVersion);
     }
     $pt3 = \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds();
     // Traverse tables of records that belongs to page:
     foreach ($GLOBALS['TCA'] as $tableName => $cfg) {
         if ($tableName != 'pages') {
             // Select all records belonging to page:
             $pt4 = \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds();
             $resSub = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid' . ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] : ''), $tableName, 'pid=' . intval($rootID) . ($this->genTree_traverseDeleted ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($tableName)));
             $this->performanceStatistics['genTree_traverse():TraverseTables:']['MySQL']['(ALL)'] += \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds() - $pt4;
             $this->performanceStatistics['genTree_traverse():TraverseTables:']['MySQL'][$tableName] += \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds() - $pt4;
             $pt5 = \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds();
             $count = $GLOBALS['TYPO3_DB']->sql_num_rows($resSub);
             if ($count) {
                 if ($echoLevel == 2) {
                     echo LF . '	\\-' . $tableName . ' (' . $count . ')';
                 }
             }
             while ($rowSub = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($resSub)) {
                 if ($echoLevel == 3) {
                     echo LF . '	\\-' . $tableName . ':' . $rowSub['uid'];
                 }
                 // If the rootID represents an "element" or "page" version type, we must check if the record from this table is allowed to belong to this:
                 if ($versionSwapmode == 'SWAPMODE:-1' || $versionSwapmode == 'SWAPMODE:0' && !$GLOBALS['TCA'][$tableName]['ctrl']['versioning_followPages']) {
                     // This is illegal records under a versioned page - therefore not registered in $this->recStats['all'] so they should be orphaned:
                     $this->recStats['illegal_record_under_versioned_page'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                     if ($echoLevel > 1) {
                         echo LF . '		ERROR! Illegal record (' . $tableName . ':' . $rowSub['uid'] . ') under versioned page!';
                     }
                 } else {
                     $this->recStats['all'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                     // Register deleted:
                     if ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] && $rowSub[$GLOBALS['TCA'][$tableName]['ctrl']['delete']]) {
                         $this->recStats['deleted'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel == 3) {
                             echo ' (DELETED)';
                         }
                     }
                     // Check location of records regarding tree root:
                     if (!$GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] && $rootID == 0) {
                         $this->recStats['misplaced_at_rootlevel'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel > 1) {
                             echo LF . '		ERROR! Misplaced record (' . $tableName . ':' . $rowSub['uid'] . ') on rootlevel!';
                         }
                     }
                     if ($GLOBALS['TCA'][$tableName]['ctrl']['rootLevel'] == 1 && $rootID > 0) {
                         $this->recStats['misplaced_inside_tree'][$tableName][$rowSub['uid']] = $rowSub['uid'];
                         if ($echoLevel > 1) {
                             echo LF . '		ERROR! Misplaced record (' . $tableName . ':' . $rowSub['uid'] . ') inside page tree!';
                         }
                     }
                     // Traverse plugins:
                     if ($callBack) {
                         $this->{$callBack}($tableName, $rowSub['uid'], $echoLevel, $versionSwapmode, $rootIsVersion);
                     }
                     // Add any versions of those records:
                     if ($this->genTree_traverseVersions) {
                         $versions = \TYPO3\CMS\Backend\Utility\BackendUtility::selectVersionsOfRecord($tableName, $rowSub['uid'], 'uid,t3ver_wsid,t3ver_count' . ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] ? ',' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] : ''), 0, TRUE);
                         if (is_array($versions)) {
                             foreach ($versions as $verRec) {
                                 if (!$verRec['_CURRENT_VERSION']) {
                                     if ($echoLevel == 3) {
                                         echo LF . '		\\-[#OFFLINE VERSION: WS#' . $verRec['t3ver_wsid'] . '/Cnt:' . $verRec['t3ver_count'] . '] ' . $tableName . ':' . $verRec['uid'] . ')';
                                     }
                                     $this->recStats['all'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     // Register deleted:
                                     if ($GLOBALS['TCA'][$tableName]['ctrl']['delete'] && $verRec[$GLOBALS['TCA'][$tableName]['ctrl']['delete']]) {
                                         $this->recStats['deleted'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel == 3) {
                                             echo ' (DELETED)';
                                         }
                                     }
                                     // Register version:
                                     $this->recStats['versions'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     if ($verRec['t3ver_count'] >= 1 && $verRec['t3ver_wsid'] == 0) {
                                         // Only register published versions in LIVE workspace (published versions in draft workspaces are allowed)
                                         $this->recStats['versions_published'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel == 3) {
                                             echo ' (PUBLISHED)';
                                         }
                                     }
                                     if ($verRec['t3ver_wsid'] == 0) {
                                         $this->recStats['versions_liveWS'][$tableName][$verRec['uid']] = $verRec['uid'];
                                     }
                                     if (!isset($this->workspaceIndex[$verRec['t3ver_wsid']])) {
                                         $this->recStats['versions_lost_workspace'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel > 1) {
                                             echo LF . '		ERROR! Version (' . $tableName . ':' . $verRec['uid'] . ') belongs to non-existing workspace (' . $verRec['t3ver_wsid'] . ')!';
                                         }
                                     }
                                     // In case we are inside a versioned branch, there should not exists versions inside that "branch".
                                     if ($versionSwapmode) {
                                         $this->recStats['versions_inside_versioned_page'][$tableName][$verRec['uid']] = $verRec['uid'];
                                         if ($echoLevel > 1) {
                                             echo LF . '		ERROR! This version (' . $tableName . ':' . $verRec['uid'] . ') is inside an already versioned page or branch!';
                                         }
                                     }
                                     // Traverse plugins:
                                     if ($callBack) {
                                         $this->{$callBack}($tableName, $verRec['uid'], $echoLevel, $versionSwapmode, $rootIsVersion);
                                     }
                                 }
                             }
                         }
                         unset($versions);
                     }
                 }
             }
             $this->performanceStatistics['genTree_traverse():TraverseTables:']['Proc']['(ALL)'] += \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds() - $pt5;
             $this->performanceStatistics['genTree_traverse():TraverseTables:']['Proc'][$tableName] += \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds() - $pt5;
         }
     }
     unset($resSub);
     unset($rowSub);
     $this->performanceStatistics['genTree_traverse():TraverseTables'] += \TYPO3\CMS\Core\Utility\GeneralUtility::milliseconds() - $pt3;
     // Find subpages to root ID and traverse (only when rootID is not a version or is a branch-version):
     if (!$versionSwapmode || $versionSwapmode == 'SWAPMODE:1') {
         if ($depth > 0) {
             $depth--;
             $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'pages', 'pid=' . intval($rootID) . ($this->genTree_traverseDeleted ? '' : \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('pages')), '', 'sorting');
             while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
                 $this->genTree_traverse($row['uid'], $depth, $echoLevel, $callBack, $versionSwapmode, 0, $accumulatedPath);
             }
         }
         // Add any versions of pages
         if ($rootID > 0 && $this->genTree_traverseVersions) {
             $versions = \TYPO3\CMS\Backend\Utility\BackendUtility::selectVersionsOfRecord('pages', $rootID, 'uid,t3ver_oid,t3ver_wsid,t3ver_count', 0, TRUE);
             if (is_array($versions)) {
                 foreach ($versions as $verRec) {
                     if (!$verRec['_CURRENT_VERSION']) {
                         $this->genTree_traverse($verRec['uid'], $depth, $echoLevel, $callBack, 'SWAPMODE:-1', $versionSwapmode ? 2 : 1, $accumulatedPath . ' [#OFFLINE VERSION: WS#' . $verRec['t3ver_wsid'] . '/Cnt:' . $verRec['t3ver_count'] . ']');
                     }
                 }
             }
         }
     }
 }
Exemple #16
0
 function deleteReminder($eventUid)
 {
     if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('scheduler')) {
         $eventRow = BackendUtility::getRecordRaw('tx_cal_fe_user_event_monitor_mm', 'uid_local=' . $eventUid);
         $taskId = $eventRow['schedulerId'];
         if ($taskId > 0) {
             $scheduler = new \TYPO3\CMS\Scheduler\Scheduler();
             try {
                 $task = $scheduler->fetchTask($taskId);
                 $scheduler->removeTask($task);
             } catch (OutOfBoundsException $e) {
             }
         }
     } else {
         if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('gabriel')) {
             $monitoringUID = 'tx_cal_fe_user_event_monitor_mm:' . $eventUid;
             $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_gabriel', ' crid="' . $eventUid . '"');
         }
     }
 }
Exemple #17
0
 /**
  * Call this function to update the sys_refindex table for a record (even one just deleted)
  * NOTICE: Currently, references updated for a deleted-flagged record will not include those from within flexform fields in some cases where the data structure is defined by another record since the resolving process ignores deleted records! This will also result in bad cleaning up in tcemain I think... Anyway, thats the story of flexforms; as long as the DS can change, lots of references can get lost in no time.
  *
  * @param string $table Table name
  * @param integer $uid UID of record
  * @param boolean $testOnly If set, nothing will be written to the index but the result value will still report statistics on what is added, deleted and kept. Can be used for mere analysis.
  * @return array Array with statistics about how many index records were added, deleted and not altered plus the complete reference set for the record.
  * @todo Define visibility
  */
 public function updateRefIndexTable($table, $uid, $testOnly = FALSE)
 {
     // First, secure that the index table is not updated with workspace tainted relations:
     $this->WSOL = FALSE;
     // Init:
     $result = array('keptNodes' => 0, 'deletedNodes' => 0, 'addedNodes' => 0);
     // Get current index from Database:
     $currentRels = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_refindex', 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($table, 'sys_refindex') . ' AND recuid=' . (int) $uid, '', '', '', 'hash');
     // First, test to see if the record exists (including deleted-flagged)
     if (BackendUtility::getRecordRaw($table, 'uid=' . (int) $uid, 'uid')) {
         // Then, get relations:
         $relations = $this->generateRefIndexData($table, $uid);
         if (is_array($relations)) {
             // Traverse the generated index:
             foreach ($relations as $k => $datRec) {
                 $relations[$k]['hash'] = md5(implode('///', $relations[$k]) . '///' . $this->hashVersion);
                 // First, check if already indexed and if so, unset that row (so in the end we know which rows to remove!)
                 if (isset($currentRels[$relations[$k]['hash']])) {
                     unset($currentRels[$relations[$k]['hash']]);
                     $result['keptNodes']++;
                     $relations[$k]['_ACTION'] = 'KEPT';
                 } else {
                     // If new, add it:
                     if (!$testOnly) {
                         $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_refindex', $relations[$k]);
                     }
                     $result['addedNodes']++;
                     $relations[$k]['_ACTION'] = 'ADDED';
                 }
             }
             $result['relations'] = $relations;
         } else {
             return FALSE;
         }
     }
     // If any old are left, remove them:
     if (count($currentRels)) {
         $hashList = array_keys($currentRels);
         if (count($hashList)) {
             $result['deletedNodes'] = count($hashList);
             $result['deletedNodes_hashList'] = implode(',', $hashList);
             if (!$testOnly) {
                 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_refindex', 'hash IN (' . implode(',', $GLOBALS['TYPO3_DB']->fullQuoteArray($hashList, 'sys_refindex')) . ')');
             }
         }
     }
     return $result;
 }
Exemple #18
0
    /**
     * Creates the listing of records from a single table
     *
     * @param string $table Table name
     * @param int $id Page id
     * @param string $rowList List of fields to show in the listing. Pseudo fields will be added including the record header.
     * @throws \UnexpectedValueException
     * @return string HTML table with the listing for the record.
     */
    public function getTable($table, $id, $rowList = '')
    {
        $rowListArray = GeneralUtility::trimExplode(',', $rowList, true);
        // if no columns have been specified, show description (if configured)
        if (!empty($GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']) && empty($rowListArray)) {
            array_push($rowListArray, $GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']);
        }
        $backendUser = $this->getBackendUserAuthentication();
        $lang = $this->getLanguageService();
        $db = $this->getDatabaseConnection();
        // Init
        $addWhere = '';
        $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label'];
        $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail'];
        $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerTable'];
        $tableCollapsed = (bool) $this->tablesCollapsed[$table];
        // prepare space icon
        $this->spaceIcon = '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>';
        // Cleaning rowlist for duplicates and place the $titleCol as the first column always!
        $this->fieldArray = array();
        // title Column
        // Add title column
        $this->fieldArray[] = $titleCol;
        // Control-Panel
        if (!GeneralUtility::inList($rowList, '_CONTROL_')) {
            $this->fieldArray[] = '_CONTROL_';
        }
        // Clipboard
        if ($this->showClipboard) {
            $this->fieldArray[] = '_CLIPBOARD_';
        }
        // Ref
        if (!$this->dontShowClipControlPanels) {
            $this->fieldArray[] = '_REF_';
        }
        // Path
        if ($this->searchLevels) {
            $this->fieldArray[] = '_PATH_';
        }
        // Localization
        if ($this->localizationView && $l10nEnabled) {
            $this->fieldArray[] = '_LOCALIZATION_';
            $this->fieldArray[] = '_LOCALIZATION_b';
            $addWhere .= ' AND (
				' . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '<=0
				OR
				' . $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] . ' = 0
			)';
        }
        // Cleaning up:
        $this->fieldArray = array_unique(array_merge($this->fieldArray, $rowListArray));
        if ($this->noControlPanels) {
            $tempArray = array_flip($this->fieldArray);
            unset($tempArray['_CONTROL_']);
            unset($tempArray['_CLIPBOARD_']);
            $this->fieldArray = array_keys($tempArray);
        }
        // Creating the list of fields to include in the SQL query:
        $selectFields = $this->fieldArray;
        $selectFields[] = 'uid';
        $selectFields[] = 'pid';
        // adding column for thumbnails
        if ($thumbsCol) {
            $selectFields[] = $thumbsCol;
        }
        if ($table == 'pages') {
            $selectFields[] = 'module';
            $selectFields[] = 'extendToSubpages';
            $selectFields[] = 'nav_hide';
            $selectFields[] = 'doktype';
            $selectFields[] = 'shortcut';
            $selectFields[] = 'shortcut_mode';
            $selectFields[] = 'mount_pid';
        }
        if (is_array($GLOBALS['TCA'][$table]['ctrl']['enablecolumns'])) {
            $selectFields = array_merge($selectFields, $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']);
        }
        foreach (array('type', 'typeicon_column', 'editlock') as $field) {
            if ($GLOBALS['TCA'][$table]['ctrl'][$field]) {
                $selectFields[] = $GLOBALS['TCA'][$table]['ctrl'][$field];
            }
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS']) {
            $selectFields[] = 't3ver_id';
            $selectFields[] = 't3ver_state';
            $selectFields[] = 't3ver_wsid';
        }
        if ($l10nEnabled) {
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['languageField'];
            $selectFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
        }
        if ($GLOBALS['TCA'][$table]['ctrl']['label_alt']) {
            $selectFields = array_merge($selectFields, GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['ctrl']['label_alt'], true));
        }
        // Unique list!
        $selectFields = array_unique($selectFields);
        $fieldListFields = $this->makeFieldList($table, 1);
        if (empty($fieldListFields) && $GLOBALS['TYPO3_CONF_VARS']['BE']['debug']) {
            $message = sprintf($lang->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessage', true), $table, $table);
            $messageTitle = $lang->sL('LLL:EXT:lang/locallang_mod_web_list.xlf:missingTcaColumnsMessageTitle', true);
            /** @var FlashMessage $flashMessage */
            $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $message, $messageTitle, FlashMessage::WARNING, true);
            /** @var $flashMessageService FlashMessageService */
            $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
            /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
            $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
            $defaultFlashMessageQueue->enqueue($flashMessage);
        }
        // Making sure that the fields in the field-list ARE in the field-list from TCA!
        $selectFields = array_intersect($selectFields, $fieldListFields);
        // Implode it into a list of fields for the SQL-statement.
        $selFieldList = implode(',', $selectFields);
        $this->selFieldList = $selFieldList;
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'])) {
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.db_list_extra.inc']['getTable'] as $classData) {
                $hookObject = GeneralUtility::getUserObj($classData);
                if (!$hookObject instanceof RecordListGetTableHookInterface) {
                    throw new \UnexpectedValueException('$hookObject must implement interface ' . RecordListGetTableHookInterface::class, 1195114460);
                }
                $hookObject->getDBlistQuery($table, $id, $addWhere, $selFieldList, $this);
            }
        }
        // Create the SQL query for selecting the elements in the listing:
        // do not do paging when outputting as CSV
        if ($this->csvOutput) {
            $this->iLimit = 0;
        }
        if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
            // Get the two previous rows for sorting if displaying page > 1
            $this->firstElementNumber = $this->firstElementNumber - 2;
            $this->iLimit = $this->iLimit + 2;
            // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList)
            $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList);
            $this->firstElementNumber = $this->firstElementNumber + 2;
            $this->iLimit = $this->iLimit - 2;
        } else {
            // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList)
            $queryParts = $this->makeQueryArray($table, $id, $addWhere, $selFieldList);
        }
        // Finding the total amount of records on the page
        // (API function from TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList)
        $this->setTotalItems($queryParts);
        // Init:
        $dbCount = 0;
        $out = '';
        $tableHeader = '';
        $result = null;
        $listOnlyInSingleTableMode = $this->listOnlyInSingleTableMode && !$this->table;
        // If the count query returned any number of records, we perform the real query,
        // selecting records.
        if ($this->totalItems) {
            // Fetch records only if not in single table mode
            if ($listOnlyInSingleTableMode) {
                $dbCount = $this->totalItems;
            } else {
                // Set the showLimit to the number of records when outputting as CSV
                if ($this->csvOutput) {
                    $this->showLimit = $this->totalItems;
                    $this->iLimit = $this->totalItems;
                }
                $result = $db->exec_SELECT_queryArray($queryParts);
                $dbCount = $db->sql_num_rows($result);
            }
        }
        // If any records was selected, render the list:
        if ($dbCount) {
            $tableTitle = $lang->sL($GLOBALS['TCA'][$table]['ctrl']['title'], true);
            if ($tableTitle === '') {
                $tableTitle = $table;
            }
            // Header line is drawn
            $theData = array();
            if ($this->disableSingleTableView) {
                $theData[$titleCol] = '<span class="c-table">' . BackendUtility::wrapInHelp($table, '', $tableTitle) . '</span> (<span class="t3js-table-total-items">' . $this->totalItems . '</span>)';
            } else {
                $icon = $this->table ? '<span title="' . $lang->getLL('contractView', true) . '">' . $this->iconFactory->getIcon('actions-view-table-collapse', Icon::SIZE_SMALL)->render() . '</span>' : '<span title="' . $lang->getLL('expandView', true) . '">' . $this->iconFactory->getIcon('actions-view-table-expand', Icon::SIZE_SMALL)->render() . '</span>';
                $theData[$titleCol] = $this->linkWrapTable($table, $tableTitle . ' (<span class="t3js-table-total-items">' . $this->totalItems . '</span>) ' . $icon);
            }
            if ($listOnlyInSingleTableMode) {
                $tableHeader .= BackendUtility::wrapInHelp($table, '', $theData[$titleCol]);
            } else {
                // Render collapse button if in multi table mode
                $collapseIcon = '';
                if (!$this->table) {
                    $href = htmlspecialchars($this->listURL() . '&collapse[' . $table . ']=' . ($tableCollapsed ? '0' : '1'));
                    $title = $tableCollapsed ? $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.expandTable', true) : $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.collapseTable', true);
                    $icon = '<span class="collapseIcon">' . $this->iconFactory->getIcon($tableCollapsed ? 'actions-view-list-expand' : 'actions-view-list-collapse', Icon::SIZE_SMALL)->render() . '</span>';
                    $collapseIcon = '<a href="' . $href . '" title="' . $title . '" class="pull-right t3js-toggle-recordlist" data-table="' . htmlspecialchars($table) . '" data-toggle="collapse" data-target="#recordlist-' . htmlspecialchars($table) . '">' . $icon . '</a>';
                }
                $tableHeader .= $theData[$titleCol] . $collapseIcon;
            }
            // Render table rows only if in multi table view or if in single table view
            $rowOutput = '';
            if (!$listOnlyInSingleTableMode || $this->table) {
                // Fixing an order table for sortby tables
                $this->currentTable = array();
                $currentIdList = array();
                $doSort = $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField;
                $prevUid = 0;
                $prevPrevUid = 0;
                // Get first two rows and initialize prevPrevUid and prevUid if on page > 1
                if ($this->firstElementNumber > 2 && $this->iLimit > 0) {
                    $row = $db->sql_fetch_assoc($result);
                    $prevPrevUid = -(int) $row['uid'];
                    $row = $db->sql_fetch_assoc($result);
                    $prevUid = $row['uid'];
                }
                $accRows = array();
                // Accumulate rows here
                while ($row = $db->sql_fetch_assoc($result)) {
                    if (!$this->isRowListingConditionFulfilled($table, $row)) {
                        continue;
                    }
                    // In offline workspace, look for alternative record:
                    BackendUtility::workspaceOL($table, $row, $backendUser->workspace, true);
                    if (is_array($row)) {
                        $accRows[] = $row;
                        $currentIdList[] = $row['uid'];
                        if ($doSort) {
                            if ($prevUid) {
                                $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
                                $this->currentTable['next'][$prevUid] = '-' . $row['uid'];
                                $this->currentTable['prevUid'][$row['uid']] = $prevUid;
                            }
                            $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
                            $prevUid = $row['uid'];
                        }
                    }
                }
                $db->sql_free_result($result);
                $this->totalRowCount = count($accRows);
                // CSV initiated
                if ($this->csvOutput) {
                    $this->initCSV();
                }
                // Render items:
                $this->CBnames = array();
                $this->duplicateStack = array();
                $this->eCounter = $this->firstElementNumber;
                $cc = 0;
                foreach ($accRows as $row) {
                    // Render item row if counter < limit
                    if ($cc < $this->iLimit) {
                        $cc++;
                        $this->translations = false;
                        $rowOutput .= $this->renderListRow($table, $row, $cc, $titleCol, $thumbsCol);
                        // If localization view is enabled it means that the selected records are
                        // either default or All language and here we will not select translations
                        // which point to the main record:
                        if ($this->localizationView && $l10nEnabled) {
                            // For each available translation, render the record:
                            if (is_array($this->translations)) {
                                foreach ($this->translations as $lRow) {
                                    // $lRow isn't always what we want - if record was moved we've to work with the
                                    // placeholder records otherwise the list is messed up a bit
                                    if ($row['_MOVE_PLH_uid'] && $row['_MOVE_PLH_pid']) {
                                        $where = 't3ver_move_id="' . (int) $lRow['uid'] . '" AND pid="' . $row['_MOVE_PLH_pid'] . '" AND t3ver_wsid=' . $row['t3ver_wsid'] . BackendUtility::deleteClause($table);
                                        $tmpRow = BackendUtility::getRecordRaw($table, $where, $selFieldList);
                                        $lRow = is_array($tmpRow) ? $tmpRow : $lRow;
                                    }
                                    // In offline workspace, look for alternative record:
                                    BackendUtility::workspaceOL($table, $lRow, $backendUser->workspace, true);
                                    if (is_array($lRow) && $backendUser->checkLanguageAccess($lRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) {
                                        $currentIdList[] = $lRow['uid'];
                                        $rowOutput .= $this->renderListRow($table, $lRow, $cc, $titleCol, $thumbsCol, 18);
                                    }
                                }
                            }
                        }
                    }
                    // Counter of total rows incremented:
                    $this->eCounter++;
                }
                // Record navigation is added to the beginning and end of the table if in single
                // table mode
                if ($this->table) {
                    $rowOutput = $this->renderListNavigation('top') . $rowOutput . $this->renderListNavigation('bottom');
                } else {
                    // Show that there are more records than shown
                    if ($this->totalItems > $this->itemsLimitPerTable) {
                        $countOnFirstPage = $this->totalItems > $this->itemsLimitSingleTable ? $this->itemsLimitSingleTable : $this->totalItems;
                        $hasMore = $this->totalItems > $this->itemsLimitSingleTable;
                        $colspan = $this->showIcon ? count($this->fieldArray) + 1 : count($this->fieldArray);
                        $rowOutput .= '<tr><td colspan="' . $colspan . '">
								<a href="' . htmlspecialchars($this->listURL() . '&table=' . rawurlencode($table)) . '" class="btn btn-default">' . '<span class="t3-icon fa fa-chevron-down"></span> <i>[1 - ' . $countOnFirstPage . ($hasMore ? '+' : '') . ']</i></a>
								</td></tr>';
                    }
                }
                // The header row for the table is now created:
                $out .= $this->renderListHeader($table, $currentIdList);
            }
            $collapseClass = $tableCollapsed && !$this->table ? 'collapse' : 'collapse in';
            $dataState = $tableCollapsed && !$this->table ? 'collapsed' : 'expanded';
            // The list of records is added after the header:
            $out .= $rowOutput;
            // ... and it is all wrapped in a table:
            $out = '



			<!--
				DB listing of elements:	"' . htmlspecialchars($table) . '"
			-->
				<div class="panel panel-space panel-default">
					<div class="panel-heading">
					' . $tableHeader . '
					</div>
					<div class="table-fit ' . $collapseClass . '" id="recordlist-' . htmlspecialchars($table) . '" data-state="' . $dataState . '">
						<table data-table="' . htmlspecialchars($table) . '" class="table table-striped table-hover' . ($listOnlyInSingleTableMode ? ' typo3-dblist-overview' : '') . '">
							' . $out . '
						</table>
					</div>
				</div>
			';
            // Output csv if...
            // This ends the page with exit.
            if ($this->csvOutput) {
                $this->outputCSV($table);
            }
        }
        // Return content:
        return $out;
    }
Exemple #19
0
 /**
  * Checks if record can be selected based on given permission criteria
  *
  * @param string $table Record table name
  * @param integer $id Record UID
  * @param mixed $perms Permission restrictions to observe: Either an integer that will be bitwise AND'ed or a string, which points to a key in the ->pMap array
  * @return boolean Returns TRUE if the record given by $table, $id and $perms can be selected
  * @todo Define visibility
  */
 public function doesRecordExist($table, $id, $perms)
 {
     if ($this->bypassAccessCheckForRecords) {
         return is_array(\TYPO3\CMS\Backend\Utility\BackendUtility::getRecordRaw($table, 'uid=' . intval($id), 'uid'));
     }
     $res = 0;
     $id = intval($id);
     // Processing the incoming $perms (from possible string to integer that can be AND'ed)
     if (!\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($perms)) {
         if ($table != 'pages') {
             switch ($perms) {
                 case 'edit':
                 case 'delete':
                 case 'new':
                     // This holds it all in case the record is not page!!
                     $perms = 'editcontent';
                     break;
             }
         }
         $perms = intval($this->pMap[$perms]);
     } else {
         $perms = intval($perms);
     }
     if (!$perms) {
         throw new \RuntimeException('Internal ERROR: no permissions to check for non-admin user', 1270853920);
     }
     // For all tables: Check if record exists:
     if (is_array($GLOBALS['TCA'][$table]) && $id > 0 && ($this->isRecordInWebMount($table, $id) || $this->admin)) {
         if ($table != 'pages') {
             // Find record without checking page:
             $mres = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,pid', $table, 'uid=' . intval($id) . $this->deleteClause($table));
             // THIS SHOULD CHECK FOR editlock I think!
             $output = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
             \TYPO3\CMS\Backend\Utility\BackendUtility::fixVersioningPid($table, $output, TRUE);
             // If record found, check page as well:
             if (is_array($output)) {
                 // Looking up the page for record:
                 $mres = $this->doesRecordExist_pageLookUp($output['pid'], $perms);
                 $pageRec = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($mres);
                 // Return TRUE if either a page was found OR if the PID is zero AND the user is ADMIN (in which case the record is at root-level):
                 if (is_array($pageRec) || !$output['pid'] && $this->admin) {
                     return TRUE;
                 }
             }
             return FALSE;
         } else {
             $mres = $this->doesRecordExist_pageLookUp($id, $perms);
             return $GLOBALS['TYPO3_DB']->sql_num_rows($mres);
         }
     }
 }
Exemple #20
0
 /**
  * exportEXCELXML which is called over cli
  *
  * @param integer $l10ncfg ID of the configuration to load
  * @param integer $tlang ID of the language to translate to
  * @return string An error message in case of failure
  */
 function exportEXCELXML($l10ncfg, $tlang)
 {
     global $lang;
     $error = '';
     // Load the configuration
     $this->loadExtConf();
     /** @var $l10nmgrCfgObj L10nConfiguration */
     $l10nmgrCfgObj = GeneralUtility::makeInstance(L10nConfiguration::class);
     $l10nmgrCfgObj->load($l10ncfg);
     if ($l10nmgrCfgObj->isLoaded()) {
         /** @var $l10nmgrGetXML ExcelXmlView */
         $l10nmgrGetXML = GeneralUtility::makeInstance(ExcelXmlView::class, $l10nmgrCfgObj, $tlang);
         // Check if sourceLangStaticId is set in configuration and set setForcedSourceLanguage to this value
         if ($l10nmgrCfgObj->getData('sourceLangStaticId') && ExtensionManagementUtility::isLoaded('static_info_tables')) {
             $staticLangArr = BackendUtility::getRecordRaw('sys_language', 'static_lang_isocode = ' . $l10nmgrCfgObj->getData('sourceLangStaticId'), 'uid');
             if (is_array($staticLangArr) && $staticLangArr['uid'] > 0) {
                 $forceLanguage = $staticLangArr['uid'];
                 $l10nmgrGetXML->setForcedSourceLanguage($forceLanguage);
             }
         }
         $onlyChanged = isset($this->cli_args['--updated']) ? $this->cli_args['--updated'][0] : 'FALSE';
         if ($onlyChanged === 'TRUE') {
             $l10nmgrGetXML->setModeOnlyChanged();
         }
         $hidden = isset($this->cli_args['--hidden']) ? $this->cli_args['--hidden'][0] : 'FALSE';
         if ($hidden === 'TRUE') {
             $GLOBALS['BE_USER']->uc['moduleData']['xMOD_tx_l10nmgr_cm1']['noHidden'] = true;
             $l10nmgrGetXML->setModeNoHidden();
         }
         // If the check for already exported content is enabled, run the ckeck.
         $checkExportsCli = isset($this->cli_args['--check-exports']) ? (bool) $this->cli_args['--check-exports'][0] : false;
         $checkExports = $l10nmgrGetXML->checkExports();
         if ($checkExportsCli === true && $checkExports == false) {
             $this->cli_echo($lang->getLL('export.process.duplicate.title') . ' ' . $lang->getLL('export.process.duplicate.message') . LF);
             $this->cli_echo($l10nmgrGetXML->renderExportsCli() . LF);
         } else {
             // Save export to XML file
             $xmlFileName = $l10nmgrGetXML->render();
             $l10nmgrGetXML->saveExportInformation();
             // If email notification is set send export files to responsible translator
             if ($this->lConf['enable_notification'] == 1) {
                 if (empty($this->lConf['email_recipient'])) {
                     $this->cli_echo($lang->getLL('error.email.repient_missing.msg') . "\n");
                 } else {
                     $this->emailNotification($xmlFileName, $l10nmgrCfgObj, $tlang);
                 }
             } else {
                 $this->cli_echo($lang->getLL('error.email.notification_disabled.msg') . "\n");
             }
             // If FTP option is set upload files to remote server
             if ($this->lConf['enable_ftp'] == 1) {
                 if (file_exists($xmlFileName)) {
                     $error .= $this->ftpUpload($xmlFileName, $l10nmgrGetXML->getFileName());
                 } else {
                     $this->cli_echo($lang->getLL('error.ftp.file_not_found.msg') . "\n");
                 }
             } else {
                 $this->cli_echo($lang->getLL('error.ftp.disabled.msg') . "\n");
             }
             if ($this->lConf['enable_notification'] == 0 && $this->lConf['enable_ftp'] == 0) {
                 $this->cli_echo(sprintf($lang->getLL('export.file_saved.msg'), $xmlFileName) . "\n");
             }
         }
     } else {
         $error .= $lang->getLL('error.l10nmgr.object_not_loaded.msg') . "\n";
     }
     return $error;
 }
 /**
  * Mandatory autofix function
  * Will run auto-fix on the result array. Echos status during processing.
  *
  * @param array $resultArray Result array from main() function
  * @return void
  * @todo Define visibility
  */
 public function main_autoFix($resultArray)
 {
     foreach ($resultArray['dirty'] as $fieldID) {
         list($table, $uid, $field) = explode(':', $fieldID);
         echo 'Cleaning XML in "' . $fieldID . '": ';
         if ($bypass = $this->cli_noExecutionCheck($fieldID)) {
             echo $bypass;
         } else {
             // Clean XML:
             $data = array();
             $recRow = \TYPO3\CMS\Backend\Utility\BackendUtility::getRecordRaw($table, 'uid=' . intval($uid));
             $flexObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\FlexForm\\FlexFormTools');
             if ($recRow[$field]) {
                 $data[$table][$uid][$field] = $flexObj->cleanFlexFormXML($table, $field, $recRow);
             }
             // Execute Data array:
             $tce = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
             $tce->stripslashes_values = FALSE;
             $tce->dontProcessTransformations = TRUE;
             $tce->bypassWorkspaceRestrictions = TRUE;
             $tce->bypassFileHandling = TRUE;
             // Check has been done previously that there is a backend user which is Admin and also in live workspace
             $tce->start($data, array());
             $tce->process_datamap();
             // Return errors if any:
             if (count($tce->errorLog)) {
                 echo '	ERROR from "TCEmain":' . LF . 'TCEmain:' . implode(LF . 'TCEmain:', $tce->errorLog);
             } else {
                 echo 'DONE';
             }
         }
         echo LF;
     }
 }
Exemple #22
0
 /**
  * Submit incoming content as translated language to database. Must match what is available in $accum.
  *
  * @param array $accum Translation configuration
  * @param array $inputArray Array with incoming translation. Must match what is found in $accum
  * @return mixed False if error - else flexFormDiffArray (if $inputArray was an array and processing was performed.)
  */
 function _submitContentAsTranslatedLanguageAndGetFlexFormDiff($accum, $inputArray)
 {
     if (is_array($inputArray)) {
         // Initialize:
         /** @var $flexToolObj FlexFormTools */
         $flexToolObj = GeneralUtility::makeInstance(FlexFormTools::class);
         $gridElementsInstalled = ExtensionManagementUtility::isLoaded('gridelements');
         $TCEmain_data = array();
         $TCEmain_cmd = array();
         $_flexFormDiffArray = array();
         // Traverse:
         foreach ($accum as $pId => $page) {
             foreach ($accum[$pId]['items'] as $table => $elements) {
                 foreach ($elements as $elementUid => $data) {
                     if (is_array($data['fields'])) {
                         foreach ($data['fields'] as $key => $tData) {
                             if (is_array($tData) && isset($inputArray[$table][$elementUid][$key])) {
                                 list($Ttable, $TuidString, $Tfield, $Tpath) = explode(':', $key);
                                 list($Tuid, $Tlang, $TdefRecord) = explode('/', $TuidString);
                                 if (!$this->createTranslationAlsoIfEmpty && $inputArray[$table][$elementUid][$key] == '' && $Tuid == 'NEW') {
                                     //if data is empty do not save it
                                     unset($inputArray[$table][$elementUid][$key]);
                                     continue;
                                 }
                                 // If new element is required, we prepare for localization
                                 if ($Tuid === 'NEW') {
                                     if ($table === 'tt_content' && $gridElementsInstalled === true) {
                                         $element = BackendUtility::getRecordRaw($table, 'uid = ' . $elementUid . ' AND deleted = 0');
                                         if ($element['colPos'] > -1) {
                                             $TCEmain_cmd[$table][$elementUid]['localize'] = $Tlang;
                                         } else {
                                             if ($element['tx_gridelements_container'] > 0) {
                                                 //TYPO3\CMS\Core\Utility\DebugUtility::debug($element,'$element');
                                                 $container = BackendUtility::getRecordRaw($table, 'l18n_parent = ' . $element['tx_gridelements_container'] . ' AND deleted = 0 AND sys_language_uid = ' . $Tlang);
                                                 if ($container['uid'] > 0) {
                                                     $TCEmain_cmd[$table][$container['uid']]['inlineLocalizeSynchronize'] = 'tx_gridelements_children,localize';
                                                 }
                                             }
                                         }
                                     } else {
                                         //print "\nNEW\n";
                                         $TCEmain_cmd[$table][$elementUid]['localize'] = $Tlang;
                                     }
                                 }
                                 // If FlexForm, we set value in special way:
                                 if ($Tpath) {
                                     if (!is_array($TCEmain_data[$Ttable][$TuidString][$Tfield])) {
                                         $TCEmain_data[$Ttable][$TuidString][$Tfield] = array();
                                     }
                                     //TCEMAINDATA is passed as reference here:
                                     $flexToolObj->setArrayValueByPath($Tpath, $TCEmain_data[$Ttable][$TuidString][$Tfield], $inputArray[$table][$elementUid][$key]);
                                     $_flexFormDiffArray[$key] = array('translated' => $inputArray[$table][$elementUid][$key], 'default' => $tData['defaultValue']);
                                 } else {
                                     $TCEmain_data[$Ttable][$TuidString][$Tfield] = $inputArray[$table][$elementUid][$key];
                                 }
                                 unset($inputArray[$table][$elementUid][$key]);
                                 // Unsetting so in the end we can see if $inputArray was fully processed.
                             } else {
                                 //debug($tData,'fields not set for: '.$elementUid.'-'.$key);
                                 //debug($inputArray[$table],'inputarray');
                             }
                         }
                         if (is_array($inputArray[$table][$elementUid]) && !count($inputArray[$table][$elementUid])) {
                             unset($inputArray[$table][$elementUid]);
                             // Unsetting so in the end we can see if $inputArray was fully processed.
                         }
                     }
                 }
                 if (is_array($inputArray[$table]) && !count($inputArray[$table])) {
                     unset($inputArray[$table]);
                     // Unsetting so in the end we can see if $inputArray was fully processed.
                 }
             }
         }
         //TYPO3\CMS\Core\Utility\DebugUtility::debug($TCEmain_cmd,'$TCEmain_cmd');
         //TYPO3\CMS\Core\Utility\DebugUtility::debug($TCEmain_data,'$TCEmain_data');
         self::$targetLanguageID = $Tlang;
         // Execute CMD array: Localizing records:
         /** @var $tce DataHandler */
         $tce = GeneralUtility::makeInstance(DataHandler::class);
         if ($this->extensionConfiguration['enable_neverHideAtCopy'] == 1) {
             $tce->neverHideAtCopy = true;
         }
         $tce->stripslashes_values = false;
         $tce->isImporting = true;
         if (count($TCEmain_cmd)) {
             $tce->start(array(), $TCEmain_cmd);
             $tce->process_cmdmap();
             if (count($tce->errorLog)) {
                 debug($tce->errorLog, 'TCEmain localization errors:');
             }
         }
         // Before remapping
         if (TYPO3_DLOG) {
             GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': TCEmain_data before remapping: ' . GeneralUtility::arrayToLogString($TCEmain_data), 'l10nmgr');
         }
         // Remapping those elements which are new:
         $this->lastTCEMAINCommandsCount = 0;
         foreach ($TCEmain_data as $table => $items) {
             foreach ($TCEmain_data[$table] as $TuidString => $fields) {
                 list($Tuid, $Tlang, $TdefRecord) = explode('/', $TuidString);
                 $this->lastTCEMAINCommandsCount++;
                 if ($Tuid === 'NEW') {
                     if ($tce->copyMappingArray_merged[$table][$TdefRecord]) {
                         $TCEmain_data[$table][BackendUtility::wsMapId($table, $tce->copyMappingArray_merged[$table][$TdefRecord])] = $fields;
                     } else {
                         GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': Record "' . $table . ':' . $TdefRecord . '" was NOT localized as it should have been!', 'l10nmgr');
                     }
                     unset($TCEmain_data[$table][$TuidString]);
                 }
             }
         }
         // After remapping
         if (TYPO3_DLOG) {
             GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': TCEmain_data after remapping: ' . GeneralUtility::arrayToLogString($TCEmain_data), 'l10nmgr');
         }
         // Now, submitting translation data:
         /** @var $tce DataHandler */
         $tce = GeneralUtility::makeInstance(DataHandler::class);
         if ($this->extensionConfiguration['enable_neverHideAtCopy'] == 1) {
             $tce->neverHideAtCopy = true;
         }
         $tce->stripslashes_values = false;
         $tce->dontProcessTransformations = true;
         $tce->isImporting = true;
         //print_r($TCEmain_data);
         $tce->start($TCEmain_data, array());
         // check has been done previously that there is a backend user which is Admin and also in live workspace
         $tce->process_datamap();
         self::$targetLanguageID = null;
         if (count($tce->errorLog)) {
             GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': TCEmain update errors: ' . GeneralUtility::arrayToLogString($tce->errorLog), 'l10nmgr');
         }
         if (count($tce->autoVersionIdMap) && count($_flexFormDiffArray)) {
             if (TYPO3_DLOG) {
                 GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': flexFormDiffArry: ' . GeneralUtility::arrayToLogString($this->flexFormDiffArray), 'l10nmgr');
             }
             foreach ($_flexFormDiffArray as $key => $value) {
                 list($Ttable, $Tuid, $Trest) = explode(':', $key, 3);
                 if ($tce->autoVersionIdMap[$Ttable][$Tuid]) {
                     $_flexFormDiffArray[$Ttable . ':' . $tce->autoVersionIdMap[$Ttable][$Tuid] . ':' . $Trest] = $_flexFormDiffArray[$key];
                     unset($_flexFormDiffArray[$key]);
                 }
             }
             if (TYPO3_DLOG) {
                 GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': autoVersionIdMap: ' . $tce->autoVersionIdMap, 'l10nmgr');
                 GeneralUtility::sysLog(__FILE__ . ': ' . __LINE__ . ': _flexFormDiffArray: ' . GeneralUtility::arrayToLogString($_flexFormDiffArray), 'l10nmgr');
             }
         }
         // Should be empty now - or there were more information in the incoming array than there should be!
         if (count($inputArray)) {
             debug($inputArray, 'These fields were ignored since they were not in the configuration:');
         }
         return $_flexFormDiffArray;
     } else {
         return false;
     }
 }
Exemple #23
0
 /**
  * Checks if record can be selected based on given permission criteria
  *
  * @param string $table Record table name
  * @param int $id Record UID
  * @param int|string $perms Permission restrictions to observe: Either an integer that will be bitwise AND'ed or a string, which points to a key in the ->pMap array
  * @return bool Returns TRUE if the record given by $table, $id and $perms can be selected
  *
  * @throws \RuntimeException
  */
 public function doesRecordExist($table, $id, $perms)
 {
     $id = (int) $id;
     if ($this->bypassAccessCheckForRecords) {
         return is_array(BackendUtility::getRecordRaw($table, 'uid=' . $id, 'uid'));
     }
     // Processing the incoming $perms (from possible string to integer that can be AND'ed)
     if (!MathUtility::canBeInterpretedAsInteger($perms)) {
         if ($table != 'pages') {
             switch ($perms) {
                 case 'edit':
                 case 'delete':
                 case 'new':
                     // This holds it all in case the record is not page!!
                     if ($table === 'sys_file_reference' && array_key_exists('pages', $this->datamap)) {
                         $perms = 'edit';
                     } else {
                         $perms = 'editcontent';
                     }
                     break;
             }
         }
         $perms = (int) $this->pMap[$perms];
     } else {
         $perms = (int) $perms;
     }
     if (!$perms) {
         throw new \RuntimeException('Internal ERROR: no permissions to check for non-admin user', 1270853920);
     }
     // For all tables: Check if record exists:
     $isWebMountRestrictionIgnored = BackendUtility::isWebMountRestrictionIgnored($table);
     if (is_array($GLOBALS['TCA'][$table]) && $id > 0 && ($isWebMountRestrictionIgnored || $this->isRecordInWebMount($table, $id) || $this->admin)) {
         if ($table != 'pages') {
             // Find record without checking page
             // @todo: Thist should probably check for editlock
             $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
             $this->addDeleteRestriction($queryBuilder->getRestrictions()->removeAll());
             $output = $queryBuilder->select('uid', 'pid')->from($table)->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)))->execute()->fetch();
             BackendUtility::fixVersioningPid($table, $output, true);
             // If record found, check page as well:
             if (is_array($output)) {
                 // Looking up the page for record:
                 $queryBuilder = $this->doesRecordExist_pageLookUp($output['pid'], $perms);
                 $pageRec = $queryBuilder->select('uid')->execute()->fetch();
                 // Return TRUE if either a page was found OR if the PID is zero AND the user is ADMIN (in which case the record is at root-level):
                 $isRootLevelRestrictionIgnored = BackendUtility::isRootLevelRestrictionIgnored($table);
                 if (is_array($pageRec) || !$output['pid'] && ($isRootLevelRestrictionIgnored || $this->admin)) {
                     return true;
                 }
             }
             return false;
         } else {
             $queryBuilder = $this->doesRecordExist_pageLookUp($id, $perms);
             return $queryBuilder->count('uid')->execute()->fetchColumn(0);
         }
     }
     return false;
 }