database = $database; } /** * @param DataTableBuildConfig $config * * @throws BuildFailedException * * @return DataTableInterface */ public function buildTable(DataTableBuildConfig $config) { if (empty(trim($config->getTableName()))) { throw new BuildFailedException('Build config is incomplete. Table name is empty.'); } if (empty(trim($config->getAjaxUrl()))) { throw new BuildFailedException('Build config is incomplete. Property "ajaxUrl" is missing.'); } if (!class_exists($config->getTableClass(), true)) { throw new BuildFailedException(sprintf('DataTable class "%s" not found', $config->getTableClass())); } $interfaces = class_implements($config->getTableClass(), true); if (!in_array(DataTableTypeInterface::class, $interfaces, true)) { throw new BuildFailedException( 'Can not build data table. Class does not implement ' . DataTableTypeInterface::class ); } /** @var DataTableTypeInterface $table */ $className = $config->getTableClass(); $table = new $className(); // @todo getParent() verarbeiten $options = new DataTableOptions(); $table->configureOptions($options); $columns = new ColumnCollection(); $table->configureColumns($columns); $query = $this->database->select(); $table->configureQuery($query); if ($query->hasOrderBy()) { throw new BuildFailedException( 'Sorting in "configureQuery" will be overwritten. ' . 'Use "setDefaultSorting" in "configureOptions" instead.' ); } $features = new FeatureCollection(); $table->configureFeatures($features); $filters = new FilterCollection(); $table->configureFilters($filters); $preparedTable = new PreparedDataTable($config, $options, $query, $columns, $features, $filters); $this->prepareTable($preparedTable); return $preparedTable; } /** * @param DataTableInterface $table * * @return void */ private function prepareTable(DataTableInterface $table) { $this->prepareColumns($table); $this->applyFeatures($table); $this->prepareSorting($table); } /** * @param DataTableInterface $table * * @return void */ private function applyFeatures(DataTableInterface $table) { /** @var DataTableFeatureInterface $feature */ foreach ($table->getFeatures() as $feature) { $feature->modifyTable($table); } } /** * @param DataTableInterface $table * * @return void */ private function prepareColumns(DataTableInterface $table) { // Spalten aus dem SQL-Query holen $query = $table->getBaseQuery(); $columnNames = $query->getCols(); foreach ($columnNames as $alias => $fullColumnName) { // Spalten mit Spaltenaliasen zuerst behandeln (easy) $column = $table->getColumns()->getByName($alias); if ($column !== null) { $column->setDbColumn($fullColumnName); continue; } // Tabellenalias aus Spaltenname entfernen $shortColumnName = $this->extractNameFromColumn($fullColumnName); $column = $table->getColumns()->getByName($shortColumnName); if ($column !== null) { $column->setDbColumn($fullColumnName); } } } /** * @param DataTableInterface $table * * @return void */ private function prepareSorting(DataTableInterface $table) { $columnNames = array_column($table->getColumns()->toArray(), 'data'); $defaultSorting = $table->getOptions()->getDefaultSorting(); $postSorting = $table->getOptions()->getPostSorting(); $preSorting = $table->getOptions()->getPreSorting(); $defaultSorting = $this->translateSortingValues($columnNames, $defaultSorting); $postSorting = $this->translateSortingValues($columnNames, $postSorting); $preSorting = $this->translateSortingValues($columnNames, $preSorting); /** * Sortierung, wenn nichts gesetzt ist; Benutzer-Sortierung überschreibt diesen Wert * * @see https://datatables.net/reference/option/order */ if (empty($defaultSorting)) { $defaultSorting = [[0, 'asc']]; } $table->getOptions()->setOption('order', $defaultSorting); /** * Vor- und Nach-Sortierung; Kann vom Benutzer nicht geändert werden * * @see https://datatables.net/reference/option/orderFixed */ if (!empty($preSorting)) { $orderFixed['pre'] = $preSorting; } if (!empty($postSorting)) { $orderFixed['post'] = $postSorting; } if (!empty($orderFixed)) { $table->getOptions()->setOption('orderFixed', $orderFixed); } else { $table->getOptions()->removeOption('orderFixed'); } } /** * @example ['lagerbestand' => 'DESC', 'bezeichnung' => 'ASC'] wird zu [[3, 'desc'], [1, 'asc']] * * @param array $columnNames * @param array $sortingValues * * @return array */ private function translateSortingValues($columnNames, $sortingValues) { $result = []; foreach ($sortingValues as $columnName => $sortOrder) { $columnIndex = array_search($columnName, $columnNames, true); if ($columnIndex !== false) { $result[] = [$columnIndex, strtolower($sortOrder)]; } } return $result; } /** * @param string $column * * @return string */ private function extractNameFromColumn($column) { if ($pos = strrpos($column, '.')) { return substr($column, $pos + 1); } return $column; } }