/** * Performs the accordant updates. * * @param array &$dbQueries Queries done in this update * @param mixed &$customMessages Custom messages * @return boolean Whether everything went smoothly or not */ public function performUpdate(array &$dbQueries, &$customMessages) { $oldCategoryTableFields = $this->databaseConnection->admin_get_fields('tx_mooxnews_domain_model_category'); // A temporary migration column is needed in old category table. Add this when not already present if (!array_key_exists('migrate_sys_category_uid', $oldCategoryTableFields)) { $this->databaseConnection->admin_query("ALTER TABLE tx_mooxnews_domain_model_category ADD migrate_sys_category_uid int(11) DEFAULT '0' NOT NULL"); } // convert tx_mooxnews_domain_model_category records $this->migrateNewsCategoryRecords(); // set/update all relations $oldNewCategoryUidMapping = $this->getOldNewCategoryUidMapping(); $this->updateParentFieldOfMigratedCategories($oldNewCategoryUidMapping); $this->migrateCategoryMmRecords($oldNewCategoryUidMapping); $this->updateCategoryPermissionFields('be_groups', $oldNewCategoryUidMapping); $this->updateCategoryPermissionFields('be_users', $oldNewCategoryUidMapping); $this->migrateCategoryImages(); $this->markWizardAsDone(); return TRUE; }
/** * @test */ public function extensionAlteringTable() { if (!ExtensionManagementUtility::isLoaded('aaa') || !ExtensionManagementUtility::isLoaded('bbb')) { self::markTestSkipped('This test can only be run if the extensions aaa and bbb ' . 'from tests/res are installed.'); } $this->importExtensions(array('bbb'), true); $tableNames = $this->getDatabaseTables(); self::assertContains('tx_bbb_test', $tableNames, 'Check that extension bbb is installed. The extension can be found in TestExtensions/.'); self::assertContains('tx_aaa_test', $tableNames, 'Check that extension aaa is installed. The extension can be found in TestExtensions/.'); // extension BBB extends an AAA table $columns = $this->db->admin_get_fields('tx_aaa_test'); self::assertContains('tx_bbb_test', array_keys($columns), self::DB_PERMISSIONS_MESSAGE); }
/** * Check whether field name is valid. * -> prevent sql injection * * @param string $field field name * @return boolean true, if column name is valid */ protected function validateName($field) { if ($field === 'username') { return true; } $res = $this->databaseHandle->admin_get_fields('fe_users'); if ($res) { while ($row = $this->databaseHandle->sql_fetch_assoc($res)) { if ($row['Field'] === $field) { return true; } } } return false; }
/** * Search * * @return string */ public function search() { $SET = $GLOBALS['SOBE']->MOD_SETTINGS; $swords = $SET['sword']; $out = ''; $limit = 200; if ($swords) { foreach ($GLOBALS['TCA'] as $table => $value) { // Get fields list $conf = $GLOBALS['TCA'][$table]; // Avoid querying tables with no columns if (empty($conf['columns'])) { continue; } $fieldsInDatabase = $this->databaseConnection->admin_get_fields($table); $list = array_intersect(array_keys($conf['columns']), array_keys($fieldsInDatabase)); // Get query $qp = $this->databaseConnection->searchQuery(array($swords), $list, $table); // Count: $count = $this->databaseConnection->exec_SELECTcountRows('*', $table, $qp . BackendUtility::deleteClause($table)); if ($count) { $rowArr = array(); $res = $this->databaseConnection->exec_SELECTquery('uid,' . $conf['ctrl']['label'], $table, $qp . BackendUtility::deleteClause($table), '', '', $limit); $lrow = null; while ($row = $this->databaseConnection->sql_fetch_assoc($res)) { $rowArr[] = $this->resultRowDisplay($row, $conf, $table); $lrow = $row; } $this->databaseConnection->sql_free_result($res); $markup = []; $markup[] = '<div class="panel panel-default">'; $markup[] = ' <div class="panel-heading">'; $markup[] = $this->languageService->sL($conf['ctrl']['title'], true) . ' (' . $count . ')'; $markup[] = ' </div>'; $markup[] = ' <table class="table table-striped table-hover">'; $markup[] = $this->resultRowTitles($lrow, $conf, $table); $markup[] = ' </table>'; $markup[] = '</div>'; $out .= implode(LF, $markup); } } } return $out; }
/** * Migrates old event categories to sys_categories if required * * @return void */ protected function migrateEventCategoriesToSysCategories() { // check if tx_sfeventmgt_domain_model_category still exists $oldCategoryTableFields = $this->databaseConnection->admin_get_fields('tx_sfeventmgt_domain_model_category'); if (count($oldCategoryTableFields) === 0) { $status = FlashMessage::NOTICE; $title = ''; $message = 'Old category table does not exist anymore so no update needed'; $this->messageArray[] = [$status, $title, $message]; return; } // check if there are categories present else no update is needed $oldCategoryCount = $this->databaseConnection->exec_SELECTcountRows('uid', 'tx_sfeventmgt_domain_model_category', 'deleted = 0'); if ($oldCategoryCount === 0) { $status = FlashMessage::NOTICE; $title = ''; $message = 'No categories found in old table, no update needed'; $this->messageArray[] = [$status, $title, $message]; return; } else { $status = FlashMessage::NOTICE; $title = ''; $message = 'Must migrate ' . $oldCategoryCount . ' categories.'; $this->messageArray[] = [$status, $title, $message]; } // A temporary migration column is needed in old category table. Add this when not already present if (!array_key_exists('migrate_sys_category_uid', $oldCategoryTableFields)) { $this->databaseConnection->admin_query("ALTER TABLE tx_sfeventmgt_domain_model_category ADD migrate_sys_category_uid int(11) DEFAULT '0' NOT NULL"); } // convert tx_sfeventmgt_domain_model_category records $this->migrateEventCategoryRecords(); // set/update all relations $oldNewCategoryUidMapping = $this->getOldNewCategoryUidMapping(); $this->updateParentFieldOfMigratedCategories($oldNewCategoryUidMapping); $this->migrateCategoryMmRecords($oldNewCategoryUidMapping); $this->updateFlexformCategories('sfeventmgt_pievent', $oldNewCategoryUidMapping, 'settings.category'); /** * Finished category migration */ $message = 'All categories are updated. Run <strong>DB compare</strong> in the install tool to remove the ' . 'now obsolete `tx_sfeventmgt_domain_model_category` and `tx_sfeventmgt_event_category_mm` tables and ' . 'run the <strong>DB check</strong> to update the reference index.'; $status = FlashMessage::OK; $title = 'Updated all categories!'; $this->messageArray[] = [$status, $title, $message]; }
/** * Returns TRUE if upgrade wizard for legacy EXT:eu_ldap records should be run. * * @return bool */ protected function checkEuLdap() { $table = 'tx_euldap_server'; $migrationField = 'tx_igldapssoauth_migrated'; // We check the database table itself and not whether EXT:eu_ldap is loaded // because it may have been deactivated since it is not incompatible $existingTables = $this->databaseConnection->admin_get_tables(); if (!isset($existingTables[$table])) { return FALSE; } // Ensure the column used to flag processed records is present $fields = $this->databaseConnection->admin_get_fields($table); if (!isset($fields[$migrationField])) { $alterTableQuery = 'ALTER TABLE ' . $table . ' ADD ' . $migrationField . ' tinyint(4) NOT NULL default \'0\''; // Method admin_query() will parse the query and make it compatible with DBAL, if needed $this->databaseConnection->admin_query($alterTableQuery); } $euLdapConfigurationRecords = $this->databaseConnection->exec_SELECTcountRows('*', $table, $migrationField . '=0'); return $euLdapConfigurationRecords > 0; }
/** * Clear the TYPO3 page cache for the given record. * If the record lies on a page, then we clear the cache of this page. * If the record has no PID column, we clear the cache of the current page as best-effort. * * Much of this functionality is taken from DataHandler::clear_cache() which unfortunately only works with logged-in BE user. * * @param string $tableName Table name of the record * @param int $uid UID of the record * @return void */ protected function clearPageCache($tableName, $uid) { $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); if (isset($frameworkConfiguration['persistence']['enableAutomaticCacheClearing']) && $frameworkConfiguration['persistence']['enableAutomaticCacheClearing'] === '1') { } else { // if disabled, return return; } $pageIdsToClear = array(); $storagePage = NULL; $columns = $this->databaseHandle->admin_get_fields($tableName); if (array_key_exists('pid', $columns)) { $result = $this->databaseHandle->exec_SELECTquery('pid', $tableName, 'uid=' . (int) $uid); if ($row = $this->databaseHandle->sql_fetch_assoc($result)) { $storagePage = $row['pid']; $pageIdsToClear[] = $storagePage; } } elseif (isset($GLOBALS['TSFE'])) { // No PID column - we can do a best-effort to clear the cache of the current page if in FE $storagePage = $GLOBALS['TSFE']->id; $pageIdsToClear[] = $storagePage; } if ($storagePage === NULL) { return; } if (!isset($this->pageTSConfigCache[$storagePage])) { $this->pageTSConfigCache[$storagePage] = BackendUtility::getPagesTSconfig($storagePage); } if (isset($this->pageTSConfigCache[$storagePage]['TCEMAIN.']['clearCacheCmd'])) { $clearCacheCommands = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', strtolower($this->pageTSConfigCache[$storagePage]['TCEMAIN.']['clearCacheCmd']), TRUE); $clearCacheCommands = array_unique($clearCacheCommands); foreach ($clearCacheCommands as $clearCacheCommand) { if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($clearCacheCommand)) { $pageIdsToClear[] = $clearCacheCommand; } } } foreach ($pageIdsToClear as $pageIdToClear) { $this->cacheService->getPageIdStack()->push($pageIdToClear); } }
/** * Builds the page ID checking statement * * @param string $tableName The database table name * @param array &$sql The query parts * @param array $storagePageIds list of storage page ids * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException * @return void */ protected function addPageIdStatement($tableName, array &$sql, array $storagePageIds) { $tableColumns = $this->tableColumnCache->get($tableName); if ($tableColumns === FALSE) { $tableColumns = $this->databaseHandle->admin_get_fields($tableName); $this->tableColumnCache->set($tableName, $tableColumns); } if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $tableColumns)) { $rootLevel = (int) $GLOBALS['TCA'][$tableName]['ctrl']['rootLevel']; if ($rootLevel) { if ($rootLevel === 1) { $sql['additionalWhereClause'][] = $tableName . '.pid = 0'; } } else { if (empty($storagePageIds)) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InconsistentQuerySettingsException('Missing storage page ids.', 1365779762); } $sql['additionalWhereClause'][] = $tableName . '.pid IN (' . implode(', ', $storagePageIds) . ')'; } } }
/** * Builds the page ID checking statement * * @param string $tableName The database table name * @param string $tableAlias The table alias used in the query. * @param array $storagePageIds list of storage page ids * @throws InconsistentQuerySettingsException * @return string */ protected function getPageIdStatement($tableName, $tableAlias, array $storagePageIds) { $pageIdStatement = ''; $tableColumns = $this->tableColumnCache->get($tableName); if ($tableColumns === false) { $tableColumns = $this->databaseHandle->admin_get_fields($tableName); $this->tableColumnCache->set($tableName, $tableColumns); } if (is_array($GLOBALS['TCA'][$tableName]['ctrl']) && array_key_exists('pid', $tableColumns)) { $rootLevel = (int) $GLOBALS['TCA'][$tableName]['ctrl']['rootLevel']; switch ($rootLevel) { // Only in pid 0 case 1: return $tableAlias . '.pid = 0'; // Pid 0 and pagetree // Pid 0 and pagetree case -1: if (empty($storagePageIds)) { return $tableAlias . '.pid = 0'; } $storagePageIds[] = 0; break; // Only pagetree or not set // Only pagetree or not set case 0: if (empty($storagePageIds)) { throw new InconsistentQuerySettingsException('Missing storage page ids.', 1365779762); } break; // Invalid configuration // Invalid configuration default: return ''; } $pageIdStatement = $tableAlias . '.pid IN (' . implode(',', $this->databaseHandle->cleanIntArray($storagePageIds)) . ')'; } return $pageIdStatement; }
/** * Check if seo_basics was installed and then transfer the properties from pages and pages_language_overlay * * @return void */ protected function migrateFromSeoBasics() { // check if seo_basics fields exists $metaseoTableFields = $this->databaseConnection->admin_get_fields('pages'); if (!array_key_exists('tx_seo_titletag', $metaseoTableFields)) { $status = FlashMessage::NOTICE; $title = 'seo_basics not found'; $message = 'No seo_basics properties, so no update needed'; $this->messageArray[] = [$status, $title, $message]; return; } // migrate pages $fieldsToMigrate = ['tx_seo_titletag' => 'tx_csseo_title', 'tx_seo_canonicaltag' => 'tx_csseo_canonical']; $this->migrateFields($fieldsToMigrate, 'pages'); $this->migrateFields($fieldsToMigrate, 'pages_language_overlay'); /** * Finished migration from seo_basics */ $message = 'Title and Canonical are migrated. Run <strong>DB compare</strong> in the install tool to remove the fields from metaseo and run the <strong>DB check</strong> to update the reference index.'; $status = FlashMessage::OK; $title = 'Migrated all seo_basics fields!'; $this->messageArray[] = [$status, $title, $message]; }
/** * Init Function: here all the needed configuration values are stored in class variables.. */ function init() { $this->db = $GLOBALS['TYPO3_DB']; $this->tsfe = $GLOBALS['TSFE']; $this->pi_loadLL(); // Loading language-labels $this->pi_setPiVarDefaults(); // Set default piVars from TS $this->SIM_ACCESS_TIME = $GLOBALS['SIM_ACCESS_TIME']; // fallback for TYPO3 < 4.2 if (!$this->SIM_ACCESS_TIME) { $simTime = $GLOBALS['SIM_EXEC_TIME']; $this->SIM_ACCESS_TIME = $simTime - $simTime % 60; } $this->initCaching(); $this->local_cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer'); // Local cObj. $this->enableFields = $this->getEnableFields('tt_news'); if ($this->tt_news_uid === 0) { // no tt_news_uid set by displayCurrentRecord $this->tt_news_uid = intval($this->piVars['tt_news']); // Get the submitted uid of a news (if any) } if (!isset($this->conf['compatVersion']) || !preg_match('/^\\d+\\.\\d+\\.\\d+$/', $this->conf['compatVersion'])) { $this->conf['compatVersion'] = $this->hObj->getCurrentVersion(); } $this->token = md5(microtime()); if (TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('version')) { $this->versioningEnabled = true; } // load available syslanguages $this->initLanguages(); // sys_language_mode defines what to do if the requested translation is not found $this->sys_language_mode = $this->conf['sys_language_mode'] ? $this->conf['sys_language_mode'] : $this->tsfe->sys_language_mode; if ($this->conf['searchFieldList']) { // get fieldnames from the tt_news db-table $this->fieldNames = array_keys($this->db->admin_get_fields('tt_news')); $searchFieldList = $this->hObj->validateFields($this->conf['searchFieldList'], $this->fieldNames); if ($searchFieldList) { $this->searchFieldList = $searchFieldList; } } // Archive: $archiveMode = trim($this->conf['archiveMode']); // month, quarter or year listing in AMENU $this->config['archiveMode'] = $archiveMode ? $archiveMode : 'month'; // arcExclusive : -1=only non-archived; 0=don't care; 1=only archived $arcExclusive = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'archive', 'sDEF'); $this->arcExclusive = $arcExclusive ? $arcExclusive : intval($this->conf['archive']); $this->config['datetimeDaysToArchive'] = intval($this->conf['datetimeDaysToArchive']); $this->config['datetimeHoursToArchive'] = intval($this->conf['datetimeHoursToArchive']); $this->config['datetimeMinutesToArchive'] = intval($this->conf['datetimeMinutesToArchive']); if ($this->conf['useHRDates']) { $this->hObj->convertDates(); } // list of pages where news records will be taken from if (!$this->conf['dontUsePidList']) { $this->initPidList(); } // itemLinkTarget is only used for categoryLinkMode 3 (catselector) in framesets $this->conf['itemLinkTarget'] = trim($this->conf['itemLinkTarget']); // id of the page where the search results should be displayed $this->config['searchPid'] = intval($this->conf['searchPid']); // pages in Single view will be divided by this token $this->config['pageBreakToken'] = trim($this->conf['pageBreakToken']) ? trim($this->conf['pageBreakToken']) : '<---newpage--->'; $this->config['singleViewPointerName'] = trim($this->conf['singleViewPointerName']) ? trim($this->conf['singleViewPointerName']) : 'sViewPointer'; $maxWordsInSingleView = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'maxWordsInSingleView', 's_misc')); $maxWordsInSingleView = $maxWordsInSingleView ? $maxWordsInSingleView : intval($this->conf['maxWordsInSingleView']); $this->config['maxWordsInSingleView'] = $maxWordsInSingleView ? $maxWordsInSingleView : 0; $this->config['useMultiPageSingleView'] = $this->conf['useMultiPageSingleView']; // pid of the page with the single view. the old var PIDitemDisplay is still processed if no other value is found $singlePid = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'PIDitemDisplay', 's_misc'); $this->config['singlePid'] = $singlePid ? $singlePid : intval($this->cObj->stdWrap($this->conf['singlePid'], $this->conf['singlePid.'])); if (!$this->config['singlePid']) { $this->errors[] = 'No singlePid defined'; } // pid to return to when leaving single view $backPid = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'backPid', 's_misc')); $backPid = $backPid ? $backPid : intval($this->conf['backPid']); $backPid = $backPid ? $backPid : intval($this->piVars['backPid']); $backPid = $backPid ? $backPid : $this->tsfe->id; $this->config['backPid'] = $backPid; // max items per page $FFlimit = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listLimit', 's_template'), 0, 1000); $limit = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->cObj->stdWrap($this->conf['limit'], $this->conf['limit.']), 0, 1000); $limit = $limit ? $limit : 50; $this->config['limit'] = $FFlimit ? $FFlimit : $limit; $latestLimit = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($this->cObj->stdWrap($this->conf['latestLimit'], $this->conf['latestLimit.']), 0, 1000); $latestLimit = $latestLimit ? $latestLimit : 10; $this->config['latestLimit'] = $FFlimit ? $FFlimit : $latestLimit; // orderBy and groupBy statements for the list Query $orderBy = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listOrderBy', 'sDEF'); $orderByTS = trim($this->conf['listOrderBy']); $orderBy = $orderBy ? $orderBy : $orderByTS; $this->config['orderBy'] = $orderBy; if ($orderBy) { $ascDesc = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'ascDesc', 'sDEF'); $this->config['ascDesc'] = $ascDesc; if ($this->config['ascDesc']) { // remove ASC/DESC from 'orderBy' if it is already set from TS $this->config['orderBy'] = preg_replace('/( DESC| ASC)\\b/i', '', $this->config['orderBy']); } } $this->config['groupBy'] = trim($this->conf['listGroupBy']); // if this is set, the first image is handled as preview image, which is only shown in list view $fImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'firstImageIsPreview', 's_misc'); $this->config['firstImageIsPreview'] = $fImgPreview ? $fImgPreview : $this->conf['firstImageIsPreview']; $forcefImgPreview = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'forceFirstImageIsPreview', 's_misc'); $this->config['forceFirstImageIsPreview'] = $forcefImgPreview ? $fImgPreview : $this->conf['forceFirstImageIsPreview']; // List start id // $listStartId = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'listStartId', 's_misc')); // $this->config['listStartId'] = /*$listStartId?$listStartId:*/intval($this->conf['listStartId']); // supress pagebrowser $noPageBrowser = $this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'noPageBrowser', 's_template'); $this->config['noPageBrowser'] = $noPageBrowser ? $noPageBrowser : $this->conf['noPageBrowser']; // image sizes/optionSplit given from FlexForms $this->config['FFimgH'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxHeight', 's_template')); $this->config['FFimgW'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'imageMaxWidth', 's_template')); // Get number of alternative Layouts (loop layout in LATEST and LIST view) default is 2: $altLayouts = intval($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'alternatingLayouts', 's_template')); $altLayouts = $altLayouts ? $altLayouts : intval($this->conf['alternatingLayouts']); $this->alternatingLayouts = $altLayouts ? $altLayouts : 2; $altLayouts = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'altLayoutsOptionSplit', 's_template')); $this->config['altLayoutsOptionSplit'] = $altLayouts ? $altLayouts : trim($this->conf['altLayoutsOptionSplit']); // Get cropping length $croppingLenghtOptionSplit = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenghtOptionSplit', 's_template')); $this->config['croppingLenghtOptionSplit'] = $croppingLenghtOptionSplit ? $croppingLenghtOptionSplit : trim($this->conf['croppingLenghtOptionSplit']); $this->config['croppingLenght'] = trim($this->pi_getFFvalue($this->cObj->data['pi_flexform'], 'croppingLenght', 's_template')); $this->initTemplate(); // Configure caching $this->allowCaching = $this->conf['allowCaching'] ? 1 : 0; if (!$this->allowCaching) { $this->tsfe->set_no_cache(); } // get siteUrl for links in rss feeds. the 'dontInsert' option seems to be needed in some configurations depending on the baseUrl setting if (!$this->conf['displayXML.']['dontInsertSiteUrl']) { $this->config['siteUrl'] = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL'); } if ($this->debugTimes) { $this->hObj->getParsetime(__METHOD__); } }
/** * Tests if a given table contains a given field. * * @param string $tablename Table name for which to check whether a given field exists in * @param string $fieldname Field name for which to check whether it exists in the given table * @param array $info Additional info, will be displayed as debug message, if a key "message" exists this will be appended to the error message */ public static function tableAndFieldExist($tablename, $fieldname, $info = array()) { self::initializeDbObj(); return self::isArrayKey($fieldname, self::$dbObj->admin_get_fields($tablename), $info); }
/** * Removes all array keys which cannot be persisted * * @param array $data * * @return array */ protected function cleanUnavailableColumns(array $data) { return array_intersect_key($data, $this->databaseConnection->admin_get_fields($this->table)); }
/** * Checks if path cache table is ok. * * @return bool */ protected function pathCacheNeedsUpdates() { $fields = $this->databaseConnection->admin_get_fields('tx_realurl_pathcache'); return isset($fields['cache_id']) || !isset($fields['uid']) || stripos($fields['uid']['Extra'], 'auto_increment') === false; }
/** * @param string $table * @return array */ protected function fields($table) { return array_keys($this->db->admin_get_fields($table)); }
/** * @test * * @return void */ public function adminGetFieldsReturnFieldInformationsForTable() { $result = $this->subject->admin_get_fields($this->testTable); $this->assertArrayHasKey('id', $result); $this->assertArrayHasKey($this->testField, $result); }
/** * check if given field exists in a table * * @param string $field * @param string $table * * @return bool */ protected function isFieldAvailable($field, $table) { $tables = $this->database->admin_get_fields($table); return array_key_exists($field, $tables); }