/** * Fetch related, foreign rows for a whole rowset's ManyToOne relationships. * (Given a table's schema and rows, iterate and replace all of its foreign * keys with the contents of these foreign rows.) * @param array $schema Table schema array * @param array $entries Table rows * @return array Revised table rows, now including foreign rows */ public function loadManyToOneRelationships($schemaArray, $table_entries) { // Identify the ManyToOne columns foreach ($schemaArray as $col) { $isManyToOneColumn = array_key_exists('relationship', $col) && $col['relationship']['type'] == 'MANYTOONE'; if ($isManyToOneColumn) { $foreign_id_column = $col['id']; if (array_key_exists('relationship', $col)) { $foreign_table_name = $col['relationship']['table_related']; } else { $message = 'Non single_file Many-to-One relationship lacks `table_related` value.'; if (array_key_exists('column_name', $col)) { $message .= " Column: " . $col['column_name']; } if (array_key_exists('table_name', $col)) { $message .= " Table: " . $col['table_name']; } throw new Exception\RelationshipMetadataException($message); } // Aggregate all foreign keys for this relationship (for each row, yield the specified foreign id) $yield = function ($row) use($foreign_id_column, $table_entries) { if (array_key_exists($foreign_id_column, $row)) { return $row[$foreign_id_column]; } }; $ids = array_map($yield, $table_entries); if (empty($ids)) { continue; } if (!TableSchema::canGroupViewTable($foreign_table_name)) { continue; } // Fetch the foreign data $select = new Select($foreign_table_name); $select->where->in('id', $ids); $columnNames = TableSchema::getAllNonAliasTableColumnNames($foreign_table_name); $select->columns($columnNames); $TableGateway = new RelationalTableGateway($this->acl, $foreign_table_name, $this->adapter); $rowset = $TableGateway->selectWith($select); $results = $rowset->toArray(); $foreign_table = array(); $columns = TableSchema::getAllNonAliasTableColumns($foreign_table_name); foreach ($results as $row) { $row = $this->parseRecordValuesByMysqlType($row, $columns); $foreign_table[$row['id']] = $row; } // Replace foreign keys with foreign rows foreach ($table_entries as &$parentRow) { if (array_key_exists($foreign_id_column, $parentRow)) { $foreign_id = (int) $parentRow[$foreign_id_column]; $parentRow[$foreign_id_column] = null; // "Did we retrieve the foreign row with this foreign ID in our recent query of the foreign table"? if (array_key_exists($foreign_id, $foreign_table)) { $parentRow[$foreign_id_column] = $foreign_table[$foreign_id]; } } } } } return $table_entries; }
public function fetchAllByUser($user_id, $assoc = false) { $select = new Select($this->table); $select->columns(array('id', 'user', 'table_name', 'columns_visible', 'sort', 'sort_order', STATUS_COLUMN_NAME, 'title', 'search_string')); $select->where->equalTo('user', $user_id)->isNull('title'); $select->where('table_name NOT IN( "directus_columns", "directus_ip_whitelist", "directus_preferences", "directus_privileges", "directus_settings", "directus_storage_adapters", "directus_tables", "directus_tab_privileges", "directus_ui" )'); $metadata = new \Zend\Db\Metadata\Metadata($this->getAdapter()); $tables = $metadata->getTableNames(DB_NAME); $tables = array_diff($tables, array("directus_columns", "directus_ip_whitelist", "directus_preferences", "directus_privileges", "directus_settings", "directus_storage_adapters", "directus_tables", "directus_tab_privileges", "directus_ui")); $rows = $this->selectWith($select)->toArray(); $preferences = array(); $tablePrefs = array(); foreach ($rows as $row) { $tablePrefs[$row['table_name']] = $row; } //Get Default Preferences foreach ($tables as $key => $table) { // Honor ACL. Skip the tables that the user doesn't have access too if (!TableSchema::canGroupViewTable($table)) { continue; } $tableName = $table; if (!isset($tablePrefs[$table])) { $table = null; } else { $table = $tablePrefs[$table]; } if (!isset($table['user'])) { $table = null; } $table = $this->constructPreferences($user_id, $tableName, $table); $preferences[$tableName] = $table; } return $preferences; }
/** * Fetch related, foreign rows for a whole rowset's ManyToOne relationships. * (Given a table's schema and rows, iterate and replace all of its foreign * keys with the contents of these foreign rows.) * * @param array $schemaArray Table schema array * @param array $table_entries Table rows * @param string|null $parentField * @param int $level * * @return array Revised table rows, now including foreign rows * * @throws Exception\RelationshipMetadataException */ public function loadManyToOneRelationships($schemaArray, $table_entries, $parentField = null, $level = 0) { // Identify the ManyToOne columns foreach ($schemaArray as $col) { $isManyToOneColumn = array_key_exists('relationship', $col) && $col['relationship']['type'] == 'MANYTOONE'; if ($isManyToOneColumn) { $foreign_id_column = $col['id']; if (array_key_exists('relationship', $col)) { $foreign_table_name = $col['relationship']['related_table']; } else { $message = 'Non single_file Many-to-One relationship lacks `related_table` value.'; if (array_key_exists('column_name', $col)) { $message .= ' Column: ' . $col['column_name']; } if (array_key_exists('table_name', $col)) { $message .= ' Table: ' . $col['table_name']; } throw new Exception\RelationshipMetadataException($message); } // ============================================================================= // HOTFIX: prevent infinite circle loop // ============================================================================= if ($parentField && $this->hasToManyCallStack($parentField, $foreign_table_name)) { return $table_entries; } $this->addToManyCallStack($level, is_null($parentField) ? $foreign_id_column : $parentField, $foreign_table_name); // Aggregate all foreign keys for this relationship (for each row, yield the specified foreign id) $yield = function ($row) use($foreign_id_column, $table_entries) { if (array_key_exists($foreign_id_column, $row)) { return $row[$foreign_id_column]; } }; $ids = array_map($yield, $table_entries); if (empty($ids)) { continue; } if (!TableSchema::canGroupViewTable($foreign_table_name)) { continue; } // Fetch the foreign data $select = new Select($foreign_table_name); $select->where->in('id', $ids); $columnNames = TableSchema::getAllNonAliasTableColumnNames($foreign_table_name); $select->columns($columnNames); $TableGateway = new RelationalTableGateway($this->acl, $foreign_table_name, $this->adapter); $rowset = $TableGateway->selectWith($select); $results = $rowset->toArray(); $foreign_table = []; foreach ($results as $row) { $row = $this->parseRecord($row, $foreign_table_name); $foreign_table[$row['id']] = $row; } // Get table column schema $schemaArray = TableSchema::getSchemaArray($foreign_table_name); // Eager-load related ManyToOne records $foreign_table = $this->loadManyToOneRelationships($schemaArray, $foreign_table, $parentField, $level + 1); // Convert dates into ISO 8601 Format $foreign_table = $this->convertDates($foreign_table, $schemaArray); // Replace foreign keys with foreign rows foreach ($table_entries as &$parentRow) { if (array_key_exists($foreign_id_column, $parentRow)) { $foreign_id = (int) $parentRow[$foreign_id_column]; $parentRow[$foreign_id_column] = null; // "Did we retrieve the foreign row with this foreign ID in our recent query of the foreign table"? if (array_key_exists($foreign_id, $foreign_table)) { $parentRow[$foreign_id_column] = $foreign_table[$foreign_id]; } } } } } return $table_entries; }
public function fetchAllByUser($user_id, $assoc = false) { $select = new Select($this->table); $select->columns(['id', 'user', 'table_name', 'columns_visible', 'sort', 'sort_order', 'status', 'title', 'search_string']); $select->where->equalTo('user', $user_id)->isNull('title'); $coreTables = SchemaManager::getDirectusTables(static::$IGNORED_TABLES); $select->where->addPredicate(new NotIn('table_name', $coreTables)); $metadata = new \Zend\Db\Metadata\Metadata($this->getAdapter()); $tables = $metadata->getTableNames(); $tables = array_diff($tables, $coreTables); $rows = $this->selectWith($select)->toArray(); $preferences = []; $tablePrefs = []; foreach ($rows as $row) { $tablePrefs[$row['table_name']] = $row; } //Get Default Preferences foreach ($tables as $key => $table) { // Honor ACL. Skip the tables that the user doesn't have access too if (!TableSchema::canGroupViewTable($table)) { continue; } $tableName = $table; if (!isset($tablePrefs[$table])) { $table = null; } else { $table = $tablePrefs[$table]; } if (!isset($table['user'])) { $table = null; } $table = $this->constructPreferences($user_id, $tableName, $table); $preferences[$tableName] = $table; } return $preferences; }