Example #1
0
    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);
    }
Example #2
0

// Add some locations
$shire = new Node('locations');
$shire->commit(array('name' => 'The Shire'));

$bilbo->link($shire);

$bree = new Node('locations');
$bree->commit(array('name' => 'Bree'));

$mirkwood = new Node('locations');
$mirkwood->commit(array('name' => 'Mirkwood'));


// Link the locations together, with directions for the preferred travel route
$shire->link($bree, array('direction' => 'forward'));
$bree->link($mirkwood, array('direction' => 'forward', 'label' => 'DANGEROUS'));


// Get the next location from the $shire
$next_stop = $shire->locations('dir:forward');

// Get all DANGEROUS paths joining $bree
$hazards = $bree->locations('rel:DANGEROUS');


// Destroy a node

MeshTools::DeleteNode($the_ring);
Example #3
0
    'name VARCHAR(20)',
    'guarded TINYINT(1) DEFAULT 1',
);

MeshTools::CommitNodeType('locations', $attributes);

// Treasures
$attributes = array(
    'name VARCHAR(20)',
);

MeshTools::CommitNodeType('treasures', $attributes);


// Next, define the link types (ie., how each node types links to any other
// node type)

// Hobbits can link to Locations
MeshTools::CommitLinkType('hobbits', 'locations');

// Hobbits can link to Treasures
MeshTools::CommitLinkType('hobbits', 'treasures');

// Hobbits can link to Hobbits (with named relationships)
// NOTE: We will be using the built-in 'label' attribute to identify friendship (ie. 'eq:label:friendship')
MeshTools::CommitLinkType('hobbits', 'hobbits');

// Locations can link to Locations (with direction)
// NOTE: We will be using the built-in 'direction' attribute to identify direction (ie. 'dir:forward')
MeshTools::CommitLinkType('locations', 'locations');
Example #4
0
    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));
    }
Example #5
0
    public static function SetDefaultContext($name)
    {
        if ('*' == $name)
        {
            throw new Exception("Default context cannot be '*'");
        }
        else
        {
            $context_pk = self::GetContextPks($name);

            self::$_DefaultContextPk    = $context_pk[0];
            self::$_DefaultContext      = $name;
        }
    }
Example #6
0
    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);
        }
    }
Example #7
0
 public function __construct()
 {
     // Figure out context
     $this->_context_pks = implode(',', MeshTools::GetContextPks());
 }
Example #8
0
 public function __construct()
 {
     // Set the default context if available
     $this->context = MeshTools::GetContext();
 }
Example #9
0
    public function __call($method, $params)
    {
        //var_dump("Getting $method from a ".get_class($this));

        if (! isset($this->_cache[$method]) || ! empty($params))        // always refetch when $params is not empty
        {
            if (MeshTools::IsNodeType($method))
            {
                $cluster = new Cluster($this->_callChain);
                $cluster->_callChain->push($method, $params);

                if (empty($params))        // only cache when $params is empty
                {
                    $this->_cache[$method] = $cluster;
                }

                return $cluster;
            }
            else
            {
                $this->_fetch();        // @todo: disable caching when $params is set
            }
        }

        if (! empty($params) && ! MeshTools::IsNodeType($method))
        {
            throw new Exception('Parameters cannot be supplied for field of a node');
        }

        return $this->_cache[$method];
    }