public static function Retrieve(array $options = array()) { $users = $options['users'] ? $options['users'] : null; $actions = $options['actions'] ? $options['actions'] : null; $nodes = $options['nodes'] ? $options['nodes'] : null; $types = $options['types'] ? $options['types'] : null; $start = $options['start'] ? $options['start'] : 0; $top = $options['top'] ? $options['top'] : 100; $start_date = $options['start_date'] ? $options['start_date'] : null; $end_date = $options['end_date'] ? $options['end_date'] : null; $nodes_sql = self::_BuildSQL('nodes', $nodes); $types_sql = self::_BuildSQL('types', $types); $actions_sql = self::_BuildSQL('actions', $actions); $users_sql = self::_BuildSQL('users', $users); $date_sql = self::_BuildSQL('date', array($start_date, $end_date)); // Limit search to current context until new history system in place $context = MeshTools::GetContextPks(); $context = implode(',', $context); if($context) { $context_sql = "AND user_context IN ($context) AND context1 IN ($context)"; } else { $context_sql = ''; } // Grab all the records based on filters $sql = "SELECT * FROM node_history WHERE 1 $nodes_sql $types_sql $actions_sql $users_sql $date_sql $context_sql LIMIT $start, $top "; $dbc = new DatabaseConnection(); $rows = $dbc->query($sql); return new HistoryCollection($rows); }
private function _process(Call $call, $prev_table, $sql, &$jump_flags, $extra_columns, $wrapped) { /* table */ if (isset($call->table)) { $table = $call->table; } elseif (isset($call->jump)) { $table = $jump_flags[$call->jump]; unset($jump_flags[$call->jump]); } else { $table = $prev_table; } /* columns */ // Rule: every column (except *) should follow this format: TABLE.COLUMN AS ALIAS $columns = array(); // @todo Use the terms 'Column' and 'Expression' consistently if (empty($call->columns) && ! $wrapped) { $columns[] = $table . '.*'; } else { foreach ($call->columns as $column) { // @todo Clean up this working code; check for columns that are built from others in $extra_columns foreach ($column->getColumns() as $real_column) { $real_table = $real_column->getTable(); if (! isset($real_table)) { foreach ($extra_columns as $extra) { if ($real_column->getColumn() == $extra->getAlias()) { $columns[] = $column->toString('link'); continue 3; } } } } $columns[] = $column->toString($table); } $columns[] = $table . '.pk AS pk'; // @todo Use proper escaping from DatabaseAdapter } foreach ($jump_flags as $flag => $flag_table) { $columns[] = "link.`#$flag` AS `#$flag`"; // @todo Use proper escaping from DatabaseAdapter } if (isset($call->flag)) { $columns[] = "$table.pk AS `#{$call->flag}`"; // @todo Use proper escaping from DatabaseAdapter } foreach ($extra_columns as $col) { $columns[] = $col->transpose('link'); // @todo Don't hardcode 'link' here } $columns = join(', ', array_unique($columns)); // @todo Replace this with a unique alias check /* where */ // @todo If possible, every column should follow this format: TABLE.COLUMN $where = $this->_format('WHERE ( %s )', join(' ', $this->_formatWhere($call->where, $call->columns))); // Handle context filtering if (isset($call->context) && $this->_isContextSupported($table)) { $contexts = join(',', MeshTools::GetContextPks($call->context)); $where = strlen($where) > 0 ? "$where AND $table.context IN ($contexts)" : "WHERE $table.context IN ($contexts)"; } /* group */ // Any aliases must be unqualified, so we are not qualifying anything $group = $this->_format('GROUP BY %s', join (', ', $this->_formatGroup($call->group))); /* order */ // Any aliases must be unqualified, so we are not qualifying anything $order = $this->_format('ORDER BY %s', join (', ', $this->_formatOrder($call->order))); /* limit */ // LIMIT 0, 5 = LIMIT 5 so this should not be a problem as $start defaults to 0 $limit = $this->_formatLimit('LIMIT %d, %d', $call->start, $call->limit); /* join */ if (isset($sql)) { if ($call->not_linked) { if ($call->optional) { throw new Exception('OPTIONAL and NOT_LINKED are incompatible'); } $outer_join_type = 'LEFT'; $inner_join_type = ''; $where = ('' == $where) ? "WHERE link.fk IS NULL" : "$where AND link.fk IS NULL"; } elseif ($call->optional) { $outer_join_type = 'RIGHT'; $inner_join_type = 'RIGHT'; } else { $outer_join_type = ''; $inner_join_type = ''; } $lookup = $this->_formatJoin($call->table, $prev_table, $sql, $call->wrap, $call->jump, array_keys($jump_flags), $extra_columns, $inner_join_type); $join = $this->_format("%s JOIN (\n\n%s\n\n ) AS link\n ON %s.pk = link.fk", $outer_join_type, $lookup, $table); } else { $join = ''; } /* create sql */ $sql = "SELECT DISTINCT $columns\nFROM $table\n" . $this->_format(" %s\n", $join) . $this->_format("%s\n", $where) . $this->_format("%s\n", $group) . $this->_format("%s\n", $order) . $this->_format("%s\n", $limit); /* debug and return */ if ($call->debug) { MeshTools::$DebugCounter++; echo 'Q' . MeshTools::$DebugCounter . '==========>' . $sql; error_log('Q' . MeshTools::$DebugCounter . '==========>' . $sql); } return array($table, $sql, array_merge($extra_columns, $call->columns)); }
public function commit(array $attributes) { //TODO: move all this logic to the query class // Get the node type $type = $this->getType(); // Determine the correct context if (is_string($attributes['context'])) { // Use the passed context $attributes['context'] = MeshTools::GetContextPks($attributes['context']); } else if (!$attributes['context']) { if ($this->pk) { // Bypass context on existing nodes if not explicitly passed in unset($attributes['context']); } else { // For new nodes use the default context $attributes['context'] = (array)MeshTools::GetDefaultContextPk(); if (empty($attributes['context'])) // for non-context setups { unset($attributes['context']); } } } if (! isset($attributes['context'])) { // Do nothing, bypass context updates } else if (1 == count($attributes['context'])) { $attributes['context'] = $attributes['context'][0]; } else // @todo New nodes can only have one context { throw new Exception('Cannot create node with ambiguous context'); } // Separate the attirbutes from the links foreach ($attributes as $key => $value) { // Link Nodes if not attributes if (! $this->_isAttribute($key)) { // Use only valid node types if ($this->_isNodeType($key)) { // Copy the attribute to the links array $links[$key] = $attributes[$key]; } else { throw new Exception('Cannot link '.$type.' with '.$key.' because type '.$key.' doesn\'t exist.'); } // Remove all non-attirbutes from the attributes array unset($attributes[$key]); } } try { // First update/insert the attributes // If the node exists then peform update, otherwise insert if ($this->pk) { // cache the data for this node $this->_cache->populate($attributes); $dbc = new DatabaseConnection(); $sql = "UPDATE $type SET "; foreach ($attributes as $key => $value) { $sql .= " $key = '".$dbc->escape($value)."', "; } $sql = rtrim($sql, ', '); $sql .= " WHERE pk = $this->pk"; $dbc->query($sql); } else { // cache the data for this node $this->_cache->populate($attributes); $dbc = new DatabaseConnection(); // Clean the attributes array_walk($attributes, array($this, '_escapeString')); // Build the columns and values $columns = implode(',', array_keys($attributes)); $values = "'".implode("','", $attributes)."'"; $sql = "INSERT INTO $type ($columns) VALUES ($values)"; $dbc->query($sql); $this->_cache->populate(array('pk' => mysql_insert_id())); // @todo MySQL-dependant! } // Now link the nodes if (count($links)) { foreach ($links as $type => $nodes) { $this->_linkNodes($nodes, $type); } } $node = new Node($this->_callChain); return $node; } catch (Exception $e) { throw new Exception($e); } }
public function __construct() { // Figure out context $this->_context_pks = implode(',', MeshTools::GetContextPks()); }