Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed unqualified keys for nodes #214

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Baum

[![Build Status](https://travis-ci.org/etrepat/baum.png?branch=master)](https://travis-ci.org/etrepat/baum)
[![StyleCI](https://styleci.io/repos/51155875/shield)](https://styleci.io/repos/51155875)

Baum is an implementation of the [Nested Set](http://en.wikipedia.org/wiki/Nested_set_model) pattern for [Laravel 5's](http://laravel.com/) Eloquent ORM.

Expand Down
68 changes: 42 additions & 26 deletions src/Baum/Extensions/Eloquent/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,55 @@

use Illuminate\Database\Eloquent\Collection as BaseCollection;

class Collection extends BaseCollection {

public function toHierarchy() {
$dict = $this->getDictionary();
/**
* Class Collection
* @package Baum\Extensions\Eloquent
*/
class Collection extends BaseCollection
{

/**
* @return BaseCollection
*/
public function toHierarchy()
{
$dict = $this->getDictionary();

// Enforce sorting by $orderColumn setting in Baum\Node instance
uasort($dict, function ($a, $b) {
return ($a->getOrder() >= $b->getOrder()) ? 1 : -1;
});

return new BaseCollection($this->hierarchical($dict));
}

// Enforce sorting by $orderColumn setting in Baum\Node instance
uasort($dict, function($a, $b){
return ($a->getOrder() >= $b->getOrder()) ? 1 : -1;
});
/**
* @param $result
* @return mixed
*/
protected function hierarchical($result)
{
foreach ($result as $key => $node) {
$node->setRelation('children', new BaseCollection);
}

return new BaseCollection($this->hierarchical($dict));
}
$nestedKeys = array();

protected function hierarchical($result) {
foreach($result as $key => $node)
$node->setRelation('children', new BaseCollection);
foreach ($result as $key => $node) {
$parentKey = $node->getParentId();

$nestedKeys = array();
if (!is_null($parentKey) && array_key_exists($parentKey, $result)) {
$result[$parentKey]->children[] = $node;

foreach($result as $key => $node) {
$parentKey = $node->getParentId();
$nestedKeys[] = $node->getKey();
}
}

if ( !is_null($parentKey) && array_key_exists($parentKey, $result) ) {
$result[$parentKey]->children[] = $node;
foreach ($nestedKeys as $key) {
unset($result[$key]);
}

$nestedKeys[] = $node->getKey();
}
return $result;
}

foreach($nestedKeys as $key)
unset($result[$key]);

return $result;
}

}
227 changes: 120 additions & 107 deletions src/Baum/Extensions/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,114 +6,127 @@
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Baum\Extensions\Query\Builder as QueryBuilder;

abstract class Model extends BaseModel {

/**
* Reloads the model from the database.
*
* @return \Baum\Node
*
* @throws ModelNotFoundException
*/
public function reload() {
if ( $this->exists || ($this->areSoftDeletesEnabled() && $this->trashed()) ) {
$fresh = $this->getFreshInstance();

if ( is_null($fresh) )
throw with(new ModelNotFoundException)->setModel(get_called_class());

$this->setRawAttributes($fresh->getAttributes(), true);

$this->setRelations($fresh->getRelations());

$this->exists = $fresh->exists;
} else {
// Revert changes if model is not persisted
$this->attributes = $this->original;
abstract class Model extends BaseModel
{

/**
* Reloads the model from the database.
*
* @return \Baum\Node
*
* @throws ModelNotFoundException
*/
public function reload()
{
if ($this->exists || ($this->areSoftDeletesEnabled() && $this->trashed())) {
$fresh = $this->getFreshInstance();

if (is_null($fresh)) {
throw with(new ModelNotFoundException)->setModel(get_called_class());
}

$this->setRawAttributes($fresh->getAttributes(), true);

$this->setRelations($fresh->getRelations());

$this->exists = $fresh->exists;
} else {
// Revert changes if model is not persisted
$this->attributes = $this->original;
}

return $this;
}

return $this;
}

/**
* Get the observable event names.
*
* @return array
*/
public function getObservableEvents() {
return array_merge(array('moving', 'moved'), parent::getObservableEvents());
}

/**
* Register a moving model event with the dispatcher.
*
* @param Closure|string $callback
* @return void
*/
public static function moving($callback, $priority = 0) {
static::registerModelEvent('moving', $callback, $priority);
}

/**
* Register a moved model event with the dispatcher.
*
* @param Closure|string $callback
* @return void
*/
public static function moved($callback, $priority = 0) {
static::registerModelEvent('moved', $callback, $priority);
}

/**
* Get a new query builder instance for the connection.
*
* @return \Baum\Extensions\Query\Builder
*/
protected function newBaseQueryBuilder() {
$conn = $this->getConnection();

$grammar = $conn->getQueryGrammar();

return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
}

/**
* Returns a fresh instance from the database.
*
* @return \Baum\Node
*/
protected function getFreshInstance() {
if ( $this->areSoftDeletesEnabled() )
return static::withTrashed()->find($this->getKey());

return static::find($this->getKey());
}

/**
* Returns wether soft delete functionality is enabled on the model or not.
*
* @return boolean
*/
public function areSoftDeletesEnabled() {
// To determine if there's a global soft delete scope defined we must
// first determine if there are any, to workaround a non-existent key error.
$globalScopes = $this->getGlobalScopes();

if ( count($globalScopes) === 0 ) return false;

// Now that we're sure that the calling class has some kind of global scope
// we check for the SoftDeletingScope existance
return static::hasGlobalScope(new SoftDeletingScope);
}

/**
* Static method which returns wether soft delete functionality is enabled
* on the model.
*
* @return boolean
*/
public static function softDeletesEnabled() {
return with(new static)->areSoftDeletesEnabled();
}
/**
* Get the observable event names.
*
* @return array
*/
public function getObservableEvents()
{
return array_merge(array('moving', 'moved'), parent::getObservableEvents());
}

/**
* Register a moving model event with the dispatcher.
*
* @param Closure|string $callback
* @return void
*/
public static function moving($callback, $priority = 0)
{
static::registerModelEvent('moving', $callback, $priority);
}

/**
* Register a moved model event with the dispatcher.
*
* @param Closure|string $callback
* @return void
*/
public static function moved($callback, $priority = 0)
{
static::registerModelEvent('moved', $callback, $priority);
}

/**
* Get a new query builder instance for the connection.
*
* @return \Baum\Extensions\Query\Builder
*/
protected function newBaseQueryBuilder()
{
$conn = $this->getConnection();

$grammar = $conn->getQueryGrammar();

return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
}

/**
* Returns a fresh instance from the database.
*
* @return \Baum\Node
*/
protected function getFreshInstance()
{
if ($this->areSoftDeletesEnabled()) {
return static::withTrashed()->find($this->getKey());
}

return static::find($this->getKey());
}

/**
* Returns wether soft delete functionality is enabled on the model or not.
*
* @return boolean
*/
public function areSoftDeletesEnabled()
{
// To determine if there's a global soft delete scope defined we must
// first determine if there are any, to workaround a non-existent key error.
$globalScopes = $this->getGlobalScopes();

if (count($globalScopes) === 0) {
return false;
}

// Now that we're sure that the calling class has some kind of global scope
// we check for the SoftDeletingScope existance
return static::hasGlobalScope(new SoftDeletingScope);
}

/**
* Static method which returns wether soft delete functionality is enabled
* on the model.
*
* @return boolean
*/
public static function softDeletesEnabled()
{
return with(new static)->areSoftDeletesEnabled();
}

}
68 changes: 37 additions & 31 deletions src/Baum/Extensions/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,42 @@

use Illuminate\Database\Query\Builder as BaseBuilder;

class Builder extends BaseBuilder {

/**
* Replace the "order by" clause of the current query.
*
* @param string $column
* @param string $direction
* @return \Illuminate\Database\Query\Builder|static
*/
public function reOrderBy($column, $direction = 'asc') {
$this->orders = null;

if ( !is_null($column) ) return $this->orderBy($column, $direction);

return $this;
}

/**
* Execute an aggregate function on the database.
*
* @param string $function
* @param array $columns
* @return mixed
*/
public function aggregate($function, $columns = array('*')) {
// Postgres doesn't like ORDER BY when there's no GROUP BY clause
if ( !isset($this->groups) )
$this->reOrderBy(null);

return parent::aggregate($function, $columns);
}
class Builder extends BaseBuilder
{

/**
* Replace the "order by" clause of the current query.
*
* @param string $column
* @param string $direction
* @return \Baum\Extensions\Query\Builder|static
*/
public function reOrderBy($column, $direction = 'asc')
{
$this->orders = null;

if (!is_null($column)) {
return $this->orderBy($column, $direction);
}

return $this;
}

/**
* Execute an aggregate function on the database.
*
* @param string $function
* @param array $columns
* @return mixed
*/
public function aggregate($function, $columns = array('*'))
{
// Postgres doesn't like ORDER BY when there's no GROUP BY clause
if (!isset($this->groups)) {
$this->reOrderBy(null);
}

return parent::aggregate($function, $columns);
}

}
Loading