diff --git a/.gitignore b/.gitignore
index a439bd57..826d2ac0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/vendor
composer.lock
.vscode
+.phpunit.result.cache
diff --git a/composer.json b/composer.json
index bc13002f..1be5191a 100644
--- a/composer.json
+++ b/composer.json
@@ -12,16 +12,16 @@
}
],
"require": {
- "php": ">=7.0.0",
- "illuminate/database": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|~5.9.0|~6.0.0",
- "illuminate/events": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|~5.9.0|~6.0.0",
- "illuminate/support": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|~5.9.0|~6.0.0"
+ "php": ">=7.2.0",
+ "illuminate/database": "^6.0",
+ "illuminate/events": "^6.0",
+ "illuminate/support": "^6.0"
},
"require-dev": {
- "d11wtq/boris": "~1.0.10",
+ "d11wtq/boris": "^1.0",
"doctrine/dbal": "*",
"mockery/mockery": "^1.0",
- "phpunit/phpunit": "^7.0",
+ "phpunit/phpunit": "^8.0",
"squizlabs/php_codesniffer": "^3.4"
},
"autoload": {
diff --git a/src/Console/BaumCommand.php b/src/Console/BaumCommand.php
index 56394739..3c2054ba 100644
--- a/src/Console/BaumCommand.php
+++ b/src/Console/BaumCommand.php
@@ -1,34 +1,37 @@
line('Baum version ' . Baum::VERSION . '');
- $this->line('A Nested Set pattern implementation for the Eloquent ORM.');
- $this->line('Copyright (c) 2013 Estanislau Trepat');
- }
+ /**
+ * Execute the console command.
+ *
+ * @return void
+ */
+ public function fire()
+ {
+ $this->line('Baum version ' . Baum::VERSION . '');
+ $this->line('A Nested Set pattern implementation for the Eloquent ORM.');
+ $this->line('Copyright (c) 2013 Estanislau Trepat');
+ }
}
diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php
index 8c273b7b..8ba1f305 100644
--- a/src/Console/InstallCommand.php
+++ b/src/Console/InstallCommand.php
@@ -1,4 +1,5 @@
migrator = $migrator;
- $this->modeler = $modeler;
- }
-
- /**
- * Execute the console command.
- *
- * Basically, we'll write the migration and model stubs out to disk inflected
- * with the name provided. Once its done, we'll `dump-autoload` for the entire
- * framework to make sure that the new classes are registered by the class
- * loaders.
- *
- * @return void
- */
- public function fire() {
- $name = $this->input->getArgument('name');
-
- $this->writeMigration($name);
-
- $this->writeModel($name);
-
- }
-
- /**
- * Get the command arguments
- *
- * @return array
- */
- protected function getArguments() {
- return array(
- array('name', InputArgument::REQUIRED, 'Name to use for the scaffolding of the migration and model.')
- );
- }
-
- /**
- * Write the migration file to disk.
- *
- * @param string $name
- * @return string
- */
- protected function writeMigration($name) {
- $output = pathinfo($this->migrator->create($name, $this->getMigrationsPath()), PATHINFO_FILENAME);
-
- $this->line(" create $output");
- }
-
- /**
- * Write the model file to disk.
- *
- * @param string $name
- * @return string
- */
- protected function writeModel($name) {
- $output = pathinfo($this->modeler->create($name, $this->getModelsPath()), PATHINFO_FILENAME);
-
- $this->line(" create $output");
- }
-
- /**
- * Get the path to the migrations directory.
- *
- * @return string
- */
- protected function getMigrationsPath() {
- return $this->laravel['path.database'].'/migrations';
- }
-
- /**
- * Get the path to the models directory.
- *
- * @return string
- */
- protected function getModelsPath() {
- return $this->laravel['path.base'];
- }
+class InstallCommand extends Command
+{
+
+ /**
+ * The console command name.
+ *
+ * @var string
+ */
+ protected $name = 'baum:install';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Scaffolds a new migration and model suitable for Baum.';
+
+ /**
+ * Migration generator instance
+ *
+ * @var Baum\Generators\MigrationGenerator
+ */
+ protected $migrator;
+
+ /**
+ * Model generator instance
+ *
+ * @var Baum\Generators\ModelGenerator
+ */
+ protected $modeler;
+
+ /**
+ * Create a new command instance
+ *
+ * @return void
+ */
+ public function __construct(MigrationGenerator $migrator, ModelGenerator $modeler)
+ {
+ parent::__construct();
+
+ $this->migrator = $migrator;
+ $this->modeler = $modeler;
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * Basically, we'll write the migration and model stubs out to disk inflected
+ * with the name provided. Once its done, we'll `dump-autoload` for the entire
+ * framework to make sure that the new classes are registered by the class
+ * loaders.
+ *
+ * @return void
+ */
+ public function fire()
+ {
+ $name = $this->input->getArgument('name');
+
+ $this->writeMigration($name);
+
+ $this->writeModel($name);
+
+ }
+
+ /**
+ * Get the command arguments
+ *
+ * @return array
+ */
+ protected function getArguments()
+ {
+ return array(
+ array('name', InputArgument::REQUIRED, 'Name to use for the scaffolding of the migration and model.')
+ );
+ }
+
+ /**
+ * Write the migration file to disk.
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function writeMigration($name)
+ {
+ $output = pathinfo($this->migrator->create($name, $this->getMigrationsPath()), PATHINFO_FILENAME);
+
+ $this->line(" create $output");
+ }
+
+ /**
+ * Write the model file to disk.
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function writeModel($name)
+ {
+ $output = pathinfo($this->modeler->create($name, $this->getModelsPath()), PATHINFO_FILENAME);
+
+ $this->line(" create $output");
+ }
+
+ /**
+ * Get the path to the migrations directory.
+ *
+ * @return string
+ */
+ protected function getMigrationsPath()
+ {
+ return $this->laravel['path.database'] . '/migrations';
+ }
+
+ /**
+ * Get the path to the models directory.
+ *
+ * @return string
+ */
+ protected function getModelsPath()
+ {
+ return $this->laravel['path.base'];
+ }
}
diff --git a/src/Extensions/Eloquent/Collection.php b/src/Extensions/Eloquent/Collection.php
index e6fa41c2..fd91ea4a 100644
--- a/src/Extensions/Eloquent/Collection.php
+++ b/src/Extensions/Eloquent/Collection.php
@@ -1,41 +1,45 @@
getDictionary();
+ 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;
- });
+ // 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));
- }
+ return new BaseCollection($this->hierarchical($dict));
+ }
- protected function hierarchical($result) {
- foreach($result as $key => $node)
- $node->setRelation('children', new BaseCollection);
+ protected function hierarchical($result)
+ {
+ foreach ($result as $key => $node)
+ $node->setRelation('children', new BaseCollection);
- $nestedKeys = array();
+ $nestedKeys = array();
- foreach($result as $key => $node) {
- $parentKey = $node->getParentId();
+ foreach ($result as $key => $node) {
+ $parentKey = $node->getParentId();
- if ( !is_null($parentKey) && array_key_exists($parentKey, $result) ) {
- $result[$parentKey]->children[] = $node;
+ if (!is_null($parentKey) && array_key_exists($parentKey, $result)) {
+ $result[$parentKey]->children[] = $node;
- $nestedKeys[] = $node->getKey();
- }
- }
+ $nestedKeys[] = $node->getKey();
+ }
+ }
- foreach($nestedKeys as $key)
- unset($result[$key]);
+ foreach ($nestedKeys as $key)
+ unset($result[$key]);
- return $result;
- }
+ return $result;
+ }
}
diff --git a/src/Extensions/Eloquent/Model.php b/src/Extensions/Eloquent/Model.php
index 946960cc..daa4b07d 100644
--- a/src/Extensions/Eloquent/Model.php
+++ b/src/Extensions/Eloquent/Model.php
@@ -1,4 +1,5 @@
exists || ($this->areSoftDeletesEnabled() && $this->trashed())) {
+ $fresh = $this->getFreshInstance();
- /**
- * 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());
- if ( is_null($fresh) )
- throw with(new ModelNotFoundException)->setModel(get_called_class());
+ $this->setRawAttributes($fresh->getAttributes(), true);
- $this->setRawAttributes($fresh->getAttributes(), true);
+ $this->setRelations($fresh->getRelations());
- $this->setRelations($fresh->getRelations());
+ $this->exists = $fresh->exists;
+ } else {
+ // Revert changes if model is not persisted
+ $this->attributes = $this->original;
+ }
- $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) {
- static::registerModelEvent('moving', $callback);
- }
-
- /**
- * Register a moved model event with the dispatcher.
- *
- * @param Closure|string $callback
- * @return void
- */
- public static function moved($callback) {
- static::registerModelEvent('moved', $callback);
- }
-
- /**
- * 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)
+ {
+ static::registerModelEvent('moving', $callback);
+ }
+
+ /**
+ * Register a moved model event with the dispatcher.
+ *
+ * @param Closure|string $callback
+ * @return void
+ */
+ public static function moved($callback)
+ {
+ static::registerModelEvent('moved', $callback);
+ }
+
+ /**
+ * 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();
+ }
}
diff --git a/src/Extensions/Query/Builder.php b/src/Extensions/Query/Builder.php
index 801a9209..ec411aed 100644
--- a/src/Extensions/Query/Builder.php
+++ b/src/Extensions/Query/Builder.php
@@ -4,40 +4,43 @@
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 = null, $direction = 'asc') {
- $this->{$this->unions ? 'unionOrders' : 'orders'} = null;
-
- if (!is_null($column)) {
- return parent::orderBy($column, $direction);
- }
+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 = null, $direction = 'asc')
+ {
+ $this->{$this->unions ? 'unionOrders' : 'orders'} = null;
+
+ if (!is_null($column)) {
+ return parent::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 $this;
}
- return parent::aggregate($function, $columns);
- }
+ /**
+ * 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);
+ }
/**
* Determine if any rows exist for the current query.
@@ -46,11 +49,11 @@ public function aggregate($function, $columns = array('*')) {
*/
public function exists()
{
- if (!isset($this->groups)) {
- $this->reOrderBy(null);
- }
+ if (!isset($this->groups)) {
+ $this->reOrderBy(null);
+ }
- return parent::exists();
+ return parent::exists();
}
}
diff --git a/src/Generators/Generator.php b/src/Generators/Generator.php
index de02fab4..50ad18b5 100644
--- a/src/Generators/Generator.php
+++ b/src/Generators/Generator.php
@@ -1,93 +1,102 @@
files = $files;
- }
+ /**
+ * Create a new MigrationGenerator instance.
+ *
+ * @param \Illuminate\Filesystem\Filesysmte $files
+ * @return void
+ */
+ function __construct(Filesystem $files)
+ {
+ $this->files = $files;
+ }
- /**
- * Get the path to the stubs.
- *
- * @return string
- */
- public function getStubPath() {
- return __DIR__.'/stubs';
- }
+ /**
+ * Get the path to the stubs.
+ *
+ * @return string
+ */
+ public function getStubPath()
+ {
+ return __DIR__ . '/stubs';
+ }
- /**
- * Get the filesystem instance.
- *
- * @return \Illuminate\Filesystem\Filesystem
- */
- public function getFilesystem() {
- return $this->files;
- }
+ /**
+ * Get the filesystem instance.
+ *
+ * @return \Illuminate\Filesystem\Filesystem
+ */
+ public function getFilesystem()
+ {
+ return $this->files;
+ }
- /**
- * Get the given stub by name.
- *
- * @param string $table
- * @return void
- */
- protected function getStub($name) {
- if ( stripos($name, '.php') === FALSE )
- $name = $name . '.php';
+ /**
+ * Get the given stub by name.
+ *
+ * @param string $table
+ * @return void
+ */
+ protected function getStub($name)
+ {
+ if (stripos($name, '.php') === false)
+ $name = $name . '.php';
- return $this->files->get($this->getStubPath() . '/' . $name);
- }
+ return $this->files->get($this->getStubPath() . '/' . $name);
+ }
- /**
- * Parse the provided stub and replace via the array given.
- *
- * @param string $stub
- * @param string $replacements
- * @return string
- */
- protected function parseStub($stub, $replacements=array()) {
- $output = $stub;
+ /**
+ * Parse the provided stub and replace via the array given.
+ *
+ * @param string $stub
+ * @param string $replacements
+ * @return string
+ */
+ protected function parseStub($stub, $replacements = array())
+ {
+ $output = $stub;
- foreach ($replacements as $key => $replacement) {
- $search = '{{'.$key.'}}';
- $output = str_replace($search, $replacement, $output);
- }
+ foreach ($replacements as $key => $replacement) {
+ $search = '{{' . $key . '}}';
+ $output = str_replace($search, $replacement, $output);
+ }
- return $output;
- }
+ return $output;
+ }
- /**
- * Inflect to a class name
- *
- * @param string $input
- * @return string
- */
- protected function classify($input) {
- return studly_case(str_singular($input));
- }
+ /**
+ * Inflect to a class name
+ *
+ * @param string $input
+ * @return string
+ */
+ protected function classify($input)
+ {
+ return studly_case(str_singular($input));
+ }
- /**
- * Inflect to table name
- *
- * @param string $input
- * @return string
- */
- protected function tableize($input) {
- return snake_case(str_plural($input));
- }
+ /**
+ * Inflect to table name
+ *
+ * @param string $input
+ * @return string
+ */
+ protected function tableize($input)
+ {
+ return snake_case(str_plural($input));
+ }
}
diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php
index c7a052e9..360872fd 100644
--- a/src/Generators/MigrationGenerator.php
+++ b/src/Generators/MigrationGenerator.php
@@ -1,65 +1,72 @@
getPath($name, $path);
+ /**
+ * Create a new migration at the given path.
+ *
+ * @param string $name
+ * @param string $path
+ * @return string
+ */
+ public function create($name, $path)
+ {
+ $path = $this->getPath($name, $path);
- $stub = $this->getStub('migration');
+ $stub = $this->getStub('migration');
- $this->files->put($path, $this->parseStub($stub, array(
- 'table' => $this->tableize($name),
- 'class' => $this->getMigrationClassName($name)
- )));
+ $this->files->put($path, $this->parseStub($stub, array(
+ 'table' => $this->tableize($name),
+ 'class' => $this->getMigrationClassName($name)
+ )));
- return $path;
- }
+ return $path;
+ }
- /**
- * Get the migration name.
- *
- * @param string $name
- * @return string
- */
- protected function getMigrationName($name) {
- return 'create_' . $this->tableize($name) . '_table';
- }
+ /**
+ * Get the migration name.
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function getMigrationName($name)
+ {
+ return 'create_' . $this->tableize($name) . '_table';
+ }
- /**
- * Get the name for the migration class.
- *
- * @param string $name
- */
- protected function getMigrationClassName($name) {
- return $this->classify($this->getMigrationName($name));
- }
+ /**
+ * Get the name for the migration class.
+ *
+ * @param string $name
+ */
+ protected function getMigrationClassName($name)
+ {
+ return $this->classify($this->getMigrationName($name));
+ }
- /**
- * Get the full path name to the migration.
- *
- * @param string $name
- * @param string $path
- * @return string
- */
- protected function getPath($name, $path) {
- return $path . '/' . $this->getDatePrefix() . '_' . $this->getMigrationName($name) . '.php';
- }
+ /**
+ * Get the full path name to the migration.
+ *
+ * @param string $name
+ * @param string $path
+ * @return string
+ */
+ protected function getPath($name, $path)
+ {
+ return $path . '/' . $this->getDatePrefix() . '_' . $this->getMigrationName($name) . '.php';
+ }
- /**
- * Get the date prefix for the migration.
- *
- * @return int
- */
- protected function getDatePrefix() {
- return date('Y_m_d_His');
- }
+ /**
+ * Get the date prefix for the migration.
+ *
+ * @return int
+ */
+ protected function getDatePrefix()
+ {
+ return date('Y_m_d_His');
+ }
}
diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php
index b5ebf5dd..dd9b2394 100644
--- a/src/Generators/ModelGenerator.php
+++ b/src/Generators/ModelGenerator.php
@@ -1,37 +1,41 @@
getPath($name, $path);
-
- $stub = $this->getStub('model');
-
- $this->files->put($path, $this->parseStub($stub, array(
- 'table' => $this->tableize($name),
- 'class' => $this->classify($name)
- )));
-
- return $path;
- }
-
- /**
- * Get the full path name to the migration.
- *
- * @param string $name
- * @param string $path
- * @return string
- */
- protected function getPath($name, $path) {
- return $path . '/' . $this->classify($name) . '.php';
- }
+class ModelGenerator extends Generator
+{
+
+ /**
+ * Create a new model at the given path.
+ *
+ * @param string $name
+ * @param string $path
+ * @return string
+ */
+ public function create($name, $path)
+ {
+ $path = $this->getPath($name, $path);
+
+ $stub = $this->getStub('model');
+
+ $this->files->put($path, $this->parseStub($stub, array(
+ 'table' => $this->tableize($name),
+ 'class' => $this->classify($name)
+ )));
+
+ return $path;
+ }
+
+ /**
+ * Get the full path name to the migration.
+ *
+ * @param string $name
+ * @param string $path
+ * @return string
+ */
+ protected function getPath($name, $path)
+ {
+ return $path . '/' . $this->classify($name) . '.php';
+ }
}
diff --git a/src/Generators/stubs/migration.php b/src/Generators/stubs/migration.php
index 1ad33068..77cfa5ed 100644
--- a/src/Generators/stubs/migration.php
+++ b/src/Generators/stubs/migration.php
@@ -5,38 +5,42 @@
class {{class}} extends Migration {
- /**
- * Run the migrations.
- *
- * @return void
- */
- public function up() {
- Schema::create('{{table}}', function(Blueprint $table) {
- // These columns are needed for Baum's Nested Set implementation to work.
- // Column names may be changed, but they *must* all exist and be modified
- // in the model.
- // Take a look at the model scaffold comments for details.
- // We add indexes on parent_id, lft, rgt columns by default.
- $table->increments('id');
- $table->integer('parent_id')->nullable()->index();
- $table->integer('lft')->nullable()->index();
- $table->integer('rgt')->nullable()->index();
- $table->integer('depth')->nullable();
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public
+ function up()
+ {
+ Schema::create('{{table}}', function (Blueprint $table) {
+ // These columns are needed for Baum's Nested Set implementation to work.
+ // Column names may be changed, but they *must* all exist and be modified
+ // in the model.
+ // Take a look at the model scaffold comments for details.
+ // We add indexes on parent_id, lft, rgt columns by default.
+ $table->increments('id');
+ $table->integer('parent_id')->nullable()->index();
+ $table->integer('lft')->nullable()->index();
+ $table->integer('rgt')->nullable()->index();
+ $table->integer('depth')->nullable();
- // Add needed columns here (f.ex: name, slug, path, etc.)
- // $table->string('name', 255);
+ // Add needed columns here (f.ex: name, slug, path, etc.)
+ // $table->string('name', 255);
- $table->timestamps();
- });
- }
+ $table->timestamps();
+ });
+ }
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down() {
- Schema::drop('{{table}}');
- }
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public
+ function down()
+ {
+ Schema::drop('{{table}}');
+ }
}
diff --git a/src/Generators/stubs/model.php b/src/Generators/stubs/model.php
index 0574e787..506c42d6 100644
--- a/src/Generators/stubs/model.php
+++ b/src/Generators/stubs/model.php
@@ -1,102 +1,104 @@
node = $node;
- $this->target = $this->resolveNode($target);
- $this->position = $position;
-
- $this->setEventDispatcher($node->getEventDispatcher());
- }
-
- /**
- * Easy static accessor for performing a move operation.
- *
- * @param \Baum\Node $node
- * @param \Baum\Node|int $target
- * @param string $position
- * @return \Baum\Node
- */
- public static function to($node, $target, $position) {
- $instance = new static($node, $target, $position);
-
- return $instance->perform();
- }
-
- /**
- * Perform the move operation.
- *
- * @return \Baum\Node
- */
- public function perform() {
- $this->guardAgainstImpossibleMove();
-
- if ( $this->fireMoveEvent('moving') === false )
- return $this->node;
-
- if ( $this->hasChange() ) {
- $self = $this;
-
- $this->node->getConnection()->transaction(function() use ($self) {
- $self->updateStructure();
- });
-
- $this->target->reload();
-
- $this->node->setDepthWithSubtree();
-
- $this->node->reload();
+ * Move
+ */
+class Move
+{
+
+ /**
+ * Node on which the move operation will be performed
+ *
+ * @var \Baum\Node
+ */
+ protected $node = null;
+
+ /**
+ * Destination node
+ *
+ * @var \Baum\Node | int
+ */
+ protected $target = null;
+
+ /**
+ * Move target position, one of: child, left, right, root
+ *
+ * @var string
+ */
+ protected $position = null;
+
+ /**
+ * Memoized 1st boundary.
+ *
+ * @var int
+ */
+ protected $_bound1 = null;
+
+ /**
+ * Memoized 2nd boundary.
+ *
+ * @var int
+ */
+ protected $_bound2 = null;
+
+ /**
+ * Memoized boundaries array.
+ *
+ * @var array
+ */
+ protected $_boundaries = null;
+
+ /**
+ * The event dispatcher instance.
+ *
+ * @var \Illuminate\Events\Dispatcher
+ */
+ protected static $dispatcher;
+
+ /**
+ * Create a new Move class instance.
+ *
+ * @param \Baum\Node $node
+ * @param \Baum\Node|int $target
+ * @param string $position
+ * @return void
+ */
+ public function __construct($node, $target, $position)
+ {
+ $this->node = $node;
+ $this->target = $this->resolveNode($target);
+ $this->position = $position;
+
+ $this->setEventDispatcher($node->getEventDispatcher());
+ }
+
+ /**
+ * Easy static accessor for performing a move operation.
+ *
+ * @param \Baum\Node $node
+ * @param \Baum\Node|int $target
+ * @param string $position
+ * @return \Baum\Node
+ */
+ public static function to($node, $target, $position)
+ {
+ $instance = new static($node, $target, $position);
+
+ return $instance->perform();
}
- $this->fireMoveEvent('moved', false);
-
- return $this->node;
- }
-
- /**
- * Runs the SQL query associated with the update of the indexes affected
- * by the move operation.
- *
- * @return int
- */
- public function updateStructure() {
- list($a, $b, $c, $d) = $this->boundaries();
-
- // select the rows between the leftmost & the rightmost boundaries and apply a lock
- $this->applyLockBetween($a, $d);
-
- $connection = $this->node->getConnection();
- $grammar = $connection->getQueryGrammar();
-
- $currentId = $this->quoteIdentifier($this->node->getKey());
- $parentId = $this->quoteIdentifier($this->parentId());
- $leftColumn = $this->node->getLeftColumnName();
- $rightColumn = $this->node->getRightColumnName();
- $parentColumn = $this->node->getParentColumnName();
- $wrappedLeft = $grammar->wrap($leftColumn);
- $wrappedRight = $grammar->wrap($rightColumn);
- $wrappedParent = $grammar->wrap($parentColumn);
- $wrappedId = $grammar->wrap($this->node->getKeyName());
-
- $lftSql = "CASE
+ /**
+ * Perform the move operation.
+ *
+ * @return \Baum\Node
+ */
+ public function perform()
+ {
+ $this->guardAgainstImpossibleMove();
+
+ if ($this->fireMoveEvent('moving') === false)
+ return $this->node;
+
+ if ($this->hasChange()) {
+ $self = $this;
+
+ $this->node->getConnection()->transaction(function () use ($self) {
+ $self->updateStructure();
+ });
+
+ $this->target->reload();
+
+ $this->node->setDepthWithSubtree();
+
+ $this->node->reload();
+ }
+
+ $this->fireMoveEvent('moved', false);
+
+ return $this->node;
+ }
+
+ /**
+ * Runs the SQL query associated with the update of the indexes affected
+ * by the move operation.
+ *
+ * @return int
+ */
+ public function updateStructure()
+ {
+ list($a, $b, $c, $d) = $this->boundaries();
+
+ // select the rows between the leftmost & the rightmost boundaries and apply a lock
+ $this->applyLockBetween($a, $d);
+
+ $connection = $this->node->getConnection();
+ $grammar = $connection->getQueryGrammar();
+
+ $currentId = $this->quoteIdentifier($this->node->getKey());
+ $parentId = $this->quoteIdentifier($this->parentId());
+ $leftColumn = $this->node->getLeftColumnName();
+ $rightColumn = $this->node->getRightColumnName();
+ $parentColumn = $this->node->getParentColumnName();
+ $wrappedLeft = $grammar->wrap($leftColumn);
+ $wrappedRight = $grammar->wrap($rightColumn);
+ $wrappedParent = $grammar->wrap($parentColumn);
+ $wrappedId = $grammar->wrap($this->node->getKeyName());
+
+ $lftSql = "CASE
WHEN $wrappedLeft BETWEEN $a AND $b THEN $wrappedLeft + $d - $b
WHEN $wrappedLeft BETWEEN $c AND $d THEN $wrappedLeft + $a - $c
ELSE $wrappedLeft END";
- $rgtSql = "CASE
+ $rgtSql = "CASE
WHEN $wrappedRight BETWEEN $a AND $b THEN $wrappedRight + $d - $b
WHEN $wrappedRight BETWEEN $c AND $d THEN $wrappedRight + $a - $c
ELSE $wrappedRight END";
- $parentSql = "CASE
+ $parentSql = "CASE
WHEN $wrappedId = $currentId THEN $parentId
ELSE $wrappedParent END";
- $updateConditions = array(
- $leftColumn => $connection->raw($lftSql),
- $rightColumn => $connection->raw($rgtSql),
- $parentColumn => $connection->raw($parentSql)
- );
-
- if ( $this->node->timestamps )
- $updateConditions[$this->node->getUpdatedAtColumn()] = $this->node->freshTimestamp();
-
- return $this->node
- ->newNestedSetQuery()
- ->where(function($query) use ($leftColumn, $rightColumn, $a, $d) {
- $query->whereBetween($leftColumn, array($a, $d))
- ->orWhereBetween($rightColumn, array($a, $d));
- })
- ->update($updateConditions);
- }
-
- /**
- * Resolves suplied node. Basically returns the node unchanged if
- * supplied parameter is an instance of \Baum\Node. Otherwise it will try
- * to find the node in the database.
- *
- * @param \Baum\node|int
- * @return \Baum\Node
- */
- protected function resolveNode($node) {
- if ( $node instanceof \Baum\Node ) return $node->reload();
-
- return $this->node->newNestedSetQuery()->find($node);
- }
-
- /**
- * Check wether the current move is possible and if not, rais an exception.
- *
- * @return void
- */
- protected function guardAgainstImpossibleMove() {
- if ( !$this->node->exists )
- throw new MoveNotPossibleException('A new node cannot be moved.');
-
- if ( array_search($this->position, array('child', 'left', 'right', 'root')) === FALSE )
- throw new MoveNotPossibleException("Position should be one of ['child', 'left', 'right'] but is {$this->position}.");
-
- if ( !$this->promotingToRoot() ) {
- if ( is_null($this->target) ) {
- if ( $this->position === 'left' || $this->position === 'right' )
- throw new MoveNotPossibleException("Could not resolve target node. This node cannot move any further to the {$this->position}.");
- else
- throw new MoveNotPossibleException('Could not resolve target node.');
- }
-
- if ( $this->node->equals($this->target) )
- throw new MoveNotPossibleException('A node cannot be moved to itself.');
-
- if ( $this->target->insideSubtree($this->node) )
- throw new MoveNotPossibleException('A node cannot be moved to a descendant of itself (inside moved tree).');
-
- if ( !$this->node->inSameScope($this->target) )
- throw new MoveNotPossibleException('A node cannot be moved to a different scope.');
+ $updateConditions = array(
+ $leftColumn => $connection->raw($lftSql),
+ $rightColumn => $connection->raw($rgtSql),
+ $parentColumn => $connection->raw($parentSql)
+ );
+
+ if ($this->node->timestamps)
+ $updateConditions[$this->node->getUpdatedAtColumn()] = $this->node->freshTimestamp();
+
+ return $this->node
+ ->newNestedSetQuery()
+ ->where(function ($query) use ($leftColumn, $rightColumn, $a, $d) {
+ $query->whereBetween($leftColumn, array($a, $d))
+ ->orWhereBetween($rightColumn, array($a, $d));
+ })
+ ->update($updateConditions);
+ }
+
+ /**
+ * Resolves suplied node. Basically returns the node unchanged if
+ * supplied parameter is an instance of \Baum\Node. Otherwise it will try
+ * to find the node in the database.
+ *
+ * @param \Baum\node|int
+ * @return \Baum\Node
+ */
+ protected function resolveNode($node)
+ {
+ if ($node instanceof \Baum\Node) return $node->reload();
+
+ return $this->node->newNestedSetQuery()->find($node);
+ }
+
+ /**
+ * Check wether the current move is possible and if not, rais an exception.
+ *
+ * @return void
+ */
+ protected function guardAgainstImpossibleMove()
+ {
+ if (!$this->node->exists)
+ throw new MoveNotPossibleException('A new node cannot be moved.');
+
+ if (array_search($this->position, array('child', 'left', 'right', 'root')) === false)
+ throw new MoveNotPossibleException("Position should be one of ['child', 'left', 'right'] but is {$this->position}.");
+
+ if (!$this->promotingToRoot()) {
+ if (is_null($this->target)) {
+ if ($this->position === 'left' || $this->position === 'right')
+ throw new MoveNotPossibleException("Could not resolve target node. This node cannot move any further to the {$this->position}.");
+ else
+ throw new MoveNotPossibleException('Could not resolve target node.');
+ }
+
+ if ($this->node->equals($this->target))
+ throw new MoveNotPossibleException('A node cannot be moved to itself.');
+
+ if ($this->target->insideSubtree($this->node))
+ throw new MoveNotPossibleException('A node cannot be moved to a descendant of itself (inside moved tree).');
+
+ if (!$this->node->inSameScope($this->target))
+ throw new MoveNotPossibleException('A node cannot be moved to a different scope.');
+ }
+ }
+
+ /**
+ * Computes the boundary.
+ *
+ * @return int
+ */
+ protected function bound1()
+ {
+ if (!is_null($this->_bound1)) return $this->_bound1;
+
+ switch ($this->position) {
+ case 'child':
+ $this->_bound1 = $this->target->getRight();
+ break;
+
+ case 'left':
+ $this->_bound1 = $this->target->getLeft();
+ break;
+
+ case 'right':
+ $this->_bound1 = $this->target->getRight() + 1;
+ break;
+
+ case 'root':
+ $this->_bound1 = $this->node->newNestedSetQuery()->max($this->node->getRightColumnName()) + 1;
+ break;
+ }
+
+ $this->_bound1 = (($this->_bound1 > $this->node->getRight()) ? $this->_bound1 - 1 : $this->_bound1);
+ return $this->_bound1;
+ }
+
+ /**
+ * Computes the other boundary.
+ * TODO: Maybe find a better name for this... ¿?
+ *
+ * @return int
+ */
+ protected function bound2()
+ {
+ if (!is_null($this->_bound2)) return $this->_bound2;
+
+ $this->_bound2 = (($this->bound1() > $this->node->getRight()) ? $this->node->getRight() + 1 : $this->node->getLeft() - 1);
+ return $this->_bound2;
}
- }
-
- /**
- * Computes the boundary.
- *
- * @return int
- */
- protected function bound1() {
- if ( !is_null($this->_bound1) ) return $this->_bound1;
-
- switch ( $this->position ) {
- case 'child':
- $this->_bound1 = $this->target->getRight();
- break;
-
- case 'left':
- $this->_bound1 = $this->target->getLeft();
- break;
-
- case 'right':
- $this->_bound1 = $this->target->getRight() + 1;
- break;
-
- case 'root':
- $this->_bound1 = $this->node->newNestedSetQuery()->max($this->node->getRightColumnName()) + 1;
- break;
+
+ /**
+ * Computes the boundaries array.
+ *
+ * @return array
+ */
+ protected function boundaries()
+ {
+ if (!is_null($this->_boundaries)) return $this->_boundaries;
+
+ // we have defined the boundaries of two non-overlapping intervals,
+ // so sorting puts both the intervals and their boundaries in order
+ $this->_boundaries = array(
+ $this->node->getLeft(),
+ $this->node->getRight(),
+ $this->bound1(),
+ $this->bound2()
+ );
+ sort($this->_boundaries);
+
+ return $this->_boundaries;
+ }
+
+ /**
+ * Computes the new parent id for the node being moved.
+ *
+ * @return int
+ */
+ protected function parentId()
+ {
+ switch ($this->position) {
+ case 'root':
+ return null;
+
+ case 'child':
+ return $this->target->getKey();
+
+ default:
+ return $this->target->getParentId();
+ }
+ }
+
+ /**
+ * Check wether there should be changes in the downward tree structure.
+ *
+ * @return boolean
+ */
+ protected function hasChange()
+ {
+ return !($this->bound1() == $this->node->getRight() || $this->bound1() == $this->node->getLeft());
+ }
+
+ /**
+ * Check if we are promoting the provided instance to a root node.
+ *
+ * @return boolean
+ */
+ protected function promotingToRoot()
+ {
+ return ($this->position == 'root');
+ }
+
+ /**
+ * Get the event dispatcher instance.
+ *
+ * @return \Illuminate\Events\Dispatcher
+ */
+ public static function getEventDispatcher()
+ {
+ return static::$dispatcher;
+ }
+
+ /**
+ * Set the event dispatcher instance.
+ *
+ * @param \Illuminate\Events\Dispatcher
+ * @return void
+ */
+ public static function setEventDispatcher(Dispatcher $dispatcher)
+ {
+ static::$dispatcher = $dispatcher;
+ }
+
+ /**
+ * Fire the given move event for the model.
+ *
+ * @param string $event
+ * @param bool $halt
+ * @return mixed
+ */
+ protected function fireMoveEvent($event, $halt = true)
+ {
+ if (!isset(static::$dispatcher)) return true;
+
+ // Basically the same as \Illuminate\Database\Eloquent\Model->fireModelEvent
+ // but we relay the event into the node instance.
+ $event = "eloquent.{$event}: " . get_class($this->node);
+
+ $method = $halt ? 'until' : 'dispatch';
+
+ return static::$dispatcher->$method($event, $this->node);
+ }
+
+ /**
+ * Quotes an identifier for being used in a database query.
+ *
+ * @param mixed $value
+ * @return string
+ */
+ protected function quoteIdentifier($value)
+ {
+ if (is_null($value))
+ return 'NULL';
+
+ $connection = $this->node->getConnection();
+
+ $pdo = $connection->getPdo();
+
+ return $pdo->quote($value);
}
- $this->_bound1 = (($this->_bound1 > $this->node->getRight()) ? $this->_bound1 - 1 : $this->_bound1);
- return $this->_bound1;
- }
-
- /**
- * Computes the other boundary.
- * TODO: Maybe find a better name for this... ¿?
- *
- * @return int
- */
- protected function bound2() {
- if ( !is_null($this->_bound2) ) return $this->_bound2;
-
- $this->_bound2 = (($this->bound1() > $this->node->getRight()) ? $this->node->getRight() + 1 : $this->node->getLeft() - 1);
- return $this->_bound2;
- }
-
- /**
- * Computes the boundaries array.
- *
- * @return array
- */
- protected function boundaries() {
- if ( !is_null($this->_boundaries) ) return $this->_boundaries;
-
- // we have defined the boundaries of two non-overlapping intervals,
- // so sorting puts both the intervals and their boundaries in order
- $this->_boundaries = array(
- $this->node->getLeft() ,
- $this->node->getRight() ,
- $this->bound1() ,
- $this->bound2()
- );
- sort($this->_boundaries);
-
- return $this->_boundaries;
- }
-
- /**
- * Computes the new parent id for the node being moved.
- *
- * @return int
- */
- protected function parentId() {
- switch( $this->position ) {
- case 'root':
- return NULL;
-
- case 'child':
- return $this->target->getKey();
-
- default:
- return $this->target->getParentId();
+ /**
+ * Applies a lock to the rows between the supplied index boundaries.
+ *
+ * @param int $lft
+ * @param int $rgt
+ * @return void
+ */
+ protected function applyLockBetween($lft, $rgt)
+ {
+ $this->node->newQuery()
+ ->where($this->node->getLeftColumnName(), '>=', $lft)
+ ->where($this->node->getRightColumnName(), '<=', $rgt)
+ ->select($this->node->getKeyName())
+ ->lockForUpdate()
+ ->get();
}
- }
-
- /**
- * Check wether there should be changes in the downward tree structure.
- *
- * @return boolean
- */
- protected function hasChange() {
- return !( $this->bound1() == $this->node->getRight() || $this->bound1() == $this->node->getLeft() );
- }
-
- /**
- * Check if we are promoting the provided instance to a root node.
- *
- * @return boolean
- */
- protected function promotingToRoot() {
- return ($this->position == 'root');
- }
-
- /**
- * Get the event dispatcher instance.
- *
- * @return \Illuminate\Events\Dispatcher
- */
- public static function getEventDispatcher() {
- return static::$dispatcher;
- }
-
- /**
- * Set the event dispatcher instance.
- *
- * @param \Illuminate\Events\Dispatcher
- * @return void
- */
- public static function setEventDispatcher(Dispatcher $dispatcher) {
- static::$dispatcher = $dispatcher;
- }
-
- /**
- * Fire the given move event for the model.
- *
- * @param string $event
- * @param bool $halt
- * @return mixed
- */
- protected function fireMoveEvent($event, $halt = true) {
- if ( !isset(static::$dispatcher) ) return true;
-
- // Basically the same as \Illuminate\Database\Eloquent\Model->fireModelEvent
- // but we relay the event into the node instance.
- $event = "eloquent.{$event}: ".get_class($this->node);
-
- $method = $halt ? 'until' : 'dispatch';
-
- return static::$dispatcher->$method($event, $this->node);
- }
-
- /**
- * Quotes an identifier for being used in a database query.
- *
- * @param mixed $value
- * @return string
- */
- protected function quoteIdentifier($value) {
- if ( is_null($value) )
- return 'NULL';
-
- $connection = $this->node->getConnection();
-
- $pdo = $connection->getPdo();
-
- return $pdo->quote($value);
- }
-
- /**
- * Applies a lock to the rows between the supplied index boundaries.
- *
- * @param int $lft
- * @param int $rgt
- * @return void
- */
- protected function applyLockBetween($lft, $rgt) {
- $this->node->newQuery()
- ->where($this->node->getLeftColumnName(), '>=', $lft)
- ->where($this->node->getRightColumnName(), '<=', $rgt)
- ->select($this->node->getKeyName())
- ->lockForUpdate()
- ->get();
- }
}
diff --git a/src/MoveNotPossibleException.php b/src/MoveNotPossibleException.php
index 4832ec2c..8ca8cf19 100644
--- a/src/MoveNotPossibleException.php
+++ b/src/MoveNotPossibleException.php
@@ -1,4 +1,7 @@
parentColumn;
}
/**
* Get the table qualified parent column name.
- *
- * @return string
- */
- public function getQualifiedParentColumnName() {
+ *
+ * @return string
+ */
+ public function getQualifiedParentColumnName()
+ {
$this->qualifyColumn($this->getParentColumnName());
}
@@ -26,7 +29,8 @@ public function getQualifiedParentColumnName() {
*
* @return string
*/
- public function getLeftColumnName() {
+ public function getLeftColumnName()
+ {
return $this->leftColumn;
}
@@ -35,7 +39,8 @@ public function getLeftColumnName() {
*
* @return string
*/
- public function getQualifiedLeftColumnName() {
+ public function getQualifiedLeftColumnName()
+ {
return $this->qualifyColumn($this->getLeftColumnName());
}
@@ -44,8 +49,9 @@ public function getQualifiedLeftColumnName() {
*
* @return int
*/
- public function getLeft() {
- return $this->getAttribute($this->getLeftColumnName());
+ public function getLeft()
+ {
+ return $this->getAttribute($this->getLeftColumnName());
}
/**
@@ -53,8 +59,9 @@ public function getLeft() {
*
* @return string
*/
- public function getRightColumnName() {
- return $this->rightColumn;
+ public function getRightColumnName()
+ {
+ return $this->rightColumn;
}
/**
@@ -62,8 +69,9 @@ public function getRightColumnName() {
*
* @return string
*/
- public function getQualifiedRightColumnName() {
- return $this->getTable() . '.' . $this->getRightColumnName();
+ public function getQualifiedRightColumnName()
+ {
+ return $this->getTable() . '.' . $this->getRightColumnName();
}
/**
@@ -71,8 +79,9 @@ public function getQualifiedRightColumnName() {
*
* @return int
*/
- public function getRight() {
- return $this->getAttribute($this->getRightColumnName());
+ public function getRight()
+ {
+ return $this->getAttribute($this->getRightColumnName());
}
/**
@@ -80,8 +89,9 @@ public function getRight() {
*
* @return string
*/
- public function getDepthColumnName() {
- return $this->depthColumn;
+ public function getDepthColumnName()
+ {
+ return $this->depthColumn;
}
/**
@@ -89,8 +99,9 @@ public function getDepthColumnName() {
*
* @return string
*/
- public function getQualifiedDepthColumnName() {
- return $this->getTable() . '.' . $this->getDepthColumnName();
+ public function getQualifiedDepthColumnName()
+ {
+ return $this->getTable() . '.' . $this->getDepthColumnName();
}
/**
@@ -98,8 +109,9 @@ public function getQualifiedDepthColumnName() {
*
* @return int
*/
- public function getDepth() {
- return $this->getAttribute($this->getDepthColumnName());
+ public function getDepth()
+ {
+ return $this->getAttribute($this->getDepthColumnName());
}
/**
@@ -107,8 +119,9 @@ public function getDepth() {
*
* @return string
*/
- public function getOrderColumnName() {
- return is_null($this->orderColumn) ? $this->getLeftColumnName() : $this->orderColumn;
+ public function getOrderColumnName()
+ {
+ return is_null($this->orderColumn) ? $this->getLeftColumnName() : $this->orderColumn;
}
/**
@@ -116,8 +129,9 @@ public function getOrderColumnName() {
*
* @return string
*/
- public function getQualifiedOrderColumnName() {
- return $this->getTable() . '.' . $this->getOrderColumnName();
+ public function getQualifiedOrderColumnName()
+ {
+ return $this->getTable() . '.' . $this->getOrderColumnName();
}
/**
@@ -125,8 +139,9 @@ public function getQualifiedOrderColumnName() {
*
* @return mixed
*/
- public function getOrder() {
- return $this->getAttribute($this->getOrderColumnName());
+ public function getOrder()
+ {
+ return $this->getAttribute($this->getOrderColumnName());
}
/**
@@ -134,8 +149,9 @@ public function getOrder() {
*
* @return array
*/
- public function getScopedColumns() {
- return (array) $this->scoped;
+ public function getScopedColumns()
+ {
+ return (array)$this->scoped;
}
/**
@@ -143,14 +159,16 @@ public function getScopedColumns() {
*
* @return array
*/
- public function getQualifiedScopedColumns() {
- if ( !$this->isScoped() )
- return $this->getScopedColumns();
+ public function getQualifiedScopedColumns()
+ {
+ if (!$this->isScoped())
+ return $this->getScopedColumns();
- $prefix = $this->getTable() . '.';
+ $prefix = $this->getTable() . '.';
- return array_map(function($c) use ($prefix) {
- return $prefix . $c; }, $this->getScopedColumns());
+ return array_map(function ($c) use ($prefix) {
+ return $prefix . $c;
+ }, $this->getScopedColumns());
}
}
diff --git a/src/Node.php b/src/Node.php
index 8dcab130..fd1ae84a 100644
--- a/src/Node.php
+++ b/src/Node.php
@@ -1,4 +1,5 @@
setDefaultLeftAndRight();
- });
-
- static::saving(function($node) {
- $node->storeNewParent();
- });
-
- static::saved(function($node) {
- $node->moveToNewParent();
- $node->setDepth();
- });
-
- static::deleting(function($node) {
- $node->destroyDescendants();
- });
-
- if ( static::softDeletesEnabled() ) {
- static::restoring(function($node) {
- $node->shiftSiblingsForRestore();
- });
-
- static::restored(function($node) {
- $node->restoreDescendants();
- });
- }
- }
-
- /**
- * Get the parent column name.
- *
- * @return string
- */
- public function getParentColumnName() {
- return $this->parentColumn;
- }
-
- /**
- * Get the table qualified parent column name.
- *
- * @return string
- */
- public function getQualifiedParentColumnName() {
- return $this->getTable(). '.' .$this->getParentColumnName();
- }
-
- /**
- * Get the value of the models "parent_id" field.
- *
- * @return int
- */
- public function getParentId() {
- return $this->getAttribute($this->getparentColumnName());
- }
-
- /**
- * Get the "left" field column name.
- *
- * @return string
- */
- public function getLeftColumnName() {
- return $this->leftColumn;
- }
-
- /**
- * Get the table qualified "left" field column name.
- *
- * @return string
- */
- public function getQualifiedLeftColumnName() {
- return $this->getTable() . '.' . $this->getLeftColumnName();
- }
-
- /**
- * Get the value of the model's "left" field.
- *
- * @return int
- */
- public function getLeft() {
- return $this->getAttribute($this->getLeftColumnName());
- }
-
- /**
- * Get the "right" field column name.
- *
- * @return string
- */
- public function getRightColumnName() {
- return $this->rightColumn;
- }
-
- /**
- * Get the table qualified "right" field column name.
- *
- * @return string
- */
- public function getQualifiedRightColumnName() {
- return $this->getTable() . '.' . $this->getRightColumnName();
- }
-
- /**
- * Get the value of the model's "right" field.
- *
- * @return int
- */
- public function getRight() {
- return $this->getAttribute($this->getRightColumnName());
- }
-
- /**
- * Get the "depth" field column name.
- *
- * @return string
- */
- public function getDepthColumnName() {
- return $this->depthColumn;
- }
-
- /**
- * Get the table qualified "depth" field column name.
- *
- * @return string
- */
- public function getQualifiedDepthColumnName() {
- return $this->getTable() . '.' . $this->getDepthColumnName();
- }
-
- /**
- * Get the model's "depth" value.
- *
- * @return int
- */
- public function getDepth() {
- return $this->getAttribute($this->getDepthColumnName());
- }
-
- /**
- * Get the "order" field column name.
- *
- * @return string
- */
- public function getOrderColumnName() {
- return is_null($this->orderColumn) ? $this->getLeftColumnName() : $this->orderColumn;
- }
-
- /**
- * Get the table qualified "order" field column name.
- *
- * @return string
- */
- public function getQualifiedOrderColumnName() {
- return $this->getTable() . '.' . $this->getOrderColumnName();
- }
-
- /**
- * Get the model's "order" value.
- *
- * @return mixed
- */
- public function getOrder() {
- return $this->getAttribute($this->getOrderColumnName());
- }
-
- /**
- * Get the column names which define our scope
- *
- * @return array
- */
- public function getScopedColumns() {
- return (array) $this->scoped;
- }
-
- /**
- * Get the qualified column names which define our scope
- *
- * @return array
- */
- public function getQualifiedScopedColumns() {
- if ( !$this->isScoped() )
- return $this->getScopedColumns();
-
- $prefix = $this->getTable() . '.';
-
- return array_map(function($c) use ($prefix) {
- return $prefix . $c; }, $this->getScopedColumns());
- }
-
- /**
- * Returns wether this particular node instance is scoped by certain fields
- * or not.
- *
- * @return boolean
- */
- public function isScoped() {
- return !!(count($this->getScopedColumns()) > 0);
- }
-
- /**
- * Parent relation (self-referential) 1-1.
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function parent() {
- return $this->belongsTo(get_class($this), $this->getParentColumnName());
- }
-
- /**
- * Children relation (self-referential) 1-N.
- *
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
- */
- public function children() {
- return $this->hasMany(get_class($this), $this->getParentColumnName())
- ->orderBy($this->getOrderColumnName());
- }
-
- /**
- * Get a new "scoped" query builder for the Node's model.
- *
- * @param bool $excludeDeleted
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public function newNestedSetQuery($excludeDeleted = true) {
- $builder = $this->newQuery($excludeDeleted)->orderBy($this->getQualifiedOrderColumnName());
-
- if ( $this->isScoped() ) {
- foreach($this->scoped as $scopeFld)
- $builder->where($scopeFld, '=', $this->$scopeFld);
- }
-
- return $builder;
- }
-
- /**
- * Overload new Collection
- *
- * @param array $models
- * @return \Baum\Extensions\Eloquent\Collection
- */
- public function newCollection(array $models = array()) {
- return new Collection($models);
- }
-
- /**
- * Get all of the nodes from the database.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection|static[]
- */
- public static function all($columns = array('*')) {
- $instance = new static;
-
- return $instance->newQuery()
- ->orderBy($instance->getQualifiedOrderColumnName())
- ->get();
- }
-
- /**
- * Returns the first root node.
- *
- * @return NestedSet
- */
- public static function root() {
- return static::roots()->first();
- }
-
- /**
- * Static query scope. Returns a query scope with all root nodes.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public static function roots() {
- $instance = new static;
-
- return $instance->newQuery()
- ->whereNull($instance->getParentColumnName())
- ->orderBy($instance->getQualifiedOrderColumnName());
- }
-
- /**
- * Static query scope. Returns a query scope with all nodes which are at
- * the end of a branch.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public static function allLeaves() {
- $instance = new static;
-
- $grammar = $instance->getConnection()->getQueryGrammar();
-
- $rgtCol = $grammar->wrap($instance->getQualifiedRightColumnName());
- $lftCol = $grammar->wrap($instance->getQualifiedLeftColumnName());
-
- return $instance->newQuery()
- ->whereRaw($rgtCol . ' - ' . $lftCol . ' = 1')
- ->orderBy($instance->getQualifiedOrderColumnName());
- }
-
- /**
- * Static query scope. Returns a query scope with all nodes which are at
- * the middle of a branch (not root and not leaves).
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public static function allTrunks() {
- $instance = new static;
-
- $grammar = $instance->getConnection()->getQueryGrammar();
-
- $rgtCol = $grammar->wrap($instance->getQualifiedRightColumnName());
- $lftCol = $grammar->wrap($instance->getQualifiedLeftColumnName());
-
- return $instance->newQuery()
- ->whereNotNull($instance->getParentColumnName())
- ->whereRaw($rgtCol . ' - ' . $lftCol . ' != 1')
- ->orderBy($instance->getQualifiedOrderColumnName());
- }
-
- /**
- * Checks wether the underlying Nested Set structure is valid.
- *
- * @return boolean
- */
- public static function isValidNestedSet() {
- $validator = new SetValidator(new static);
-
- return $validator->passes();
- }
-
- /**
- * Rebuilds the structure of the current Nested Set.
- *
- * @param bool $force
- * @return void
- */
- public static function rebuild($force = false) {
- $builder = new SetBuilder(new static);
-
- $builder->rebuild($force);
- }
-
- /**
- * Maps the provided tree structure into the database.
- *
- * @param array|\Illuminate\Support\Contracts\ArrayableInterface
- * @return boolean
- */
- public static function buildTree($nodeList) {
- return with(new static)->makeTree($nodeList);
- }
-
- /**
- * Query scope which extracts a certain node object from the current query
- * expression.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeWithoutNode($query, $node) {
- return $query->where($node->getKeyName(), '!=', $node->getKey());
- }
-
- /**
- * Extracts current node (self) from current query expression.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeWithoutSelf($query) {
- return $this->scopeWithoutNode($query, $this);
- }
-
- /**
- * Extracts first root (from the current node p-o-v) from current query
- * expression.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeWithoutRoot($query) {
- return $this->scopeWithoutNode($query, $this->getRoot());
- }
-
- /**
- * Provides a depth level limit for the query.
- *
- * @param query \Illuminate\Database\Query\Builder
- * @param limit integer
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeLimitDepth($query, $limit) {
- $depth = $this->exists ? $this->getDepth() : $this->getLevel();
- $max = $depth + $limit;
- $scopes = array($depth, $max);
-
- return $query->whereBetween($this->getDepthColumnName(), array(min($scopes), max($scopes)));
- }
-
- /**
- * Returns true if this is a root node.
- *
- * @return boolean
- */
- public function isRoot() {
- return is_null($this->getParentId());
- }
-
- /**
- * Returns true if this is a leaf node (end of a branch).
- *
- * @return boolean
- */
- public function isLeaf() {
- return $this->exists && ($this->getRight() - $this->getLeft() == 1);
- }
-
- /**
- * Returns true if this is a trunk node (not root or leaf).
- *
- * @return boolean
- */
- public function isTrunk() {
- return !$this->isRoot() && !$this->isLeaf();
- }
-
- /**
- * Returns true if this is a child node.
- *
- * @return boolean
- */
- public function isChild() {
- return !$this->isRoot();
- }
-
- /**
- * Returns the root node starting at the current node.
- *
- * @return NestedSet
- */
- public function getRoot() {
- if ( $this->exists ) {
- return $this->ancestorsAndSelf()->whereNull($this->getParentColumnName())->first();
- } else {
- $parentId = $this->getParentId();
-
- if ( !is_null($parentId) && $currentParent = static::find($parentId) ) {
- return $currentParent->getRoot();
- } else {
+abstract class Node extends Model
+{
+
+ /**
+ * Column name to store the reference to parent's node.
+ *
+ * @var string
+ */
+ protected $parentColumn = 'parent_id';
+
+ /**
+ * Column name for left index.
+ *
+ * @var string
+ */
+ protected $leftColumn = 'lft';
+
+ /**
+ * Column name for right index.
+ *
+ * @var string
+ */
+ protected $rightColumn = 'rgt';
+
+ /**
+ * Column name for depth field.
+ *
+ * @var string
+ */
+ protected $depthColumn = 'depth';
+
+ /**
+ * Column to perform the default sorting
+ *
+ * @var string
+ */
+ protected $orderColumn = null;
+
+ /**
+ * Guard NestedSet fields from mass-assignment.
+ *
+ * @var array
+ */
+ protected $guarded = array('id', 'parent_id', 'lft', 'rgt', 'depth');
+
+ /**
+ * Indicates whether we should move to a new parent.
+ *
+ * @var int
+ */
+ protected static $moveToNewParentId = null;
+
+ /**
+ * Columns which restrict what we consider our Nested Set list
+ *
+ * @var array
+ */
+ protected $scoped = array();
+
+ /**
+ * The "booting" method of the model.
+ *
+ * We'll use this method to register event listeners on a Node instance as
+ * suggested in the beta documentation...
+ *
+ * TODO:
+ *
+ * - Find a way to avoid needing to declare the called methods "public"
+ * as registering the event listeners *inside* this methods does not give
+ * us an object context.
+ *
+ * Events:
+ *
+ * 1. "creating": Before creating a new Node we'll assign a default value
+ * for the left and right indexes.
+ *
+ * 2. "saving": Before saving, we'll perform a check to see if we have to
+ * move to another parent.
+ *
+ * 3. "saved": Move to the new parent after saving if needed and re-set
+ * depth.
+ *
+ * 4. "deleting": Before delete we should prune all children and update
+ * the left and right indexes for the remaining nodes.
+ *
+ * 5. (optional) "restoring": Before a soft-delete node restore operation,
+ * shift its siblings.
+ *
+ * 6. (optional) "restore": After having restored a soft-deleted node,
+ * restore all of its descendants.
+ *
+ * @return void
+ */
+ protected static function boot()
+ {
+ parent::boot();
+
+ static::creating(function ($node) {
+ $node->setDefaultLeftAndRight();
+ });
+
+ static::saving(function ($node) {
+ $node->storeNewParent();
+ });
+
+ static::saved(function ($node) {
+ $node->moveToNewParent();
+ $node->setDepth();
+ });
+
+ static::deleting(function ($node) {
+ $node->destroyDescendants();
+ });
+
+ if (static::softDeletesEnabled()) {
+ static::restoring(function ($node) {
+ $node->shiftSiblingsForRestore();
+ });
+
+ static::restored(function ($node) {
+ $node->restoreDescendants();
+ });
+ }
+ }
+
+ /**
+ * Get the parent column name.
+ *
+ * @return string
+ */
+ public function getParentColumnName()
+ {
+ return $this->parentColumn;
+ }
+
+ /**
+ * Get the table qualified parent column name.
+ *
+ * @return string
+ */
+ public function getQualifiedParentColumnName()
+ {
+ return $this->getTable() . '.' . $this->getParentColumnName();
+ }
+
+ /**
+ * Get the value of the models "parent_id" field.
+ *
+ * @return int
+ */
+ public function getParentId()
+ {
+ return $this->getAttribute($this->getparentColumnName());
+ }
+
+ /**
+ * Get the "left" field column name.
+ *
+ * @return string
+ */
+ public function getLeftColumnName()
+ {
+ return $this->leftColumn;
+ }
+
+ /**
+ * Get the table qualified "left" field column name.
+ *
+ * @return string
+ */
+ public function getQualifiedLeftColumnName()
+ {
+ return $this->getTable() . '.' . $this->getLeftColumnName();
+ }
+
+ /**
+ * Get the value of the model's "left" field.
+ *
+ * @return int
+ */
+ public function getLeft()
+ {
+ return $this->getAttribute($this->getLeftColumnName());
+ }
+
+ /**
+ * Get the "right" field column name.
+ *
+ * @return string
+ */
+ public function getRightColumnName()
+ {
+ return $this->rightColumn;
+ }
+
+ /**
+ * Get the table qualified "right" field column name.
+ *
+ * @return string
+ */
+ public function getQualifiedRightColumnName()
+ {
+ return $this->getTable() . '.' . $this->getRightColumnName();
+ }
+
+ /**
+ * Get the value of the model's "right" field.
+ *
+ * @return int
+ */
+ public function getRight()
+ {
+ return $this->getAttribute($this->getRightColumnName());
+ }
+
+ /**
+ * Get the "depth" field column name.
+ *
+ * @return string
+ */
+ public function getDepthColumnName()
+ {
+ return $this->depthColumn;
+ }
+
+ /**
+ * Get the table qualified "depth" field column name.
+ *
+ * @return string
+ */
+ public function getQualifiedDepthColumnName()
+ {
+ return $this->getTable() . '.' . $this->getDepthColumnName();
+ }
+
+ /**
+ * Get the model's "depth" value.
+ *
+ * @return int
+ */
+ public function getDepth()
+ {
+ return $this->getAttribute($this->getDepthColumnName());
+ }
+
+ /**
+ * Get the "order" field column name.
+ *
+ * @return string
+ */
+ public function getOrderColumnName()
+ {
+ return is_null($this->orderColumn) ? $this->getLeftColumnName() : $this->orderColumn;
+ }
+
+ /**
+ * Get the table qualified "order" field column name.
+ *
+ * @return string
+ */
+ public function getQualifiedOrderColumnName()
+ {
+ return $this->getTable() . '.' . $this->getOrderColumnName();
+ }
+
+ /**
+ * Get the model's "order" value.
+ *
+ * @return mixed
+ */
+ public function getOrder()
+ {
+ return $this->getAttribute($this->getOrderColumnName());
+ }
+
+ /**
+ * Get the column names which define our scope
+ *
+ * @return array
+ */
+ public function getScopedColumns()
+ {
+ return (array)$this->scoped;
+ }
+
+ /**
+ * Get the qualified column names which define our scope
+ *
+ * @return array
+ */
+ public function getQualifiedScopedColumns()
+ {
+ if (!$this->isScoped())
+ return $this->getScopedColumns();
+
+ $prefix = $this->getTable() . '.';
+
+ return array_map(function ($c) use ($prefix) {
+ return $prefix . $c;
+ }, $this->getScopedColumns());
+ }
+
+ /**
+ * Returns wether this particular node instance is scoped by certain fields
+ * or not.
+ *
+ * @return boolean
+ */
+ public function isScoped()
+ {
+ return !!(count($this->getScopedColumns()) > 0);
+ }
+
+ /**
+ * Parent relation (self-referential) 1-1.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function parent()
+ {
+ return $this->belongsTo(get_class($this), $this->getParentColumnName());
+ }
+
+ /**
+ * Children relation (self-referential) 1-N.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function children()
+ {
+ return $this->hasMany(get_class($this), $this->getParentColumnName())
+ ->orderBy($this->getOrderColumnName());
+ }
+
+ /**
+ * Get a new "scoped" query builder for the Node's model.
+ *
+ * @param bool $excludeDeleted
+ * @return \Illuminate\Database\Eloquent\Builder|static
+ */
+ public function newNestedSetQuery($excludeDeleted = true)
+ {
+ $builder = $this->newQuery($excludeDeleted)->orderBy($this->getQualifiedOrderColumnName());
+
+ if ($this->isScoped()) {
+ foreach ($this->scoped as $scopeFld)
+ $builder->where($scopeFld, '=', $this->$scopeFld);
+ }
+
+ return $builder;
+ }
+
+ /**
+ * Overload new Collection
+ *
+ * @param array $models
+ * @return \Baum\Extensions\Eloquent\Collection
+ */
+ public function newCollection(array $models = array())
+ {
+ return new Collection($models);
+ }
+
+ /**
+ * Get all of the nodes from the database.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection|static[]
+ */
+ public static function all($columns = array('*'))
+ {
+ $instance = new static;
+
+ return $instance->newQuery()
+ ->orderBy($instance->getQualifiedOrderColumnName())
+ ->get();
+ }
+
+ /**
+ * Returns the first root node.
+ *
+ * @return NestedSet
+ */
+ public static function root()
+ {
+ return static::roots()->first();
+ }
+
+ /**
+ * Static query scope. Returns a query scope with all root nodes.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public static function roots()
+ {
+ $instance = new static;
+
+ return $instance->newQuery()
+ ->whereNull($instance->getParentColumnName())
+ ->orderBy($instance->getQualifiedOrderColumnName());
+ }
+
+ /**
+ * Static query scope. Returns a query scope with all nodes which are at
+ * the end of a branch.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public static function allLeaves()
+ {
+ $instance = new static;
+
+ $grammar = $instance->getConnection()->getQueryGrammar();
+
+ $rgtCol = $grammar->wrap($instance->getQualifiedRightColumnName());
+ $lftCol = $grammar->wrap($instance->getQualifiedLeftColumnName());
+
+ return $instance->newQuery()
+ ->whereRaw($rgtCol . ' - ' . $lftCol . ' = 1')
+ ->orderBy($instance->getQualifiedOrderColumnName());
+ }
+
+ /**
+ * Static query scope. Returns a query scope with all nodes which are at
+ * the middle of a branch (not root and not leaves).
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public static function allTrunks()
+ {
+ $instance = new static;
+
+ $grammar = $instance->getConnection()->getQueryGrammar();
+
+ $rgtCol = $grammar->wrap($instance->getQualifiedRightColumnName());
+ $lftCol = $grammar->wrap($instance->getQualifiedLeftColumnName());
+
+ return $instance->newQuery()
+ ->whereNotNull($instance->getParentColumnName())
+ ->whereRaw($rgtCol . ' - ' . $lftCol . ' != 1')
+ ->orderBy($instance->getQualifiedOrderColumnName());
+ }
+
+ /**
+ * Checks wether the underlying Nested Set structure is valid.
+ *
+ * @return boolean
+ */
+ public static function isValidNestedSet()
+ {
+ $validator = new SetValidator(new static);
+
+ return $validator->passes();
+ }
+
+ /**
+ * Rebuilds the structure of the current Nested Set.
+ *
+ * @param bool $force
+ * @return void
+ */
+ public static function rebuild($force = false)
+ {
+ $builder = new SetBuilder(new static);
+
+ $builder->rebuild($force);
+ }
+
+ /**
+ * Maps the provided tree structure into the database.
+ *
+ * @param array|\Illuminate\Contracts\Support\Arrayable
+ * @return boolean
+ */
+ public static function buildTree($nodeList)
+ {
+ return with(new static)->makeTree($nodeList);
+ }
+
+ /**
+ * Query scope which extracts a certain node object from the current query
+ * expression.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeWithoutNode($query, $node)
+ {
+ return $query->where($node->getKeyName(), '!=', $node->getKey());
+ }
+
+ /**
+ * Extracts current node (self) from current query expression.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeWithoutSelf($query)
+ {
+ return $this->scopeWithoutNode($query, $this);
+ }
+
+ /**
+ * Extracts first root (from the current node p-o-v) from current query
+ * expression.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeWithoutRoot($query)
+ {
+ return $this->scopeWithoutNode($query, $this->getRoot());
+ }
+
+ /**
+ * Provides a depth level limit for the query.
+ *
+ * @param query \Illuminate\Database\Query\Builder
+ * @param limit integer
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function scopeLimitDepth($query, $limit)
+ {
+ $depth = $this->exists ? $this->getDepth() : $this->getLevel();
+ $max = $depth + $limit;
+ $scopes = array($depth, $max);
+
+ return $query->whereBetween($this->getDepthColumnName(), array(min($scopes), max($scopes)));
+ }
+
+ /**
+ * Returns true if this is a root node.
+ *
+ * @return boolean
+ */
+ public function isRoot()
+ {
+ return is_null($this->getParentId());
+ }
+
+ /**
+ * Returns true if this is a leaf node (end of a branch).
+ *
+ * @return boolean
+ */
+ public function isLeaf()
+ {
+ return $this->exists && ($this->getRight() - $this->getLeft() == 1);
+ }
+
+ /**
+ * Returns true if this is a trunk node (not root or leaf).
+ *
+ * @return boolean
+ */
+ public function isTrunk()
+ {
+ return !$this->isRoot() && !$this->isLeaf();
+ }
+
+ /**
+ * Returns true if this is a child node.
+ *
+ * @return boolean
+ */
+ public function isChild()
+ {
+ return !$this->isRoot();
+ }
+
+ /**
+ * Returns the root node starting at the current node.
+ *
+ * @return NestedSet
+ */
+ public function getRoot()
+ {
+ if ($this->exists) {
+ return $this->ancestorsAndSelf()->whereNull($this->getParentColumnName())->first();
+ } else {
+ $parentId = $this->getParentId();
+
+ if (!is_null($parentId) && $currentParent = static::find($parentId)) {
+ return $currentParent->getRoot();
+ } else {
+ return $this;
+ }
+ }
+ }
+
+ /**
+ * Instance scope which targes all the ancestor chain nodes including
+ * the current one.
+ *
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function ancestorsAndSelf()
+ {
+ return $this->newNestedSetQuery()
+ ->where($this->getLeftColumnName(), '<=', $this->getLeft())
+ ->where($this->getRightColumnName(), '>=', $this->getRight());
+ }
+
+ /**
+ * Get all the ancestor chain from the database including the current node.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getAncestorsAndSelf($columns = array('*'))
+ {
+ return $this->ancestorsAndSelf()->get($columns);
+ }
+
+ /**
+ * Get all the ancestor chain from the database including the current node
+ * but without the root node.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getAncestorsAndSelfWithoutRoot($columns = array('*'))
+ {
+ return $this->ancestorsAndSelf()->withoutRoot()->get($columns);
+ }
+
+ /**
+ * Instance scope which targets all the ancestor chain nodes excluding
+ * the current one.
+ *
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function ancestors()
+ {
+ return $this->ancestorsAndSelf()->withoutSelf();
+ }
+
+ /**
+ * Get all the ancestor chain from the database excluding the current node.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getAncestors($columns = array('*'))
+ {
+ return $this->ancestors()->get($columns);
+ }
+
+ /**
+ * Get all the ancestor chain from the database excluding the current node
+ * and the root node (from the current node's perspective).
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getAncestorsWithoutRoot($columns = array('*'))
+ {
+ return $this->ancestors()->withoutRoot()->get($columns);
+ }
+
+ /**
+ * Instance scope which targets all children of the parent, including self.
+ *
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function siblingsAndSelf()
+ {
+ return $this->newNestedSetQuery()
+ ->where($this->getParentColumnName(), $this->getParentId());
+ }
+
+ /**
+ * Get all children of the parent, including self.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getSiblingsAndSelf($columns = array('*'))
+ {
+ return $this->siblingsAndSelf()->get($columns);
+ }
+
+ /**
+ * Instance scope targeting all children of the parent, except self.
+ *
+ * @return \Illuminate\Database\Eloquent\Builder
+ */
+ public function siblings()
+ {
+ return $this->siblingsAndSelf()->withoutSelf();
+ }
+
+ /**
+ * Return all children of the parent, except self.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getSiblings($columns = array('*'))
+ {
+ return $this->siblings()->get($columns);
+ }
+
+ /**
+ * Instance scope targeting all of its nested children which do not have
+ * children.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function leaves()
+ {
+ $grammar = $this->getConnection()->getQueryGrammar();
+
+ $rgtCol = $grammar->wrap($this->getQualifiedRightColumnName());
+ $lftCol = $grammar->wrap($this->getQualifiedLeftColumnName());
+
+ return $this->descendants()
+ ->whereRaw($rgtCol . ' - ' . $lftCol . ' = 1');
+ }
+
+ /**
+ * Return all of its nested children which do not have children.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getLeaves($columns = array('*'))
+ {
+ return $this->leaves()->get($columns);
+ }
+
+ /**
+ * Instance scope targeting all of its nested children which are between the
+ * root and the leaf nodes (middle branch).
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function trunks()
+ {
+ $grammar = $this->getConnection()->getQueryGrammar();
+
+ $rgtCol = $grammar->wrap($this->getQualifiedRightColumnName());
+ $lftCol = $grammar->wrap($this->getQualifiedLeftColumnName());
+
+ return $this->descendants()
+ ->whereNotNull($this->getQualifiedParentColumnName())
+ ->whereRaw($rgtCol . ' - ' . $lftCol . ' != 1');
+ }
+
+ /**
+ * Return all of its nested children which are trunks.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getTrunks($columns = array('*'))
+ {
+ return $this->trunks()->get($columns);
+ }
+
+ /**
+ * Scope targeting itself and all of its nested children.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function descendantsAndSelf()
+ {
+ return $this->newNestedSetQuery()
+ ->where($this->getLeftColumnName(), '>=', $this->getLeft())
+ ->where($this->getLeftColumnName(), '<', $this->getRight());
+ }
+
+ /**
+ * Retrieve all nested children an self.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getDescendantsAndSelf($columns = array('*'))
+ {
+ if (is_array($columns))
+ return $this->descendantsAndSelf()->get($columns);
+
+ $arguments = func_get_args();
+
+ $limit = intval(array_shift($arguments));
+ $columns = array_shift($arguments) ?: array('*');
+
+ return $this->descendantsAndSelf()->limitDepth($limit)->get($columns);
+ }
+
+ /**
+ * Set of all children & nested children.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function descendants()
+ {
+ return $this->descendantsAndSelf()->withoutSelf();
+ }
+
+ /**
+ * Retrieve all of its children & nested children.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getDescendants($columns = array('*'))
+ {
+ if (is_array($columns))
+ return $this->descendants()->get($columns);
+
+ $arguments = func_get_args();
+
+ $limit = intval(array_shift($arguments));
+ $columns = array_shift($arguments) ?: array('*');
+
+ return $this->descendants()->limitDepth($limit)->get($columns);
+ }
+
+ /**
+ * Set of "immediate" descendants (aka children), alias for the children relation.
+ *
+ * @return \Illuminate\Database\Query\Builder
+ */
+ public function immediateDescendants()
+ {
+ return $this->children();
+ }
+
+ /**
+ * Retrive all of its "immediate" descendants.
+ *
+ * @param array $columns
+ * @return \Illuminate\Database\Eloquent\Collection
+ */
+ public function getImmediateDescendants($columns = array('*'))
+ {
+ return $this->children()->get($columns);
+ }
+
+ /**
+ * Returns the level of this node in the tree.
+ * Root level is 0.
+ *
+ * @return int
+ */
+ public function getLevel()
+ {
+ if (is_null($this->getParentId()))
+ return 0;
+
+ return $this->computeLevel();
+ }
+
+ /**
+ * Returns true if node is a descendant.
+ *
+ * @param NestedSet
+ * @return boolean
+ */
+ public function isDescendantOf($other)
+ {
+ return (
+ $this->getLeft() > $other->getLeft() &&
+ $this->getLeft() < $other->getRight() &&
+ $this->inSameScope($other)
+ );
+ }
+
+ /**
+ * Returns true if node is self or a descendant.
+ *
+ * @param NestedSet
+ * @return boolean
+ */
+ public function isSelfOrDescendantOf($other)
+ {
+ return (
+ $this->getLeft() >= $other->getLeft() &&
+ $this->getLeft() < $other->getRight() &&
+ $this->inSameScope($other)
+ );
+ }
+
+ /**
+ * Returns true if node is an ancestor.
+ *
+ * @param NestedSet
+ * @return boolean
+ */
+ public function isAncestorOf($other)
+ {
+ return (
+ $this->getLeft() < $other->getLeft() &&
+ $this->getRight() > $other->getLeft() &&
+ $this->inSameScope($other)
+ );
+ }
+
+ /**
+ * Returns true if node is self or an ancestor.
+ *
+ * @param NestedSet
+ * @return boolean
+ */
+ public function isSelfOrAncestorOf($other)
+ {
+ return (
+ $this->getLeft() <= $other->getLeft() &&
+ $this->getRight() > $other->getLeft() &&
+ $this->inSameScope($other)
+ );
+ }
+
+ /**
+ * Returns the first sibling to the left.
+ *
+ * @return NestedSet
+ */
+ public function getLeftSibling()
+ {
+ return $this->siblings()
+ ->where($this->getLeftColumnName(), '<', $this->getLeft())
+ ->orderBy($this->getOrderColumnName(), 'desc')
+ ->get()
+ ->last();
+ }
+
+ /**
+ * Returns the first sibling to the right.
+ *
+ * @return NestedSet
+ */
+ public function getRightSibling()
+ {
+ return $this->siblings()
+ ->where($this->getLeftColumnName(), '>', $this->getLeft())
+ ->first();
+ }
+
+ /**
+ * Find the left sibling and move to left of it.
+ *
+ * @return \Baum\Node
+ */
+ public function moveLeft()
+ {
+ return $this->moveToLeftOf($this->getLeftSibling());
+ }
+
+ /**
+ * Find the right sibling and move to the right of it.
+ *
+ * @return \Baum\Node
+ */
+ public function moveRight()
+ {
+ return $this->moveToRightOf($this->getRightSibling());
+ }
+
+ /**
+ * Move to the node to the left of ...
+ *
+ * @return \Baum\Node
+ */
+ public function moveToLeftOf($node)
+ {
+ return $this->moveTo($node, 'left');
+ }
+
+ /**
+ * Move to the node to the right of ...
+ *
+ * @return \Baum\Node
+ */
+ public function moveToRightOf($node)
+ {
+ return $this->moveTo($node, 'right');
+ }
+
+ /**
+ * Alias for moveToRightOf
+ *
+ * @return \Baum\Node
+ */
+ public function makeNextSiblingOf($node)
+ {
+ return $this->moveToRightOf($node);
+ }
+
+ /**
+ * Alias for moveToRightOf
+ *
+ * @return \Baum\Node
+ */
+ public function makeSiblingOf($node)
+ {
+ return $this->moveToRightOf($node);
+ }
+
+ /**
+ * Alias for moveToLeftOf
+ *
+ * @return \Baum\Node
+ */
+ public function makePreviousSiblingOf($node)
+ {
+ return $this->moveToLeftOf($node);
+ }
+
+ /**
+ * Make the node a child of ...
+ *
+ * @return \Baum\Node
+ */
+ public function makeChildOf($node)
+ {
+ return $this->moveTo($node, 'child');
+ }
+
+ /**
+ * Make the node the first child of ...
+ *
+ * @return \Baum\Node
+ */
+ public function makeFirstChildOf($node)
+ {
+ if ($node->children()->count() == 0)
+ return $this->makeChildOf($node);
+
+ return $this->moveToLeftOf($node->children()->first());
+ }
+
+ /**
+ * Make the node the last child of ...
+ *
+ * @return \Baum\Node
+ */
+ public function makeLastChildOf($node)
+ {
+ return $this->makeChildOf($node);
+ }
+
+ /**
+ * Make current node a root node.
+ *
+ * @return \Baum\Node
+ */
+ public function makeRoot()
+ {
+ return $this->moveTo($this, 'root');
+ }
+
+ /**
+ * Equals?
+ *
+ * @param \Baum\Node
+ * @return boolean
+ */
+ public function equals($node)
+ {
+ return ($this == $node);
+ }
+
+ /**
+ * Checkes if the given node is in the same scope as the current one.
+ *
+ * @param \Baum\Node
+ * @return boolean
+ */
+ public function inSameScope($other)
+ {
+ foreach ($this->getScopedColumns() as $fld) {
+ if ($this->$fld != $other->$fld) return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks wether the given node is a descendant of itself. Basically, whether
+ * its in the subtree defined by the left and right indices.
+ *
+ * @param \Baum\Node
+ * @return boolean
+ */
+ public function insideSubtree($node)
+ {
+ return (
+ $this->getLeft() >= $node->getLeft() &&
+ $this->getLeft() <= $node->getRight() &&
+ $this->getRight() >= $node->getLeft() &&
+ $this->getRight() <= $node->getRight()
+ );
+ }
+
+ /**
+ * Sets default values for left and right fields.
+ *
+ * @return void
+ */
+ public function setDefaultLeftAndRight()
+ {
+ $withHighestRight = $this->newNestedSetQuery()->reOrderBy($this->getRightColumnName(), 'desc')->take(1)->sharedLock()->first();
+
+ $maxRgt = 0;
+ if (!is_null($withHighestRight)) $maxRgt = $withHighestRight->getRight();
+
+ $this->setAttribute($this->getLeftColumnName(), $maxRgt + 1);
+ $this->setAttribute($this->getRightColumnName(), $maxRgt + 2);
+ }
+
+ /**
+ * Store the parent_id if the attribute is modified so as we are able to move
+ * the node to this new parent after saving.
+ *
+ * @return void
+ */
+ public function storeNewParent()
+ {
+ if ($this->isDirty($this->getParentColumnName()) && ($this->exists || !$this->isRoot()))
+ static::$moveToNewParentId = $this->getParentId();
+ else
+ static::$moveToNewParentId = false;
+ }
+
+ /**
+ * Move to the new parent if appropiate.
+ *
+ * @return void
+ */
+ public function moveToNewParent()
+ {
+ $pid = static::$moveToNewParentId;
+
+ if (is_null($pid))
+ $this->makeRoot();
+ else if ($pid !== false)
+ $this->makeChildOf($pid);
+ }
+
+ /**
+ * Sets the depth attribute
+ *
+ * @return \Baum\Node
+ */
+ public function setDepth()
+ {
+ $self = $this;
+
+ $this->getConnection()->transaction(function () use ($self) {
+ $self->reload();
+
+ $level = $self->getLevel();
+
+ $self->newNestedSetQuery()->where($self->getKeyName(), '=', $self->getKey())->update(array($self->getDepthColumnName() => $level));
+ $self->setAttribute($self->getDepthColumnName(), $level);
+ });
+
+ return $this;
+ }
+
+ /**
+ * Sets the depth attribute for the current node and all of its descendants.
+ *
+ * @return \Baum\Node
+ */
+ public function setDepthWithSubtree()
+ {
+ $self = $this;
+
+ $this->getConnection()->transaction(function () use ($self) {
+ $self->reload();
+
+ $self->descendantsAndSelf()->select($self->getKeyName())->lockForUpdate()->get();
+
+ $oldDepth = !is_null($self->getDepth()) ? $self->getDepth() : 0;
+
+ $newDepth = $self->getLevel();
+
+ $self->newNestedSetQuery()->where($self->getKeyName(), '=', $self->getKey())->update(array($self->getDepthColumnName() => $newDepth));
+ $self->setAttribute($self->getDepthColumnName(), $newDepth);
+
+ $diff = $newDepth - $oldDepth;
+ if (!$self->isLeaf() && $diff != 0)
+ $self->descendants()->increment($self->getDepthColumnName(), $diff);
+ });
+
return $this;
- }
- }
- }
-
- /**
- * Instance scope which targes all the ancestor chain nodes including
- * the current one.
- *
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function ancestorsAndSelf() {
- return $this->newNestedSetQuery()
- ->where($this->getLeftColumnName(), '<=', $this->getLeft())
- ->where($this->getRightColumnName(), '>=', $this->getRight());
- }
-
- /**
- * Get all the ancestor chain from the database including the current node.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getAncestorsAndSelf($columns = array('*')) {
- return $this->ancestorsAndSelf()->get($columns);
- }
-
- /**
- * Get all the ancestor chain from the database including the current node
- * but without the root node.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getAncestorsAndSelfWithoutRoot($columns = array('*')) {
- return $this->ancestorsAndSelf()->withoutRoot()->get($columns);
- }
-
- /**
- * Instance scope which targets all the ancestor chain nodes excluding
- * the current one.
- *
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function ancestors() {
- return $this->ancestorsAndSelf()->withoutSelf();
- }
-
- /**
- * Get all the ancestor chain from the database excluding the current node.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getAncestors($columns = array('*')) {
- return $this->ancestors()->get($columns);
- }
-
- /**
- * Get all the ancestor chain from the database excluding the current node
- * and the root node (from the current node's perspective).
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getAncestorsWithoutRoot($columns = array('*')) {
- return $this->ancestors()->withoutRoot()->get($columns);
- }
-
- /**
- * Instance scope which targets all children of the parent, including self.
- *
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function siblingsAndSelf() {
- return $this->newNestedSetQuery()
- ->where($this->getParentColumnName(), $this->getParentId());
- }
-
- /**
- * Get all children of the parent, including self.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getSiblingsAndSelf($columns = array('*')) {
- return $this->siblingsAndSelf()->get($columns);
- }
-
- /**
- * Instance scope targeting all children of the parent, except self.
- *
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function siblings() {
- return $this->siblingsAndSelf()->withoutSelf();
- }
-
- /**
- * Return all children of the parent, except self.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getSiblings($columns = array('*')) {
- return $this->siblings()->get($columns);
- }
-
- /**
- * Instance scope targeting all of its nested children which do not have
- * children.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function leaves() {
- $grammar = $this->getConnection()->getQueryGrammar();
-
- $rgtCol = $grammar->wrap($this->getQualifiedRightColumnName());
- $lftCol = $grammar->wrap($this->getQualifiedLeftColumnName());
-
- return $this->descendants()
- ->whereRaw($rgtCol . ' - ' . $lftCol . ' = 1');
- }
-
- /**
- * Return all of its nested children which do not have children.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getLeaves($columns = array('*')) {
- return $this->leaves()->get($columns);
- }
-
- /**
- * Instance scope targeting all of its nested children which are between the
- * root and the leaf nodes (middle branch).
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function trunks() {
- $grammar = $this->getConnection()->getQueryGrammar();
-
- $rgtCol = $grammar->wrap($this->getQualifiedRightColumnName());
- $lftCol = $grammar->wrap($this->getQualifiedLeftColumnName());
-
- return $this->descendants()
- ->whereNotNull($this->getQualifiedParentColumnName())
- ->whereRaw($rgtCol . ' - ' . $lftCol . ' != 1');
- }
-
- /**
- * Return all of its nested children which are trunks.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getTrunks($columns = array('*')) {
- return $this->trunks()->get($columns);
- }
-
- /**
- * Scope targeting itself and all of its nested children.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function descendantsAndSelf() {
- return $this->newNestedSetQuery()
- ->where($this->getLeftColumnName(), '>=', $this->getLeft())
- ->where($this->getLeftColumnName(), '<', $this->getRight());
- }
-
- /**
- * Retrieve all nested children an self.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getDescendantsAndSelf($columns = array('*')) {
- if ( is_array($columns) )
- return $this->descendantsAndSelf()->get($columns);
-
- $arguments = func_get_args();
-
- $limit = intval(array_shift($arguments));
- $columns = array_shift($arguments) ?: array('*');
-
- return $this->descendantsAndSelf()->limitDepth($limit)->get($columns);
- }
-
- /**
- * Set of all children & nested children.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function descendants() {
- return $this->descendantsAndSelf()->withoutSelf();
- }
-
- /**
- * Retrieve all of its children & nested children.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getDescendants($columns = array('*')) {
- if ( is_array($columns) )
- return $this->descendants()->get($columns);
-
- $arguments = func_get_args();
-
- $limit = intval(array_shift($arguments));
- $columns = array_shift($arguments) ?: array('*');
-
- return $this->descendants()->limitDepth($limit)->get($columns);
- }
-
- /**
- * Set of "immediate" descendants (aka children), alias for the children relation.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function immediateDescendants() {
- return $this->children();
- }
-
- /**
- * Retrive all of its "immediate" descendants.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function getImmediateDescendants($columns = array('*')) {
- return $this->children()->get($columns);
- }
-
- /**
- * Returns the level of this node in the tree.
- * Root level is 0.
- *
- * @return int
- */
- public function getLevel() {
- if ( is_null($this->getParentId()) )
- return 0;
-
- return $this->computeLevel();
- }
-
- /**
- * Returns true if node is a descendant.
- *
- * @param NestedSet
- * @return boolean
- */
- public function isDescendantOf($other) {
- return (
- $this->getLeft() > $other->getLeft() &&
- $this->getLeft() < $other->getRight() &&
- $this->inSameScope($other)
- );
- }
-
- /**
- * Returns true if node is self or a descendant.
- *
- * @param NestedSet
- * @return boolean
- */
- public function isSelfOrDescendantOf($other) {
- return (
- $this->getLeft() >= $other->getLeft() &&
- $this->getLeft() < $other->getRight() &&
- $this->inSameScope($other)
- );
- }
-
- /**
- * Returns true if node is an ancestor.
- *
- * @param NestedSet
- * @return boolean
- */
- public function isAncestorOf($other) {
- return (
- $this->getLeft() < $other->getLeft() &&
- $this->getRight() > $other->getLeft() &&
- $this->inSameScope($other)
- );
- }
-
- /**
- * Returns true if node is self or an ancestor.
- *
- * @param NestedSet
- * @return boolean
- */
- public function isSelfOrAncestorOf($other) {
- return (
- $this->getLeft() <= $other->getLeft() &&
- $this->getRight() > $other->getLeft() &&
- $this->inSameScope($other)
- );
- }
-
- /**
- * Returns the first sibling to the left.
- *
- * @return NestedSet
- */
- public function getLeftSibling() {
- return $this->siblings()
- ->where($this->getLeftColumnName(), '<', $this->getLeft())
- ->orderBy($this->getOrderColumnName(), 'desc')
- ->get()
- ->last();
- }
-
- /**
- * Returns the first sibling to the right.
- *
- * @return NestedSet
- */
- public function getRightSibling() {
- return $this->siblings()
- ->where($this->getLeftColumnName(), '>', $this->getLeft())
- ->first();
- }
-
- /**
- * Find the left sibling and move to left of it.
- *
- * @return \Baum\Node
- */
- public function moveLeft() {
- return $this->moveToLeftOf($this->getLeftSibling());
- }
-
- /**
- * Find the right sibling and move to the right of it.
- *
- * @return \Baum\Node
- */
- public function moveRight() {
- return $this->moveToRightOf($this->getRightSibling());
- }
-
- /**
- * Move to the node to the left of ...
- *
- * @return \Baum\Node
- */
- public function moveToLeftOf($node) {
- return $this->moveTo($node, 'left');
- }
-
- /**
- * Move to the node to the right of ...
- *
- * @return \Baum\Node
- */
- public function moveToRightOf($node) {
- return $this->moveTo($node, 'right');
- }
-
- /**
- * Alias for moveToRightOf
- *
- * @return \Baum\Node
- */
- public function makeNextSiblingOf($node) {
- return $this->moveToRightOf($node);
- }
-
- /**
- * Alias for moveToRightOf
- *
- * @return \Baum\Node
- */
- public function makeSiblingOf($node) {
- return $this->moveToRightOf($node);
- }
-
- /**
- * Alias for moveToLeftOf
- *
- * @return \Baum\Node
- */
- public function makePreviousSiblingOf($node) {
- return $this->moveToLeftOf($node);
- }
-
- /**
- * Make the node a child of ...
- *
- * @return \Baum\Node
- */
- public function makeChildOf($node) {
- return $this->moveTo($node, 'child');
- }
-
- /**
- * Make the node the first child of ...
- *
- * @return \Baum\Node
- */
- public function makeFirstChildOf($node) {
- if ( $node->children()->count() == 0 )
- return $this->makeChildOf($node);
-
- return $this->moveToLeftOf($node->children()->first());
- }
-
- /**
- * Make the node the last child of ...
- *
- * @return \Baum\Node
- */
- public function makeLastChildOf($node) {
- return $this->makeChildOf($node);
- }
-
- /**
- * Make current node a root node.
- *
- * @return \Baum\Node
- */
- public function makeRoot() {
- return $this->moveTo($this, 'root');
- }
-
- /**
- * Equals?
- *
- * @param \Baum\Node
- * @return boolean
- */
- public function equals($node) {
- return ($this == $node);
- }
-
- /**
- * Checkes if the given node is in the same scope as the current one.
- *
- * @param \Baum\Node
- * @return boolean
- */
- public function inSameScope($other) {
- foreach($this->getScopedColumns() as $fld) {
- if ( $this->$fld != $other->$fld ) return false;
- }
-
- return true;
- }
-
- /**
- * Checks wether the given node is a descendant of itself. Basically, whether
- * its in the subtree defined by the left and right indices.
- *
- * @param \Baum\Node
- * @return boolean
- */
- public function insideSubtree($node) {
- return (
- $this->getLeft() >= $node->getLeft() &&
- $this->getLeft() <= $node->getRight() &&
- $this->getRight() >= $node->getLeft() &&
- $this->getRight() <= $node->getRight()
- );
- }
-
- /**
- * Sets default values for left and right fields.
- *
- * @return void
- */
- public function setDefaultLeftAndRight() {
- $withHighestRight = $this->newNestedSetQuery()->reOrderBy($this->getRightColumnName(), 'desc')->take(1)->sharedLock()->first();
-
- $maxRgt = 0;
- if ( !is_null($withHighestRight) ) $maxRgt = $withHighestRight->getRight();
-
- $this->setAttribute($this->getLeftColumnName() , $maxRgt + 1);
- $this->setAttribute($this->getRightColumnName() , $maxRgt + 2);
- }
-
- /**
- * Store the parent_id if the attribute is modified so as we are able to move
- * the node to this new parent after saving.
- *
- * @return void
- */
- public function storeNewParent() {
- if ( $this->isDirty($this->getParentColumnName()) && ($this->exists || !$this->isRoot()) )
- static::$moveToNewParentId = $this->getParentId();
- else
- static::$moveToNewParentId = FALSE;
- }
-
- /**
- * Move to the new parent if appropiate.
- *
- * @return void
- */
- public function moveToNewParent() {
- $pid = static::$moveToNewParentId;
-
- if ( is_null($pid) )
- $this->makeRoot();
- else if ( $pid !== FALSE )
- $this->makeChildOf($pid);
- }
-
- /**
- * Sets the depth attribute
- *
- * @return \Baum\Node
- */
- public function setDepth() {
- $self = $this;
-
- $this->getConnection()->transaction(function() use ($self) {
- $self->reload();
-
- $level = $self->getLevel();
-
- $self->newNestedSetQuery()->where($self->getKeyName(), '=', $self->getKey())->update(array($self->getDepthColumnName() => $level));
- $self->setAttribute($self->getDepthColumnName(), $level);
- });
-
- return $this;
- }
-
- /**
- * Sets the depth attribute for the current node and all of its descendants.
- *
- * @return \Baum\Node
- */
- public function setDepthWithSubtree() {
- $self = $this;
-
- $this->getConnection()->transaction(function() use ($self) {
- $self->reload();
-
- $self->descendantsAndSelf()->select($self->getKeyName())->lockForUpdate()->get();
-
- $oldDepth = !is_null($self->getDepth()) ? $self->getDepth() : 0;
-
- $newDepth = $self->getLevel();
-
- $self->newNestedSetQuery()->where($self->getKeyName(), '=', $self->getKey())->update(array($self->getDepthColumnName() => $newDepth));
- $self->setAttribute($self->getDepthColumnName(), $newDepth);
-
- $diff = $newDepth - $oldDepth;
- if ( !$self->isLeaf() && $diff != 0 )
- $self->descendants()->increment($self->getDepthColumnName(), $diff);
- });
-
- return $this;
- }
-
- /**
- * Prunes a branch off the tree, shifting all the elements on the right
- * back to the left so the counts work.
- *
- * @return void;
- */
- public function destroyDescendants() {
- if ( is_null($this->getRight()) || is_null($this->getLeft()) ) return;
-
- $self = $this;
-
- $this->getConnection()->transaction(function() use ($self) {
- $self->reload();
-
- $lftCol = $self->getLeftColumnName();
- $rgtCol = $self->getRightColumnName();
- $lft = $self->getLeft();
- $rgt = $self->getRight();
-
- // Apply a lock to the rows which fall past the deletion point
- $self->newNestedSetQuery()->where($lftCol, '>=', $lft)->select($self->getKeyName())->lockForUpdate()->get();
-
- // Prune children
- $self->newNestedSetQuery()->where($lftCol, '>', $lft)->where($rgtCol, '<', $rgt)->delete();
-
- // Update left and right indexes for the remaining nodes
- $diff = $rgt - $lft + 1;
-
- $self->newNestedSetQuery()->where($lftCol, '>', $rgt)->decrement($lftCol, $diff);
- $self->newNestedSetQuery()->where($rgtCol, '>', $rgt)->decrement($rgtCol, $diff);
- });
- }
-
- /**
- * "Makes room" for the the current node between its siblings.
- *
- * @return void
- */
- public function shiftSiblingsForRestore() {
- if ( is_null($this->getRight()) || is_null($this->getLeft()) ) return;
-
- $self = $this;
-
- $this->getConnection()->transaction(function() use ($self) {
- $lftCol = $self->getLeftColumnName();
- $rgtCol = $self->getRightColumnName();
- $lft = $self->getLeft();
- $rgt = $self->getRight();
-
- $diff = $rgt - $lft + 1;
-
- $self->newNestedSetQuery()->where($lftCol, '>=', $lft)->increment($lftCol, $diff);
- $self->newNestedSetQuery()->where($rgtCol, '>=', $lft)->increment($rgtCol, $diff);
- });
- }
-
- /**
- * Restores all of the current node's descendants.
- *
- * @return void
- */
- public function restoreDescendants() {
- if ( is_null($this->getRight()) || is_null($this->getLeft()) ) return;
-
- $self = $this;
-
- $this->getConnection()->transaction(function() use ($self) {
- $self->newNestedSetQuery()
- ->withTrashed()
- ->where($self->getLeftColumnName(), '>', $self->getLeft())
- ->where($self->getRightColumnName(), '<', $self->getRight())
- ->update(array(
- $self->getDeletedAtColumn() => null,
- $self->getUpdatedAtColumn() => $self->{$self->getUpdatedAtColumn()}
- ));
- });
- }
-
- /**
- * Return an key-value array indicating the node's depth with $seperator
- *
- * @return Array
- */
- public static function getNestedList($column, $key = null, $seperator = ' ') {
- $instance = new static;
-
- $key = $key ?: $instance->getKeyName();
- $depthColumn = $instance->getDepthColumnName();
-
- $nodes = $instance->newNestedSetQuery()->get()->toArray();
-
- return array_combine(array_map(function($node) use($key) {
- return $node[$key];
- }, $nodes), array_map(function($node) use($seperator, $depthColumn, $column) {
- return str_repeat($seperator, $node[$depthColumn]) . $node[$column];
- }, $nodes));
- }
-
- /**
- * Maps the provided tree structure into the database using the current node
- * as the parent. The provided tree structure will be inserted/updated as the
- * descendancy subtree of the current node instance.
- *
- * @param array|\Illuminate\Support\Contracts\ArrayableInterface
- * @return boolean
- */
- public function makeTree($nodeList) {
- $mapper = new SetMapper($this);
-
- return $mapper->map($nodeList);
- }
-
- /**
- * Main move method. Here we handle all node movements with the corresponding
- * lft/rgt index updates.
- *
- * @param Baum\Node|int $target
- * @param string $position
- * @return \Baum\Node
- */
- protected function moveTo($target, $position) {
- return Move::to($this, $target, $position);
- }
-
- /**
- * Compute current node level. If could not move past ourseleves return
- * our ancestor count, otherwhise get the first parent level + the computed
- * nesting.
- *
- * @return integer
- */
- protected function computeLevel() {
- list($node, $nesting) = $this->determineDepth($this);
-
- if ( $node->equals($this) )
- return $this->ancestors()->count();
-
- return $node->getLevel() + $nesting;
- }
-
- /**
- * Return an array with the last node we could reach and its nesting level
- *
- * @param Baum\Node $node
- * @param integer $nesting
- * @return array
- */
- protected function determineDepth($node, $nesting = 0) {
- // Traverse back up the ancestry chain and add to the nesting level count
- while( $parent = $node->parent()->first() ) {
- $nesting = $nesting + 1;
-
- $node = $parent;
- }
-
- return array($node, $nesting);
- }
+ }
+
+ /**
+ * Prunes a branch off the tree, shifting all the elements on the right
+ * back to the left so the counts work.
+ *
+ * @return void;
+ */
+ public function destroyDescendants()
+ {
+ if (is_null($this->getRight()) || is_null($this->getLeft())) return;
+
+ $self = $this;
+
+ $this->getConnection()->transaction(function () use ($self) {
+ $self->reload();
+
+ $lftCol = $self->getLeftColumnName();
+ $rgtCol = $self->getRightColumnName();
+ $lft = $self->getLeft();
+ $rgt = $self->getRight();
+
+ // Apply a lock to the rows which fall past the deletion point
+ $self->newNestedSetQuery()->where($lftCol, '>=', $lft)->select($self->getKeyName())->lockForUpdate()->get();
+
+ // Prune children
+ $self->newNestedSetQuery()->where($lftCol, '>', $lft)->where($rgtCol, '<', $rgt)->delete();
+
+ // Update left and right indexes for the remaining nodes
+ $diff = $rgt - $lft + 1;
+
+ $self->newNestedSetQuery()->where($lftCol, '>', $rgt)->decrement($lftCol, $diff);
+ $self->newNestedSetQuery()->where($rgtCol, '>', $rgt)->decrement($rgtCol, $diff);
+ });
+ }
+
+ /**
+ * "Makes room" for the the current node between its siblings.
+ *
+ * @return void
+ */
+ public function shiftSiblingsForRestore()
+ {
+ if (is_null($this->getRight()) || is_null($this->getLeft())) return;
+
+ $self = $this;
+
+ $this->getConnection()->transaction(function () use ($self) {
+ $lftCol = $self->getLeftColumnName();
+ $rgtCol = $self->getRightColumnName();
+ $lft = $self->getLeft();
+ $rgt = $self->getRight();
+
+ $diff = $rgt - $lft + 1;
+
+ $self->newNestedSetQuery()->where($lftCol, '>=', $lft)->increment($lftCol, $diff);
+ $self->newNestedSetQuery()->where($rgtCol, '>=', $lft)->increment($rgtCol, $diff);
+ });
+ }
+
+ /**
+ * Restores all of the current node's descendants.
+ *
+ * @return void
+ */
+ public function restoreDescendants()
+ {
+ if (is_null($this->getRight()) || is_null($this->getLeft())) return;
+
+ $self = $this;
+
+ $this->getConnection()->transaction(function () use ($self) {
+ $self->newNestedSetQuery()
+ ->withTrashed()
+ ->where($self->getLeftColumnName(), '>', $self->getLeft())
+ ->where($self->getRightColumnName(), '<', $self->getRight())
+ ->update(array(
+ $self->getDeletedAtColumn() => null,
+ $self->getUpdatedAtColumn() => $self->{$self->getUpdatedAtColumn()}
+ ));
+ });
+ }
+
+ /**
+ * Return an key-value array indicating the node's depth with $seperator
+ *
+ * @return Array
+ */
+ public static function getNestedList($column, $key = null, $seperator = ' ')
+ {
+ $instance = new static;
+
+ $key = $key ?: $instance->getKeyName();
+ $depthColumn = $instance->getDepthColumnName();
+
+ $nodes = $instance->newNestedSetQuery()->get()->toArray();
+
+ return array_combine(array_map(function ($node) use ($key) {
+ return $node[$key];
+ }, $nodes), array_map(function ($node) use ($seperator, $depthColumn, $column) {
+ return str_repeat($seperator, $node[$depthColumn]) . $node[$column];
+ }, $nodes));
+ }
+
+ /**
+ * Maps the provided tree structure into the database using the current node
+ * as the parent. The provided tree structure will be inserted/updated as the
+ * descendancy subtree of the current node instance.
+ *
+ * @param array|\Illuminate\Contracts\Support\Arrayable
+ * @return boolean
+ */
+ public function makeTree($nodeList)
+ {
+ $mapper = new SetMapper($this);
+
+ return $mapper->map($nodeList);
+ }
+
+ /**
+ * Main move method. Here we handle all node movements with the corresponding
+ * lft/rgt index updates.
+ *
+ * @param Baum\Node|int $target
+ * @param string $position
+ * @return \Baum\Node
+ */
+ protected function moveTo($target, $position)
+ {
+ return Move::to($this, $target, $position);
+ }
+
+ /**
+ * Compute current node level. If could not move past ourseleves return
+ * our ancestor count, otherwhise get the first parent level + the computed
+ * nesting.
+ *
+ * @return integer
+ */
+ protected function computeLevel()
+ {
+ list($node, $nesting) = $this->determineDepth($this);
+
+ if ($node->equals($this))
+ return $this->ancestors()->count();
+
+ return $node->getLevel() + $nesting;
+ }
+
+ /**
+ * Return an array with the last node we could reach and its nesting level
+ *
+ * @param Baum\Node $node
+ * @param integer $nesting
+ * @return array
+ */
+ protected function determineDepth($node, $nesting = 0)
+ {
+ // Traverse back up the ancestry chain and add to the nesting level count
+ while ($parent = $node->parent()->first()) {
+ $nesting = $nesting + 1;
+
+ $node = $parent;
+ }
+
+ return array($node, $nesting);
+ }
}
diff --git a/src/Providers/BaumServiceProvider.php b/src/Providers/BaumServiceProvider.php
index 5c6f18c5..4061873b 100644
--- a/src/Providers/BaumServiceProvider.php
+++ b/src/Providers/BaumServiceProvider.php
@@ -1,4 +1,5 @@
registerCommands();
- }
+ /**
+ * Register the service provider.
+ *
+ * @return void
+ */
+ public function register()
+ {
+ $this->registerCommands();
+ }
- /**
- * Register the commands.
- *
- * @return void
- */
- public function registerCommands() {
- $this->registerBaumCommand();
- $this->registerInstallCommand();
+ /**
+ * Register the commands.
+ *
+ * @return void
+ */
+ public function registerCommands()
+ {
+ $this->registerBaumCommand();
+ $this->registerInstallCommand();
- // Resolve the commands with Artisan by attaching the event listener to Artisan's
- // startup. This allows us to use the commands from our terminal.
- $this->commands('command.baum', 'command.baum.install');
- }
+ // Resolve the commands with Artisan by attaching the event listener to Artisan's
+ // startup. This allows us to use the commands from our terminal.
+ $this->commands('command.baum', 'command.baum.install');
+ }
- /**
- * Register the 'baum' command.
- *
- * @return void
- */
- protected function registerBaumCommand() {
- $this->app->singleton('command.baum', function($app) {
- return new BaumCommand;
- });
- }
+ /**
+ * Register the 'baum' command.
+ *
+ * @return void
+ */
+ protected function registerBaumCommand()
+ {
+ $this->app->singleton('command.baum', function ($app) {
+ return new BaumCommand;
+ });
+ }
- /**
- * Register the 'baum:install' command.
- *
- * @return void
- */
- protected function registerInstallCommand() {
- $this->app->singleton('command.baum.install', function($app) {
- $migrator = new MigrationGenerator($app['files']);
- $modeler = new ModelGenerator($app['files']);
+ /**
+ * Register the 'baum:install' command.
+ *
+ * @return void
+ */
+ protected function registerInstallCommand()
+ {
+ $this->app->singleton('command.baum.install', function ($app) {
+ $migrator = new MigrationGenerator($app['files']);
+ $modeler = new ModelGenerator($app['files']);
- return new InstallCommand($migrator, $modeler);
- });
- }
+ return new InstallCommand($migrator, $modeler);
+ });
+ }
- /**
- * Get the services provided by the provider.
- *
- * @return array
- */
- public function provides() {
- return array('command.baum', 'command.baum.install');
- }
+ /**
+ * Get the services provided by the provider.
+ *
+ * @return array
+ */
+ public function provides()
+ {
+ return array('command.baum', 'command.baum.install');
+ }
}
diff --git a/src/SetBuilder.php b/src/SetBuilder.php
index 873c238e..05b1ab67 100644
--- a/src/SetBuilder.php
+++ b/src/SetBuilder.php
@@ -1,175 +1,187 @@
node = $node;
- }
-
- /**
- * Perform the re-calculation of the left and right indexes of the whole
- * nested set tree structure.
- *
- * @param bool $force
- * @return void
- */
- public function rebuild($force = false) {
- $alreadyValid = forward_static_call(array(get_class($this->node), 'isValidNestedSet'));
-
- // Do not rebuild a valid Nested Set tree structure
- if ( !$force && $alreadyValid ) return true;
-
- // Rebuild lefts and rights for each root node and its children (recursively).
- // We go by setting left (and keep track of the current left bound), then
- // search for each children and recursively set the left index (while
- // incrementing that index). When going back up the recursive chain we start
- // setting the right indexes and saving the nodes...
- $self = $this;
-
- $this->node->getConnection()->transaction(function() use ($self) {
- foreach($self->roots() as $root)
- $self->rebuildBounds($root, 0);
- });
- }
-
- /**
- * Return all root nodes for the current database table appropiately sorted.
- *
- * @return Illuminate\Database\Eloquent\Collection
- */
- public function roots() {
- return $this->node->newQuery()
- ->whereNull($this->node->getQualifiedParentColumnName())
- ->orderBy($this->node->getQualifiedLeftColumnName())
- ->orderBy($this->node->getQualifiedRightColumnName())
- ->orderBy($this->node->getQualifiedKeyName())
- ->get();
- }
-
- /**
- * Recompute left and right index bounds for the specified node and its
- * children (recursive call). Fill the depth column too.
- */
- public function rebuildBounds($node, $depth = 0) {
- $k = $this->scopedKey($node);
-
- $node->setAttribute($node->getLeftColumnName(), $this->getNextBound($k));
- $node->setAttribute($node->getDepthColumnName(), $depth);
-
- foreach($this->children($node) as $child)
- $this->rebuildBounds($child, $depth + 1);
-
- $node->setAttribute($node->getRightColumnName(), $this->getNextBound($k));
-
- $node->save();
- }
-
- /**
- * Return all children for the specified node.
- *
- * @param Baum\Node $node
- * @return Illuminate\Database\Eloquent\Collection
- */
- public function children($node) {
- $query = $this->node->newQuery();
-
- $query->where($this->node->getQualifiedParentColumnName(), '=', $node->getKey());
-
- // We must also add the scoped column values to the query to compute valid
- // left and right indexes.
- foreach($this->scopedAttributes($node) as $fld => $value)
- $query->where($this->qualify($fld), '=', $value);
-
- $query->orderBy($this->node->getQualifiedLeftColumnName());
- $query->orderBy($this->node->getQualifiedRightColumnName());
- $query->orderBy($this->node->getQualifiedKeyName());
-
- return $query->get();
- }
-
- /**
- * Return an array of the scoped attributes of the supplied node.
- *
- * @param Baum\Node $node
- * @return array
- */
- protected function scopedAttributes($node) {
- $keys = $this->node->getScopedColumns();
-
- if ( count($keys) == 0 )
- return array();
-
- $values = array_map(function($column) use ($node) {
- return $node->getAttribute($column); }, $keys);
-
- return array_combine($keys, $values);
- }
-
- /**
- * Return a string-key for the current scoped attributes. Used for index
- * computing when a scope is defined (acsts as an scope identifier).
- *
- * @param Baum\Node $node
- * @return string
- */
- protected function scopedKey($node) {
- $attributes = $this->scopedAttributes($node);
-
- $output = array();
-
- foreach($attributes as $fld => $value)
- $output[] = $this->qualify($fld).'='.(is_null($value) ? 'NULL' : $value);
-
- // NOTE: Maybe an md5 or something would be better. Should be unique though.
- return implode(',', $output);
- }
-
- /**
- * Return next index bound value for the given key (current scope identifier)
- *
- * @param string $key
- * @return integer
- */
- protected function getNextBound($key) {
- if ( false === array_key_exists($key, $this->bounds) )
- $this->bounds[$key] = 0;
-
- $this->bounds[$key] = $this->bounds[$key] + 1;
-
- return $this->bounds[$key];
- }
-
- /**
- * Get the fully qualified value for the specified column.
- *
- * @return string
- */
- protected function qualify($column) {
- return $this->node->getTable() . '.' . $column;
- }
+class SetBuilder
+{
+
+ /**
+ * Node instance for reference
+ *
+ * @var \Baum\Node
+ */
+ protected $node = null;
+
+ /**
+ * Array which will hold temporary lft, rgt index values for each scope.
+ *
+ * @var array
+ */
+ protected $bounds = array();
+
+ /**
+ * Create a new \Baum\SetBuilder class instance.
+ *
+ * @param \Baum\Node $node
+ * @return void
+ */
+ public function __construct($node)
+ {
+ $this->node = $node;
+ }
+
+ /**
+ * Perform the re-calculation of the left and right indexes of the whole
+ * nested set tree structure.
+ *
+ * @param bool $force
+ * @return void
+ */
+ public function rebuild($force = false)
+ {
+ $alreadyValid = forward_static_call(array(get_class($this->node), 'isValidNestedSet'));
+
+ // Do not rebuild a valid Nested Set tree structure
+ if (!$force && $alreadyValid) return true;
+
+ // Rebuild lefts and rights for each root node and its children (recursively).
+ // We go by setting left (and keep track of the current left bound), then
+ // search for each children and recursively set the left index (while
+ // incrementing that index). When going back up the recursive chain we start
+ // setting the right indexes and saving the nodes...
+ $self = $this;
+
+ $this->node->getConnection()->transaction(function () use ($self) {
+ foreach ($self->roots() as $root)
+ $self->rebuildBounds($root, 0);
+ });
+ }
+
+ /**
+ * Return all root nodes for the current database table appropiately sorted.
+ *
+ * @return Illuminate\Database\Eloquent\Collection
+ */
+ public function roots()
+ {
+ return $this->node->newQuery()
+ ->whereNull($this->node->getQualifiedParentColumnName())
+ ->orderBy($this->node->getQualifiedLeftColumnName())
+ ->orderBy($this->node->getQualifiedRightColumnName())
+ ->orderBy($this->node->getQualifiedKeyName())
+ ->get();
+ }
+
+ /**
+ * Recompute left and right index bounds for the specified node and its
+ * children (recursive call). Fill the depth column too.
+ */
+ public function rebuildBounds($node, $depth = 0)
+ {
+ $k = $this->scopedKey($node);
+
+ $node->setAttribute($node->getLeftColumnName(), $this->getNextBound($k));
+ $node->setAttribute($node->getDepthColumnName(), $depth);
+
+ foreach ($this->children($node) as $child)
+ $this->rebuildBounds($child, $depth + 1);
+
+ $node->setAttribute($node->getRightColumnName(), $this->getNextBound($k));
+
+ $node->save();
+ }
+
+ /**
+ * Return all children for the specified node.
+ *
+ * @param Baum\Node $node
+ * @return Illuminate\Database\Eloquent\Collection
+ */
+ public function children($node)
+ {
+ $query = $this->node->newQuery();
+
+ $query->where($this->node->getQualifiedParentColumnName(), '=', $node->getKey());
+
+ // We must also add the scoped column values to the query to compute valid
+ // left and right indexes.
+ foreach ($this->scopedAttributes($node) as $fld => $value)
+ $query->where($this->qualify($fld), '=', $value);
+
+ $query->orderBy($this->node->getQualifiedLeftColumnName());
+ $query->orderBy($this->node->getQualifiedRightColumnName());
+ $query->orderBy($this->node->getQualifiedKeyName());
+
+ return $query->get();
+ }
+
+ /**
+ * Return an array of the scoped attributes of the supplied node.
+ *
+ * @param Baum\Node $node
+ * @return array
+ */
+ protected function scopedAttributes($node)
+ {
+ $keys = $this->node->getScopedColumns();
+
+ if (count($keys) == 0)
+ return array();
+
+ $values = array_map(function ($column) use ($node) {
+ return $node->getAttribute($column);
+ }, $keys);
+
+ return array_combine($keys, $values);
+ }
+
+ /**
+ * Return a string-key for the current scoped attributes. Used for index
+ * computing when a scope is defined (acsts as an scope identifier).
+ *
+ * @param Baum\Node $node
+ * @return string
+ */
+ protected function scopedKey($node)
+ {
+ $attributes = $this->scopedAttributes($node);
+
+ $output = array();
+
+ foreach ($attributes as $fld => $value)
+ $output[] = $this->qualify($fld) . '=' . (is_null($value) ? 'NULL' : $value);
+
+ // NOTE: Maybe an md5 or something would be better. Should be unique though.
+ return implode(',', $output);
+ }
+
+ /**
+ * Return next index bound value for the given key (current scope identifier)
+ *
+ * @param string $key
+ * @return integer
+ */
+ protected function getNextBound($key)
+ {
+ if (false === array_key_exists($key, $this->bounds))
+ $this->bounds[$key] = 0;
+
+ $this->bounds[$key] = $this->bounds[$key] + 1;
+
+ return $this->bounds[$key];
+ }
+
+ /**
+ * Get the fully qualified value for the specified column.
+ *
+ * @return string
+ */
+ protected function qualify($column)
+ {
+ return $this->node->getTable() . '.' . $column;
+ }
}
diff --git a/src/SetMapper.php b/src/SetMapper.php
index a44dabab..43bee475 100644
--- a/src/SetMapper.php
+++ b/src/SetMapper.php
@@ -1,164 +1,178 @@
node = $node;
-
- $this->childrenKeyName = $childrenKeyName;
- }
-
- /**
- * Maps a tree structure into the database. Unguards & wraps in transaction.
- *
- * @param array|\Illuminate\Support\Contracts\ArrayableInterface
- * @return boolean
- */
- public function map($nodeList) {
- $self = $this;
-
- return $this->wrapInTransaction(function() use ($self, $nodeList) {
- forward_static_call(array(get_class($self->node), 'unguard'));
-
- $result = $self->mapTree($nodeList);
-
- forward_static_call(array(get_class($self->node), 'reguard'));
-
- return $result;
- });
- }
-
- /**
- * Maps a tree structure into the database without unguarding nor wrapping
- * inside a transaction.
- *
- * @param array|\Illuminate\Support\Contracts\ArrayableInterface
- * @return boolean
- */
- public function mapTree($nodeList) {
- $tree = $nodeList instanceof ArrayableInterface ? $nodeList->toArray() : $nodeList;
-
- $affectedKeys = array();
-
- $result = $this->mapTreeRecursive($tree, $this->node->getKey(), $affectedKeys);
-
- if ( $result && count($affectedKeys) > 0 )
- $this->deleteUnaffected($affectedKeys);
-
- return $result;
- }
-
- /**
- * Returns the children key name to use on the mapping array
- *
- * @return string
- */
- public function getChildrenKeyName() {
- return $this->childrenKeyName;
- }
-
- /**
- * Maps a tree structure into the database
- *
- * @param array $tree
- * @param mixed $parent
- * @return boolean
- */
- protected function mapTreeRecursive(array $tree, $parentKey = null, &$affectedKeys = array()) {
- // For every attribute entry: We'll need to instantiate a new node either
- // from the database (if the primary key was supplied) or a new instance. Then,
- // append all the remaining data attributes (including the `parent_id` if
- // present) and save it. Finally, tail-recurse performing the same
- // operations for any child node present. Setting the `parent_id` property at
- // each level will take care of the nesting work for us.
- foreach($tree as $attributes) {
- $node = $this->firstOrNew($this->getSearchAttributes($attributes));
-
- $data = $this->getDataAttributes($attributes);
- if ( !is_null($parentKey) )
- $data[$node->getParentColumnName()] = $parentKey;
-
- $node->fill($data);
-
- $result = $node->save();
-
- if ( ! $result ) return false;
-
- $affectedKeys[] = $node->getKey();
-
- if ( array_key_exists($this->getChildrenKeyName(), $attributes) ) {
- $children = $attributes[$this->getChildrenKeyName()];
-
- if ( count($children) > 0 ) {
- $result = $this->mapTreeRecursive($children, $node->getKey(), $affectedKeys);
-
- if ( ! $result ) return false;
- }
- }
+class SetMapper
+{
+
+ /**
+ * Node instance for reference
+ *
+ * @var \Baum\Node
+ */
+ protected $node = null;
+
+ /**
+ * Children key name
+ *
+ * @var string
+ */
+ protected $childrenKeyName = 'children';
+
+ /**
+ * Create a new \Baum\SetBuilder class instance.
+ *
+ * @param \Baum\Node $node
+ * @return void
+ */
+ public function __construct($node, $childrenKeyName = 'children')
+ {
+ $this->node = $node;
+
+ $this->childrenKeyName = $childrenKeyName;
}
- return true;
- }
+ /**
+ * Maps a tree structure into the database. Unguards & wraps in transaction.
+ *
+ * @param array|\Illuminate\Support\Contracts\ArrayableInterface
+ * @return boolean
+ */
+ public function map($nodeList)
+ {
+ $self = $this;
- protected function getSearchAttributes($attributes) {
- $searchable = array($this->node->getKeyName());
+ return $this->wrapInTransaction(function () use ($self, $nodeList) {
+ forward_static_call(array(get_class($self->node), 'unguard'));
- return array_only($attributes, $searchable);
- }
+ $result = $self->mapTree($nodeList);
- protected function getDataAttributes($attributes) {
- $exceptions = array($this->node->getKeyName(), $this->getChildrenKeyName());
+ forward_static_call(array(get_class($self->node), 'reguard'));
+
+ return $result;
+ });
+ }
- return array_except($attributes, $exceptions);
- }
+ /**
+ * Maps a tree structure into the database without unguarding nor wrapping
+ * inside a transaction.
+ *
+ * @param array|\Illuminate\Support\Contracts\ArrayableInterface
+ * @return boolean
+ */
+ public function mapTree($nodeList)
+ {
+ $tree = $nodeList instanceof ArrayableInterface ? $nodeList->toArray() : $nodeList;
- protected function firstOrNew($attributes) {
- $className = get_class($this->node);
+ $affectedKeys = array();
- if ( count($attributes) === 0 )
- return new $className;
+ $result = $this->mapTreeRecursive($tree, $this->node->getKey(), $affectedKeys);
- return forward_static_call(array($className, 'firstOrNew'), $attributes);
- }
+ if ($result && count($affectedKeys) > 0)
+ $this->deleteUnaffected($affectedKeys);
- protected function pruneScope() {
- if ( $this->node->exists )
- return $this->node->descendants();
+ return $result;
+ }
+
+ /**
+ * Returns the children key name to use on the mapping array
+ *
+ * @return string
+ */
+ public function getChildrenKeyName()
+ {
+ return $this->childrenKeyName;
+ }
- return $this->node->newNestedSetQuery();
- }
+ /**
+ * Maps a tree structure into the database
+ *
+ * @param array $tree
+ * @param mixed $parent
+ * @return boolean
+ */
+ protected function mapTreeRecursive(array $tree, $parentKey = null, &$affectedKeys = array())
+ {
+ // For every attribute entry: We'll need to instantiate a new node either
+ // from the database (if the primary key was supplied) or a new instance. Then,
+ // append all the remaining data attributes (including the `parent_id` if
+ // present) and save it. Finally, tail-recurse performing the same
+ // operations for any child node present. Setting the `parent_id` property at
+ // each level will take care of the nesting work for us.
+ foreach ($tree as $attributes) {
+ $node = $this->firstOrNew($this->getSearchAttributes($attributes));
+
+ $data = $this->getDataAttributes($attributes);
+ if (!is_null($parentKey))
+ $data[$node->getParentColumnName()] = $parentKey;
+
+ $node->fill($data);
+
+ $result = $node->save();
+
+ if (!$result) return false;
+
+ $affectedKeys[] = $node->getKey();
+
+ if (array_key_exists($this->getChildrenKeyName(), $attributes)) {
+ $children = $attributes[$this->getChildrenKeyName()];
+
+ if (count($children) > 0) {
+ $result = $this->mapTreeRecursive($children, $node->getKey(), $affectedKeys);
+
+ if (!$result) return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ protected function getSearchAttributes($attributes)
+ {
+ $searchable = array($this->node->getKeyName());
+
+ return Arr::only($attributes, $searchable);
+ }
- protected function deleteUnaffected($keys = array()) {
- return $this->pruneScope()->whereNotIn($this->node->getKeyName(), $keys)->delete();
- }
+ protected function getDataAttributes($attributes)
+ {
+ $exceptions = array($this->node->getKeyName(), $this->getChildrenKeyName());
- protected function wrapInTransaction(Closure $callback) {
- return $this->node->getConnection()->transaction($callback);
- }
+ return Arr::except($attributes, $exceptions);
+ }
+
+ protected function firstOrNew($attributes)
+ {
+ $className = get_class($this->node);
+
+ if (count($attributes) === 0)
+ return new $className;
+
+ return forward_static_call(array($className, 'firstOrNew'), $attributes);
+ }
+
+ protected function pruneScope()
+ {
+ if ($this->node->exists)
+ return $this->node->descendants();
+
+ return $this->node->newNestedSetQuery();
+ }
+
+ protected function deleteUnaffected($keys = array())
+ {
+ return $this->pruneScope()->whereNotIn($this->node->getKeyName(), $keys)->delete();
+ }
+
+ protected function wrapInTransaction(Closure $callback)
+ {
+ return $this->node->getConnection()->transaction($callback);
+ }
}
diff --git a/src/SetValidator.php b/src/SetValidator.php
index 10d87640..9cec5472 100644
--- a/src/SetValidator.php
+++ b/src/SetValidator.php
@@ -1,224 +1,238 @@
node = $node;
- }
-
- /**
- * Determine if the validation passes.
- *
- * @return boolean
- */
- public function passes() {
- return $this->validateBounds() && $this->validateDuplicates() &&
- $this->validateRoots();
- }
-
- /**
- * Determine if validation fails.
- *
- * @return boolean
- */
- public function fails() {
- return !$this->passes();
- }
-
- /**
- * Validates bounds of the nested tree structure. It will perform checks on
- * the `lft`, `rgt` and `parent_id` columns. Mainly that they're not null,
- * rights greater than lefts, and that they're within the bounds of the parent.
- *
- * @return boolean
- */
- protected function validateBounds() {
- $connection = $this->node->getConnection();
- $grammar = $connection->getQueryGrammar();
-
- $tableName = $this->node->getTable();
- $primaryKeyName = $this->node->getKeyName();
- $parentColumn = $this->node->getQualifiedParentColumnName();
-
- $lftCol = $grammar->wrap($this->node->getLeftColumnName());
- $rgtCol = $grammar->wrap($this->node->getRightColumnName());
-
- $qualifiedLftCol = $grammar->wrap($this->node->getQualifiedLeftColumnName());
- $qualifiedRgtCol = $grammar->wrap($this->node->getQualifiedRightColumnName());
- $qualifiedParentCol = $grammar->wrap($this->node->getQualifiedParentColumnName());
-
- $whereStm = "($qualifiedLftCol IS NULL OR
+class SetValidator
+{
+
+ /**
+ * Node instance for reference
+ *
+ * @var \Baum\Node
+ */
+ protected $node = null;
+
+ /**
+ * Create a new \Baum\SetValidator class instance.
+ *
+ * @param \Baum\Node $node
+ * @return void
+ */
+ public function __construct($node)
+ {
+ $this->node = $node;
+ }
+
+ /**
+ * Determine if the validation passes.
+ *
+ * @return boolean
+ */
+ public function passes()
+ {
+ return $this->validateBounds() && $this->validateDuplicates() &&
+ $this->validateRoots();
+ }
+
+ /**
+ * Determine if validation fails.
+ *
+ * @return boolean
+ */
+ public function fails()
+ {
+ return !$this->passes();
+ }
+
+ /**
+ * Validates bounds of the nested tree structure. It will perform checks on
+ * the `lft`, `rgt` and `parent_id` columns. Mainly that they're not null,
+ * rights greater than lefts, and that they're within the bounds of the parent.
+ *
+ * @return boolean
+ */
+ protected function validateBounds()
+ {
+ $connection = $this->node->getConnection();
+ $grammar = $connection->getQueryGrammar();
+
+ $tableName = $this->node->getTable();
+ $primaryKeyName = $this->node->getKeyName();
+ $parentColumn = $this->node->getQualifiedParentColumnName();
+
+ $lftCol = $grammar->wrap($this->node->getLeftColumnName());
+ $rgtCol = $grammar->wrap($this->node->getRightColumnName());
+
+ $qualifiedLftCol = $grammar->wrap($this->node->getQualifiedLeftColumnName());
+ $qualifiedRgtCol = $grammar->wrap($this->node->getQualifiedRightColumnName());
+ $qualifiedParentCol = $grammar->wrap($this->node->getQualifiedParentColumnName());
+
+ $whereStm = "($qualifiedLftCol IS NULL OR
$qualifiedRgtCol IS NULL OR
$qualifiedLftCol >= $qualifiedRgtCol OR
($qualifiedParentCol IS NOT NULL AND
($qualifiedLftCol <= parent.$lftCol OR
$qualifiedRgtCol >= parent.$rgtCol)))";
- $query = $this->node->newQuery()
- ->join($connection->raw($grammar->wrapTable($tableName).' AS parent'),
- $parentColumn, '=', $connection->raw('parent.'.$grammar->wrap($primaryKeyName)),
- 'left outer')
- ->whereRaw($whereStm);
-
- return ($query->count() == 0);
- }
-
- /**
- * Checks that there are no duplicates for the `lft` and `rgt` columns.
- *
- * @return boolean
- */
- protected function validateDuplicates() {
- return (
- !$this->duplicatesExistForColumn($this->node->getQualifiedLeftColumnName()) &&
- !$this->duplicatesExistForColumn($this->node->getQualifiedRightColumnName())
- );
- }
-
- /**
- * For each root of the whole nested set tree structure, checks that their
- * `lft` and `rgt` bounds are properly set.
- *
- * @return boolean
- */
- protected function validateRoots() {
- $roots = forward_static_call(array(get_class($this->node), 'roots'))->get();
-
- // If a scope is defined in the model we should check that the roots are
- // valid *for each* value in the scope columns.
- if ( $this->node->isScoped() )
- return $this->validateRootsByScope($roots);
-
- return $this->isEachRootValid($roots);
- }
-
- /**
- * Checks if duplicate values for the column specified exist. Takes
- * the Nested Set scope columns into account (if appropiate).
- *
- * @param string $column
- * @return boolean
- */
- protected function duplicatesExistForColumn($column) {
- $connection = $this->node->getConnection();
- $grammar = $connection->getQueryGrammar();
-
- $columns = array_merge($this->node->getQualifiedScopedColumns(), array($column));
-
- $columnsForSelect = implode(', ', array_map(function($col) use ($grammar) {
- return $grammar->wrap($col); }, $columns));
-
- $wrappedColumn = $grammar->wrap($column);
-
- $query = $this->node->newQuery()
- ->select($connection->raw("$columnsForSelect, COUNT($wrappedColumn)"))
- ->havingRaw("COUNT($wrappedColumn) > 1");
-
- foreach($columns as $col)
- $query->groupBy($col);
-
- $result = $query->first();
-
- return !is_null($result);
- }
-
- /**
- * Check that each root node in the list supplied satisfies that its bounds
- * values (lft, rgt indexes) are less than the next.
- *
- * @param mixed $roots
- * @return boolean
- */
- protected function isEachRootValid($roots) {
- $left = $right = 0;
-
- foreach($roots as $root) {
- $rootLeft = $root->getLeft();
- $rootRight = $root->getRight();
-
- if ( !($rootLeft > $left && $rootRight > $right) )
- return false;
-
- $left = $rootLeft;
- $right = $rootRight;
+ $query = $this->node->newQuery()
+ ->join($connection->raw($grammar->wrapTable($tableName) . ' AS parent'),
+ $parentColumn, '=', $connection->raw('parent.' . $grammar->wrap($primaryKeyName)),
+ 'left outer')
+ ->whereRaw($whereStm);
+
+ return ($query->count() == 0);
+ }
+
+ /**
+ * Checks that there are no duplicates for the `lft` and `rgt` columns.
+ *
+ * @return boolean
+ */
+ protected function validateDuplicates()
+ {
+ return (
+ !$this->duplicatesExistForColumn($this->node->getQualifiedLeftColumnName()) &&
+ !$this->duplicatesExistForColumn($this->node->getQualifiedRightColumnName())
+ );
+ }
+
+ /**
+ * For each root of the whole nested set tree structure, checks that their
+ * `lft` and `rgt` bounds are properly set.
+ *
+ * @return boolean
+ */
+ protected function validateRoots()
+ {
+ $roots = forward_static_call(array(get_class($this->node), 'roots'))->get();
+
+ // If a scope is defined in the model we should check that the roots are
+ // valid *for each* value in the scope columns.
+ if ($this->node->isScoped())
+ return $this->validateRootsByScope($roots);
+
+ return $this->isEachRootValid($roots);
}
- return true;
- }
-
- /**
- * Check that each root node in the list supplied satisfies that its bounds
- * values (lft, rgt indexes) are less than the next *within each scope*.
- *
- * @param mixed $roots
- * @return boolean
- */
- protected function validateRootsByScope($roots) {
- foreach($this->groupRootsByScope($roots) as $scope => $groupedRoots) {
- $valid = $this->isEachRootValid($groupedRoots);
-
- if ( !$valid )
- return false;
+ /**
+ * Checks if duplicate values for the column specified exist. Takes
+ * the Nested Set scope columns into account (if appropiate).
+ *
+ * @param string $column
+ * @return boolean
+ */
+ protected function duplicatesExistForColumn($column)
+ {
+ $connection = $this->node->getConnection();
+ $grammar = $connection->getQueryGrammar();
+
+ $columns = array_merge($this->node->getQualifiedScopedColumns(), array($column));
+
+ $columnsForSelect = implode(', ', array_map(function ($col) use ($grammar) {
+ return $grammar->wrap($col);
+ }, $columns));
+
+ $wrappedColumn = $grammar->wrap($column);
+
+ $query = $this->node->newQuery()
+ ->select($connection->raw("$columnsForSelect, COUNT($wrappedColumn)"))
+ ->havingRaw("COUNT($wrappedColumn) > 1");
+
+ foreach ($columns as $col)
+ $query->groupBy($col);
+
+ $result = $query->first();
+
+ return !is_null($result);
+ }
+
+ /**
+ * Check that each root node in the list supplied satisfies that its bounds
+ * values (lft, rgt indexes) are less than the next.
+ *
+ * @param mixed $roots
+ * @return boolean
+ */
+ protected function isEachRootValid($roots)
+ {
+ $left = $right = 0;
+
+ foreach ($roots as $root) {
+ $rootLeft = $root->getLeft();
+ $rootRight = $root->getRight();
+
+ if (!($rootLeft > $left && $rootRight > $right))
+ return false;
+
+ $left = $rootLeft;
+ $right = $rootRight;
+ }
+
+ return true;
}
- return true;
- }
+ /**
+ * Check that each root node in the list supplied satisfies that its bounds
+ * values (lft, rgt indexes) are less than the next *within each scope*.
+ *
+ * @param mixed $roots
+ * @return boolean
+ */
+ protected function validateRootsByScope($roots)
+ {
+ foreach ($this->groupRootsByScope($roots) as $scope => $groupedRoots) {
+ $valid = $this->isEachRootValid($groupedRoots);
+
+ if (!$valid)
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Given a list of root nodes, it returns an array in which the keys are the
+ * array of the actual scope column values and the values are the root nodes
+ * inside that scope themselves
+ *
+ * @param mixed $roots
+ * @return array
+ */
+ protected function groupRootsByScope($roots)
+ {
+ $rootsGroupedByScope = array();
- /**
- * Given a list of root nodes, it returns an array in which the keys are the
- * array of the actual scope column values and the values are the root nodes
- * inside that scope themselves
- *
- * @param mixed $roots
- * @return array
- */
- protected function groupRootsByScope($roots) {
- $rootsGroupedByScope = array();
+ foreach ($roots as $root) {
+ $key = $this->keyForScope($root);
- foreach($roots as $root) {
- $key = $this->keyForScope($root);
+ if (!isset($rootsGroupedByScope[$key]))
+ $rootsGroupedByScope[$key] = array();
- if ( !isset($rootsGroupedByScope[$key]) )
- $rootsGroupedByScope[$key] = array();
+ $rootsGroupedByScope[$key][] = $root;
+ }
- $rootsGroupedByScope[$key][] = $root;
+ return $rootsGroupedByScope;
}
- return $rootsGroupedByScope;
- }
-
- /**
- * Builds a single string for the given scope columns values. Useful for
- * making array keys for grouping.
- *
- * @param Baum\Node $node
- * @return string
- */
- protected function keyForScope($node) {
- return implode('-', array_map(function($column) use ($node) {
- $value = $node->getAttribute($column);
-
- if ( is_null($value) )
- return 'NULL';
-
- return $value;
- }, $node->getScopedColumns()));
- }
+ /**
+ * Builds a single string for the given scope columns values. Useful for
+ * making array keys for grouping.
+ *
+ * @param Baum\Node $node
+ * @return string
+ */
+ protected function keyForScope($node)
+ {
+ return implode('-', array_map(function ($column) use ($node) {
+ $value = $node->getAttribute($column);
+
+ if (is_null($value))
+ return 'NULL';
+
+ return $value;
+ }, $node->getScopedColumns()));
+ }
}
diff --git a/tests/suite/BaumTestCase.php b/tests/suite/BaumTestCase.php
index 68b6e445..17d730a4 100644
--- a/tests/suite/BaumTestCase.php
+++ b/tests/suite/BaumTestCase.php
@@ -2,13 +2,13 @@
use PHPUnit\Framework\TestCase;
-class BaumTestCase extends TestCase {
-
- public function assertArraysAreEqual($expected, $actual, $message = '') {
- $ex = var_export($expected, true);
- $ac = var_export($actual, true);
-
- return $this->assertEquals($ex, $ac, $message);
- }
-
+class BaumTestCase extends TestCase
+{
+ public function assertArraysAreEqual($expected, $actual, $message = '')
+ {
+ $ex = var_export($expected, true);
+ $ac = var_export($actual, true);
+
+ $this->assertEquals($ex, $ac, $message);
+ }
}
diff --git a/tests/suite/Category/CategoryColumnsTest.php b/tests/suite/Category/CategoryColumnsTest.php
index 02f1bd3b..f970eead 100644
--- a/tests/suite/Category/CategoryColumnsTest.php
+++ b/tests/suite/Category/CategoryColumnsTest.php
@@ -1,131 +1,150 @@
assertEquals(with(new Category)->getParentColumnName(), 'parent_id');
- }
+ $this->assertEquals(with(new Category)->getParentColumnName(), 'parent_id');
+ }
- public function testGetQualifiedParentColumnName() {
- $category = new Category;
+ public function testGetQualifiedParentColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getQualifiedParentColumnName(), 'categories.parent_id');
- }
+ $this->assertEquals($category->getQualifiedParentColumnName(), 'categories.parent_id');
+ }
- public function testGetParentId() {
- $this->assertNull($this->categories('Root 1')->getParentId());
+ public function testGetParentId()
+ {
+ $this->assertNull($this->categories('Root 1')->getParentId());
- $this->assertEquals($this->categories('Child 1')->getParentId(), 1);
- }
+ $this->assertEquals($this->categories('Child 1')->getParentId(), 1);
+ }
- public function testGetLeftColumnName() {
- $category = new Category;
+ public function testGetLeftColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getLeftColumnName(), 'lft');
- }
+ $this->assertEquals($category->getLeftColumnName(), 'lft');
+ }
- public function testGetQualifiedLeftColumnName() {
- $category = new Category;
+ public function testGetQualifiedLeftColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getQualifiedLeftColumnName(), 'categories.lft');
- }
+ $this->assertEquals($category->getQualifiedLeftColumnName(), 'categories.lft');
+ }
- public function testGetLeft() {
- $category = $this->categories('Root 1');
+ public function testGetLeft()
+ {
+ $category = $this->categories('Root 1');
- $this->assertEquals($category->getLeft(), 1);
- }
+ $this->assertEquals($category->getLeft(), 1);
+ }
- public function testGetRightColumnName() {
- $category = new Category;
+ public function testGetRightColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getRightColumnName(), 'rgt');
- }
+ $this->assertEquals($category->getRightColumnName(), 'rgt');
+ }
- public function testGetQualifiedRightColumnName() {
- $category = new Category;
+ public function testGetQualifiedRightColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getQualifiedRightColumnName(), 'categories.rgt');
- }
+ $this->assertEquals($category->getQualifiedRightColumnName(), 'categories.rgt');
+ }
- public function testGetRight() {
- $category = $this->categories('Root 1');
+ public function testGetRight()
+ {
+ $category = $this->categories('Root 1');
- $this->assertEquals($category->getRight(), 10);
- }
+ $this->assertEquals($category->getRight(), 10);
+ }
- public function testGetOrderColumName() {
- $category = new Category;
+ public function testGetOrderColumName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getOrderColumnName(), $category->getLeftColumnName());
- }
+ $this->assertEquals($category->getOrderColumnName(), $category->getLeftColumnName());
+ }
- public function testGetQualifiedOrderColumnName() {
- $category = new Category;
+ public function testGetQualifiedOrderColumnName()
+ {
+ $category = new Category;
- $this->assertEquals($category->getQualifiedOrderColumnName(), $category->getQualifiedLeftColumnName());
- }
+ $this->assertEquals($category->getQualifiedOrderColumnName(), $category->getQualifiedLeftColumnName());
+ }
- public function testGetOrder() {
- $category = $this->categories('Root 1');
+ public function testGetOrder()
+ {
+ $category = $this->categories('Root 1');
- $this->assertEquals($category->getOrder(), $category->getLeft());
- }
+ $this->assertEquals($category->getOrder(), $category->getLeft());
+ }
- public function testGetOrderColumnNameNonDefault() {
- $category = new OrderedCategory;
+ public function testGetOrderColumnNameNonDefault()
+ {
+ $category = new OrderedCategory;
- $this->assertEquals($category->getOrderColumnName(), 'name');
- }
+ $this->assertEquals($category->getOrderColumnName(), 'name');
+ }
- public function testGetQualifiedOrderColumnNameNonDefault() {
- $category = new OrderedCategory;
+ public function testGetQualifiedOrderColumnNameNonDefault()
+ {
+ $category = new OrderedCategory;
- $this->assertEquals($category->getQualifiedOrderColumnName(), 'categories.name');
- }
+ $this->assertEquals($category->getQualifiedOrderColumnName(), 'categories.name');
+ }
- public function testGetOrderNonDefault() {
- $category = $this->categories('Root 1', 'OrderedCategory');
+ public function testGetOrderNonDefault()
+ {
+ $category = $this->categories('Root 1', 'OrderedCategory');
- $this->assertEquals($category->getOrder(), 'Root 1');
- }
+ $this->assertEquals($category->getOrder(), 'Root 1');
+ }
- public function testGetScopedColumns() {
- $category = new Category;
- $this->assertEquals($category->getScopedColumns(), array());
+ public function testGetScopedColumns()
+ {
+ $category = new Category;
+ $this->assertEquals($category->getScopedColumns(), array());
- $category = new ScopedCategory;
- $this->assertEquals($category->getScopedColumns(), array('company_id'));
+ $category = new ScopedCategory;
+ $this->assertEquals($category->getScopedColumns(), array('company_id'));
- $category = new MultiScopedCategory;
- $this->assertEquals($category->getScopedColumns(), array('company_id', 'language'));
- }
+ $category = new MultiScopedCategory;
+ $this->assertEquals($category->getScopedColumns(), array('company_id', 'language'));
+ }
- public function testGetQualifiedScopedColumns() {
- $category = new Category;
- $this->assertEquals($category->getQualifiedScopedColumns(), array());
+ public function testGetQualifiedScopedColumns()
+ {
+ $category = new Category;
+ $this->assertEquals($category->getQualifiedScopedColumns(), array());
- $category = new ScopedCategory;
- $this->assertEquals($category->getQualifiedScopedColumns(), array('categories.company_id'));
+ $category = new ScopedCategory;
+ $this->assertEquals($category->getQualifiedScopedColumns(), array('categories.company_id'));
- $category = new MultiScopedCategory;
- $this->assertEquals($category->getQualifiedScopedColumns(), array('categories.company_id', 'categories.language'));
- }
+ $category = new MultiScopedCategory;
+ $this->assertEquals($category->getQualifiedScopedColumns(), array('categories.company_id', 'categories.language'));
+ }
- public function testIsScoped() {
- $category = new Category;
- $this->assertFalse($category->isScoped());
+ public function testIsScoped()
+ {
+ $category = new Category;
+ $this->assertFalse($category->isScoped());
- $category = new ScopedCategory;
- $this->assertTrue($category->isScoped());
+ $category = new ScopedCategory;
+ $this->assertTrue($category->isScoped());
- $category = new MultiScopedCategory;
- $this->assertTrue($category->isScoped());
+ $category = new MultiScopedCategory;
+ $this->assertTrue($category->isScoped());
- $category = new OrderedCategory();
- $this->assertFalse($category->isScoped());
- }
+ $category = new OrderedCategory();
+ $this->assertFalse($category->isScoped());
+ }
}
diff --git a/tests/suite/Category/CategoryCustomEventsTest.php b/tests/suite/Category/CategoryCustomEventsTest.php
index ec2ada15..a5b088f8 100644
--- a/tests/suite/Category/CategoryCustomEventsTest.php
+++ b/tests/suite/Category/CategoryCustomEventsTest.php
@@ -2,55 +2,61 @@
use Mockery as m;
-class CategoryCustomEventsTest extends CategoryTestCase {
+class CategoryCustomEventsTest extends CategoryTestCase
+{
- public function tearDown() {
- m::close();
- }
+ public function tearDown(): void
+ {
+ m::close();
+ }
- public function testMovementEventsFire() {
- $child1 = $this->categories('Child 1');
- $child3 = $this->categories('Child 3');
+ public function testMovementEventsFire()
+ {
+ $child1 = $this->categories('Child 1');
+ $child3 = $this->categories('Child 3');
- $dispatcher = Category::getEventDispatcher();
+ $dispatcher = Category::getEventDispatcher();
- Category::setEventDispatcher($events = m::mock('\Illuminate\Events\Dispatcher')->makePartial());
+ Category::setEventDispatcher($events = m::mock('\Illuminate\Events\Dispatcher')->makePartial());
- $events->shouldReceive('until')->once()->with('eloquent.moving: '.get_class($child1), $child1)->andReturn(true);
+ $events->shouldReceive('until')->once()->with('eloquent.moving: ' . get_class($child1), $child1)->andReturn(true);
- $events->shouldReceive('dispatch')->once()->with('eloquent.moved: '.get_class($child1), $child1)->andReturn(true);
+ $events->shouldReceive('dispatch')->once()->with('eloquent.moved: ' . get_class($child1), $child1)->andReturn(true);
- $child1->moveToRightOf($child3);
+ $child1->moveToRightOf($child3);
- Category::unsetEventDispatcher();
- Category::setEventDispatcher($dispatcher);
- }
+ Category::unsetEventDispatcher();
+ Category::setEventDispatcher($dispatcher);
+ }
- public function testMovementHaltsWhenReturningFalseFromMoving() {
- $unchanged = $this->categories('Child 2');
+ public function testMovementHaltsWhenReturningFalseFromMoving()
+ {
+ $unchanged = $this->categories('Child 2');
- $dispatcher = Category::getEventDispatcher();
+ $dispatcher = Category::getEventDispatcher();
- Category::setEventDispatcher($events = m::mock('Illuminate\Events\Dispatcher')->makePartial());
- $events->shouldReceive('until')->once()->with('eloquent.moving: '.get_class($unchanged), $unchanged)->andReturn(false);
+ Category::setEventDispatcher($events = m::mock('Illuminate\Events\Dispatcher')->makePartial());
+ $events->shouldReceive('until')->once()->with('eloquent.moving: ' . get_class($unchanged), $unchanged)->andReturn(false);
- // Force "moving" to return false
- Category::moving(function($node) { return false; });
+ // Force "moving" to return false
+ Category::moving(function ($node) {
+ return false;
+ });
- $unchanged->makeRoot();
+ $unchanged->makeRoot();
- $unchanged->reload();
+ $unchanged->reload();
- $this->assertEquals(1, $unchanged->getParentId());
- $this->assertEquals(1, $unchanged->getLevel());
- $this->assertEquals(4, $unchanged->getLeft());
- $this->assertEquals(7, $unchanged->getRight());
+ $this->assertEquals(1, $unchanged->getParentId());
+ $this->assertEquals(1, $unchanged->getLevel());
+ $this->assertEquals(4, $unchanged->getLeft());
+ $this->assertEquals(7, $unchanged->getRight());
- // Restore
- Category::getEventDispatcher()->forget('eloquent.moving: '.get_class($unchanged));
+ // Restore
+ Category::getEventDispatcher()->forget('eloquent.moving: ' . get_class($unchanged));
- Category::unsetEventDispatcher();
- Category::setEventDispatcher($dispatcher);
- }
+ Category::unsetEventDispatcher();
+ Category::setEventDispatcher($dispatcher);
+ }
}
diff --git a/tests/suite/Category/CategoryHierarchyTest.php b/tests/suite/Category/CategoryHierarchyTest.php
index bad299c6..2f40d0a7 100644
--- a/tests/suite/Category/CategoryHierarchyTest.php
+++ b/tests/suite/Category/CategoryHierarchyTest.php
@@ -1,705 +1,761 @@
orderBy('lft')->get();
+ public function testAllStatic()
+ {
+ $results = Category::all();
+ $expected = Category::query()->orderBy('lft')->get();
- $this->assertEquals($results, $expected);
- }
+ $this->assertEquals($results, $expected);
+ }
- public function testAllStaticWithCustomOrder() {
- $results = OrderedCategory::all();
- $expected = OrderedCategory::query()->orderBy('name')->get();
+ public function testAllStaticWithCustomOrder()
+ {
+ $results = OrderedCategory::all();
+ $expected = OrderedCategory::query()->orderBy('name')->get();
- $this->assertEquals($results, $expected);
- }
+ $this->assertEquals($results, $expected);
+ }
- public function testRootsStatic() {
- $query = Category::whereNull('parent_id')->get();
+ public function testRootsStatic()
+ {
+ $query = Category::whereNull('parent_id')->get();
- $roots = Category::roots()->get();
+ $roots = Category::roots()->get();
- $this->assertEquals($query->count(), $roots->count());
- $this->assertCount(2, $roots);
+ $this->assertEquals($query->count(), $roots->count());
+ $this->assertCount(2, $roots);
- foreach($query->pluck('id')as $node)
- $this->assertContains($node, $roots->pluck('id'));
- }
+ foreach ($query->pluck('id') as $node)
+ $this->assertContains($node, $roots->pluck('id'));
+ }
- public function testRootsStaticWithCustomOrder() {
- $category = OrderedCategory::create(array('name' => 'A new root is born'));
- $category->syncOriginal(); // ¿? --> This should be done already !?
+ public function testRootsStaticWithCustomOrder()
+ {
+ $category = OrderedCategory::create(array('name' => 'A new root is born'));
+ $category->syncOriginal(); // ¿? --> This should be done already !?
- $roots = OrderedCategory::roots()->get();
+ $roots = OrderedCategory::roots()->get();
- $this->assertCount(3, $roots);
- $this->assertEquals($category->getAttributes(), $roots->first()->getAttributes());
- }
+ $this->assertCount(3, $roots);
+ $this->assertEquals($category->getAttributes(), $roots->first()->getAttributes());
+ }
- public function testRootStatic() {
- $this->assertEquals(Category::root(), $this->categories('Root 1'));
- }
+ public function testRootStatic()
+ {
+ $this->assertEquals(Category::root(), $this->categories('Root 1'));
+ }
- public function testAllLeavesStatic() {
- $allLeaves = Category::allLeaves()->get();
+ public function testAllLeavesStatic()
+ {
+ $allLeaves = Category::allLeaves()->get();
- $this->assertCount(4, $allLeaves);
+ $this->assertCount(4, $allLeaves);
- $leaves = $allLeaves->pluck('name');
+ $leaves = $allLeaves->pluck('name');
- $this->assertContains('Child 1' , $leaves);
- $this->assertContains('Child 2.1' , $leaves);
- $this->assertContains('Child 3' , $leaves);
- $this->assertContains('Root 2' , $leaves);
- }
+ $this->assertContains('Child 1', $leaves);
+ $this->assertContains('Child 2.1', $leaves);
+ $this->assertContains('Child 3', $leaves);
+ $this->assertContains('Root 2', $leaves);
+ }
- public function testAllTrunksStatic() {
- $allTrunks = Category::allTrunks()->get();
+ public function testAllTrunksStatic()
+ {
+ $allTrunks = Category::allTrunks()->get();
- $this->assertCount(1, $allTrunks);
+ $this->assertCount(1, $allTrunks);
- $trunks = $allTrunks->pluck('name');
- $this->assertContains('Child 2', $trunks);
- }
+ $trunks = $allTrunks->pluck('name');
+ $this->assertContains('Child 2', $trunks);
+ }
- public function testGetRoot() {
- $this->assertEquals($this->categories('Root 1'), $this->categories('Root 1')->getRoot());
- $this->assertEquals($this->categories('Root 2'), $this->categories('Root 2')->getRoot());
+ public function testGetRoot()
+ {
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Root 1')->getRoot());
+ $this->assertEquals($this->categories('Root 2'), $this->categories('Root 2')->getRoot());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Child 1')->getRoot());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Child 2')->getRoot());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Child 2.1')->getRoot());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Child 3')->getRoot());
- }
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Child 1')->getRoot());
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Child 2')->getRoot());
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Child 2.1')->getRoot());
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Child 3')->getRoot());
+ }
- public function testGetRootEqualsSelfIfUnpersisted() {
- $category = new Category;
+ public function testGetRootEqualsSelfIfUnpersisted()
+ {
+ $category = new Category;
- $this->assertEquals($category->getRoot(), $category);
- }
+ $this->assertEquals($category->getRoot(), $category);
+ }
- public function testGetRootEqualsValueIfSetIfUnpersisted() {
- $parent = Category::roots()->first();
+ public function testGetRootEqualsValueIfSetIfUnpersisted()
+ {
+ $parent = Category::roots()->first();
- $child = new Category;
- $child->setAttribute($child->getParentColumnName(), $parent->getKey());
+ $child = new Category;
+ $child->setAttribute($child->getParentColumnName(), $parent->getKey());
- $this->assertEquals($child->getRoot(), $parent);
- }
+ $this->assertEquals($child->getRoot(), $parent);
+ }
- public function testIsRoot() {
- $this->assertTrue($this->categories('Root 1')->isRoot());
- $this->assertTrue($this->categories('Root 2')->isRoot());
+ public function testIsRoot()
+ {
+ $this->assertTrue($this->categories('Root 1')->isRoot());
+ $this->assertTrue($this->categories('Root 2')->isRoot());
- $this->assertFalse($this->categories('Child 1')->isRoot());
- $this->assertFalse($this->categories('Child 2')->isRoot());
- $this->assertFalse($this->categories('Child 2.1')->isRoot());
- $this->assertFalse($this->categories('Child 3')->isRoot());
- }
+ $this->assertFalse($this->categories('Child 1')->isRoot());
+ $this->assertFalse($this->categories('Child 2')->isRoot());
+ $this->assertFalse($this->categories('Child 2.1')->isRoot());
+ $this->assertFalse($this->categories('Child 3')->isRoot());
+ }
- public function testGetLeaves() {
- $leaves = array($this->categories('Child 1'), $this->categories('Child 2.1'), $this->categories('Child 3'));
+ public function testGetLeaves()
+ {
+ $leaves = array($this->categories('Child 1'), $this->categories('Child 2.1'), $this->categories('Child 3'));
- $this->assertEquals($leaves, $this->categories('Root 1')->getLeaves()->all());
- }
+ $this->assertEquals($leaves, $this->categories('Root 1')->getLeaves()->all());
+ }
- public function testGetLeavesInIteration() {
- $node = $this->categories('Root 1');
+ public function testGetLeavesInIteration()
+ {
+ $node = $this->categories('Root 1');
- $expectedIds = array(2, 4, 5);
+ $expectedIds = array(2, 4, 5);
- foreach($node->getLeaves() as $i => $leaf)
- $this->assertEquals($expectedIds[$i], $leaf->getKey());
- }
+ foreach ($node->getLeaves() as $i => $leaf)
+ $this->assertEquals($expectedIds[$i], $leaf->getKey());
+ }
- public function testGetTrunks() {
- $trunks = array($this->categories('Child 2'));
+ public function testGetTrunks()
+ {
+ $trunks = array($this->categories('Child 2'));
- $this->assertEquals($trunks, $this->categories('Root 1')->getTrunks()->all());
- }
+ $this->assertEquals($trunks, $this->categories('Root 1')->getTrunks()->all());
+ }
- public function testGetTrunksInIteration() {
- $node = $this->categories('Root 1');
+ public function testGetTrunksInIteration()
+ {
+ $node = $this->categories('Root 1');
- $expectedIds = array(3);
+ $expectedIds = array(3);
- foreach($node->getTrunks() as $i => $trunk)
- $this->assertEquals($expectedIds[$i], $trunk->getKey());
- }
+ foreach ($node->getTrunks() as $i => $trunk)
+ $this->assertEquals($expectedIds[$i], $trunk->getKey());
+ }
- public function testIsLeaf() {
- $this->assertTrue($this->categories('Child 1')->isLeaf());
- $this->assertTrue($this->categories('Child 2.1')->isLeaf());
- $this->assertTrue($this->categories('Child 3')->isLeaf());
- $this->assertTrue($this->categories('Root 2')->isLeaf());
+ public function testIsLeaf()
+ {
+ $this->assertTrue($this->categories('Child 1')->isLeaf());
+ $this->assertTrue($this->categories('Child 2.1')->isLeaf());
+ $this->assertTrue($this->categories('Child 3')->isLeaf());
+ $this->assertTrue($this->categories('Root 2')->isLeaf());
- $this->assertFalse($this->categories('Root 1')->isLeaf());
- $this->assertFalse($this->categories('Child 2')->isLeaf());
+ $this->assertFalse($this->categories('Root 1')->isLeaf());
+ $this->assertFalse($this->categories('Child 2')->isLeaf());
- $new = new Category;
- $this->assertFalse($new->isLeaf());
- }
+ $new = new Category;
+ $this->assertFalse($new->isLeaf());
+ }
- public function testIsTrunk() {
- $this->assertFalse($this->categories('Child 1')->isTrunk());
- $this->assertFalse($this->categories('Child 2.1')->isTrunk());
- $this->assertFalse($this->categories('Child 3')->isTrunk());
- $this->assertFalse($this->categories('Root 2')->isTrunk());
+ public function testIsTrunk()
+ {
+ $this->assertFalse($this->categories('Child 1')->isTrunk());
+ $this->assertFalse($this->categories('Child 2.1')->isTrunk());
+ $this->assertFalse($this->categories('Child 3')->isTrunk());
+ $this->assertFalse($this->categories('Root 2')->isTrunk());
- $this->assertFalse($this->categories('Root 1')->isTrunk());
- $this->assertTrue($this->categories('Child 2')->isTrunk());
+ $this->assertFalse($this->categories('Root 1')->isTrunk());
+ $this->assertTrue($this->categories('Child 2')->isTrunk());
- $new = new Category;
- $this->assertFalse($new->isTrunk());
- }
+ $new = new Category;
+ $this->assertFalse($new->isTrunk());
+ }
- public function testWithoutNodeScope() {
- $child = $this->categories('Child 2.1');
+ public function testWithoutNodeScope()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Root 1'), $child);
+ $expected = array($this->categories('Root 1'), $child);
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutNode($this->categories('Child 2'))->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutNode($this->categories('Child 2'))->get()->all());
+ }
- public function testWithoutSelfScope() {
- $child = $this->categories('Child 2.1');
+ public function testWithoutSelfScope()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Root 1'), $this->categories('Child 2'));
+ $expected = array($this->categories('Root 1'), $this->categories('Child 2'));
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutSelf()->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutSelf()->get()->all());
+ }
- public function testWithoutRootScope() {
- $child = $this->categories('Child 2.1');
+ public function testWithoutRootScope()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Child 2'), $child);
+ $expected = array($this->categories('Child 2'), $child);
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutRoot()->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutRoot()->get()->all());
+ }
- public function testLimitDepthScope() {
- with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 10);
+ public function testLimitDepthScope()
+ {
+ with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 10);
- $node = $this->categories('Child 2');
+ $node = $this->categories('Child 2');
- $descendancy = $node->descendants()->pluck('id')->all();
+ $descendancy = $node->descendants()->pluck('id')->all();
- $this->assertEmpty($node->descendants()->limitDepth(0)->pluck('id')->all());
- $this->assertEquals($node->getAttributes(), $node->descendantsAndSelf()->limitDepth(0)->first()->getAttributes());
+ $this->assertEmpty($node->descendants()->limitDepth(0)->pluck('id')->all());
+ $this->assertEquals($node->getAttributes(), $node->descendantsAndSelf()->limitDepth(0)->first()->getAttributes());
- $this->assertEquals(array_slice($descendancy, 0, 3), $node->descendants()->limitDepth(3)->pluck('id')->all());
- $this->assertEquals(array_slice($descendancy, 0, 5), $node->descendants()->limitDepth(5)->pluck('id')->all());
- $this->assertEquals(array_slice($descendancy, 0, 7), $node->descendants()->limitDepth(7)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 3), $node->descendants()->limitDepth(3)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 5), $node->descendants()->limitDepth(5)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 7), $node->descendants()->limitDepth(7)->pluck('id')->all());
- $this->assertEquals($descendancy, $node->descendants()->limitDepth(1000)->pluck('id')->all());
- }
+ $this->assertEquals($descendancy, $node->descendants()->limitDepth(1000)->pluck('id')->all());
+ }
- public function testGetAncestorsAndSelf() {
- $child = $this->categories('Child 2.1');
+ public function testGetAncestorsAndSelf()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Root 1'), $this->categories('Child 2'), $child);
+ $expected = array($this->categories('Root 1'), $this->categories('Child 2'), $child);
- $this->assertEquals($expected, $child->getAncestorsAndSelf()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsAndSelf()->all());
+ }
- public function testGetAncestorsAndSelfWithoutRoot() {
- $child = $this->categories('Child 2.1');
+ public function testGetAncestorsAndSelfWithoutRoot()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Child 2'), $child);
+ $expected = array($this->categories('Child 2'), $child);
- $this->assertEquals($expected, $child->getAncestorsAndSelfWithoutRoot()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsAndSelfWithoutRoot()->all());
+ }
- public function testGetAncestors() {
- $child = $this->categories('Child 2.1');
+ public function testGetAncestors()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Root 1'), $this->categories('Child 2'));
+ $expected = array($this->categories('Root 1'), $this->categories('Child 2'));
- $this->assertEquals($expected, $child->getAncestors()->all());
- }
+ $this->assertEquals($expected, $child->getAncestors()->all());
+ }
- public function testGetAncestorsWithoutRoot() {
- $child = $this->categories('Child 2.1');
+ public function testGetAncestorsWithoutRoot()
+ {
+ $child = $this->categories('Child 2.1');
- $expected = array($this->categories('Child 2'));
+ $expected = array($this->categories('Child 2'));
- $this->assertEquals($expected, $child->getAncestorsWithoutRoot()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsWithoutRoot()->all());
+ }
- public function testGetDescendantsAndSelf() {
- $parent = $this->categories('Root 1');
+ public function testGetDescendantsAndSelf()
+ {
+ $parent = $this->categories('Root 1');
- $expected = array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 3')
- );
+ $expected = array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 3')
+ );
- $this->assertCount(count($expected), $parent->getDescendantsAndSelf());
+ $this->assertCount(count($expected), $parent->getDescendantsAndSelf());
- $this->assertEquals($expected, $parent->getDescendantsAndSelf()->all());
- }
+ $this->assertEquals($expected, $parent->getDescendantsAndSelf()->all());
+ }
- public function testGetDescendantsAndSelfWithLimit() {
- with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 3);
-
- $parent = $this->categories('Root 1');
-
- $this->assertEquals(array($parent), $parent->getDescendantsAndSelf(0)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 3')
- ), $parent->getDescendantsAndSelf(1)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 3')
- ), $parent->getDescendantsAndSelf(2)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendantsAndSelf(3)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 2.1.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendantsAndSelf(4)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 2.1.1.1'),
- $this->categories('Child 2.1.1.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendantsAndSelf(10)->all());
- }
-
- public function testGetDescendants() {
- $parent = $this->categories('Root 1');
-
- $expected = array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 3')
- );
-
- $this->assertCount(count($expected), $parent->getDescendants());
-
- $this->assertEquals($expected, $parent->getDescendants()->all());
- }
-
- public function testGetDescendantsWithLimit() {
- with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 3);
-
- $parent = $this->categories('Root 1');
-
- $this->assertEmpty($parent->getDescendants(0)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 3')
- ), $parent->getDescendants(1)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 3')
- ), $parent->getDescendants(2)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendants(3)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 2.1.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendants(4)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 2.1.1.1'),
- $this->categories('Child 2.1.1.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendants(5)->all());
-
- $this->assertEquals(array(
- $this->categories('Child 1'),
- $this->categories('Child 2'),
- $this->categories('Child 2.1'),
- $this->categories('Child 2.1.1'),
- $this->categories('Child 2.1.1.1'),
- $this->categories('Child 2.1.1.1.1'),
- $this->categories('Child 3')
- ), $parent->getDescendants(10)->all());
- }
-
- public function testDescendantsRecursesChildren() {
- $a = Category::create(array('name' => 'A'));
- $b = Category::create(array('name' => 'B'));
- $c = Category::create(array('name' => 'C'));
-
- // a > b > c
- $b->makeChildOf($a);
- $c->makeChildOf($b);
-
- $a->reload(); $b->reload(); $c->reload();
-
- $this->assertEquals(1, $a->children()->count());
- $this->assertEquals(1, $b->children()->count());
- $this->assertEquals(2, $a->descendants()->count());
- }
-
- public function testGetImmediateDescendants() {
- $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
-
- $this->assertEquals($expected, $this->categories('Root 1')->getImmediateDescendants()->all());
-
- $this->assertEquals(array($this->categories('Child 2.1')), $this->categories('Child 2')->getImmediateDescendants()->all());
-
- $this->assertEmpty($this->categories('Root 2')->getImmediateDescendants()->all());
- }
-
- public function testIsSelfOrAncestorOf() {
- $this->assertTrue($this->categories('Root 1')->isSelfOrAncestorOf($this->categories('Child 1')));
- $this->assertTrue($this->categories('Root 1')->isSelfOrAncestorOf($this->categories('Child 2.1')));
- $this->assertTrue($this->categories('Child 2')->isSelfOrAncestorOf($this->categories('Child 2.1')));
- $this->assertFalse($this->categories('Child 2.1')->isSelfOrAncestorOf($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 1')->isSelfOrAncestorOf($this->categories('Child 2')));
- $this->assertTrue($this->categories('Child 1')->isSelfOrAncestorOf($this->categories('Child 1')));
- }
-
- public function testIsAncestorOf() {
- $this->assertTrue($this->categories('Root 1')->isAncestorOf($this->categories('Child 1')));
- $this->assertTrue($this->categories('Root 1')->isAncestorOf($this->categories('Child 2.1')));
- $this->assertTrue($this->categories('Child 2')->isAncestorOf($this->categories('Child 2.1')));
- $this->assertFalse($this->categories('Child 2.1')->isAncestorOf($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 1')->isAncestorOf($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 1')->isAncestorOf($this->categories('Child 1')));
- }
-
- public function testIsSelfOrDescendantOf() {
- $this->assertTrue($this->categories('Child 1')->isSelfOrDescendantOf($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2.1')->isSelfOrDescendantOf($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2.1')->isSelfOrDescendantOf($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 2')->isSelfOrDescendantOf($this->categories('Child 2.1')));
- $this->assertFalse($this->categories('Child 2')->isSelfOrDescendantOf($this->categories('Child 1')));
- $this->assertTrue($this->categories('Child 1')->isSelfOrDescendantOf($this->categories('Child 1')));
- }
-
- public function testIsDescendantOf() {
- $this->assertTrue($this->categories('Child 1')->isDescendantOf($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2.1')->isDescendantOf($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2.1')->isDescendantOf($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 2')->isDescendantOf($this->categories('Child 2.1')));
- $this->assertFalse($this->categories('Child 2')->isDescendantOf($this->categories('Child 1')));
- $this->assertFalse($this->categories('Child 1')->isDescendantOf($this->categories('Child 1')));
- }
-
- public function testGetSiblingsAndSelf() {
- $child = $this->categories('Child 2');
-
- $expected = array($this->categories('Child 1'), $child, $this->categories('Child 3'));
- $this->assertEquals($expected, $child->getSiblingsAndSelf()->all());
-
- $expected = array($this->categories('Root 1'), $this->categories('Root 2'));
- $this->assertEquals($expected, $this->categories('Root 1')->getSiblingsAndSelf()->all());
- }
-
- public function testGetSiblings() {
- $child = $this->categories('Child 2');
-
- $expected = array($this->categories('Child 1'), $this->categories('Child 3'));
-
- $this->assertEquals($expected, $child->getSiblings()->all());
- }
-
- public function testGetLeftSibling() {
- $this->assertEquals($this->categories('Child 1'), $this->categories('Child 2')->getLeftSibling());
- $this->assertEquals($this->categories('Child 2'), $this->categories('Child 3')->getLeftSibling());
- }
-
- public function testGetLeftSiblingOfFirstRootIsNull() {
- $this->assertNull($this->categories('Root 1')->getLeftSibling());
- }
-
- public function testGetLeftSiblingWithNoneIsNull() {
- $this->assertNull($this->categories('Child 2.1')->getLeftSibling());
- }
-
- public function testGetLeftSiblingOfLeftmostNodeIsNull() {
- $this->assertNull($this->categories('Child 1')->getLeftSibling());
- }
-
- public function testGetRightSibling() {
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 2')->getRightSibling());
- $this->assertEquals($this->categories('Child 2'), $this->categories('Child 1')->getRightSibling());
- }
-
- public function testGetRightSiblingOfRoots() {
- $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getRightSibling());
- $this->assertNull($this->categories('Root 2')->getRightSibling());
- }
-
- public function testGetRightSiblingWithNoneIsNull() {
- $this->assertNull($this->categories('Child 2.1')->getRightSibling());
- }
-
- public function testGetRightSiblingOfRightmostNodeIsNull() {
- $this->assertNull($this->categories('Child 3')->getRightSibling());
- }
-
- public function testInsideSubtree() {
- $this->assertFalse($this->categories('Child 1')->insideSubtree($this->categories('Root 2')));
- $this->assertFalse($this->categories('Child 2')->insideSubtree($this->categories('Root 2')));
- $this->assertFalse($this->categories('Child 3')->insideSubtree($this->categories('Root 2')));
-
- $this->assertTrue($this->categories('Child 1')->insideSubtree($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2')->insideSubtree($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 2.1')->insideSubtree($this->categories('Root 1')));
- $this->assertTrue($this->categories('Child 3')->insideSubtree($this->categories('Root 1')));
-
- $this->assertTrue($this->categories('Child 2.1')->insideSubtree($this->categories('Child 2')));
- $this->assertFalse($this->categories('Child 2.1')->insideSubtree($this->categories('Root 2')));
- }
-
- public function testGetLevel() {
- $this->assertEquals(0, $this->categories('Root 1')->getLevel());
- $this->assertEquals(1, $this->categories('Child 1')->getLevel());
- $this->assertEquals(2, $this->categories('Child 2.1')->getLevel());
- }
-
- public function testToHierarchyReturnsAnEloquentCollection() {
- $categories = Category::all()->toHierarchy();
-
- $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $categories);
- }
-
- public function testToHierarchyReturnsHierarchicalData() {
- $categories = Category::all()->toHierarchy();
-
- $this->assertEquals(2, $categories->count());
-
- $first = $categories->first();
- $this->assertEquals('Root 1', $first->name);
- $this->assertEquals(3, $first->children->count());
-
- $first_lvl2 = $first->children->first();
- $this->assertEquals('Child 1', $first_lvl2->name);
- $this->assertEquals(0, $first_lvl2->children->count());
- }
-
- public function testToHierarchyNestsCorrectly() {
- // Prune all categories
- Category::query()->delete();
-
- // Build a sample tree structure:
- //
- // - A
- // |- A.1
- // |- A.2
- // - B
- // |- B.1
- // |- B.2
- // |- B.2.1
- // |- B.2.2
- // |- B.2.2.1
- // |- B.2.3
- // |- B.3
- // - C
- // |- C.1
- // |- C.2
- // - D
- //
- $a = Category::create(array('name' => 'A'));
- $b = Category::create(array('name' => 'B'));
- $c = Category::create(array('name' => 'C'));
- $d = Category::create(array('name' => 'D'));
-
- $ch = Category::create(array('name' => 'A.1'));
- $ch->makeChildOf($a);
-
- $ch = Category::create(array('name' => 'A.2'));
- $ch->makeChildOf($a);
-
- $ch = Category::create(array('name' => 'B.1'));
- $ch->makeChildOf($b);
-
- $ch = Category::create(array('name' => 'B.2'));
- $ch->makeChildOf($b);
-
- $ch2 = Category::create(array('name' => 'B.2.1'));
- $ch2->makeChildOf($ch);
-
- $ch2 = Category::create(array('name' => 'B.2.2'));
- $ch2->makeChildOf($ch);
-
- $ch3 = Category::create(array('name' => 'B.2.2.1'));
- $ch3->makeChildOf($ch2);
-
- $ch2 = Category::create(array('name' => 'B.2.3'));
- $ch2->makeChildOf($ch);
-
- $ch = Category::create(array('name' => 'B.3'));
- $ch->makeChildOf($b);
-
- $ch = Category::create(array('name' => 'C.1'));
- $ch->makeChildOf($c);
-
- $ch = Category::create(array('name' => 'C.2'));
- $ch->makeChildOf($c);
-
- $this->assertTrue(Category::isValidNestedSet());
-
- // Build expectations (expected trees/subtrees)
- $expectedWholeTree = array(
- 'A' => array ( 'A.1' => null, 'A.2' => null ),
- 'B' => array (
- 'B.1' => null,
- 'B.2' =>
- array (
- 'B.2.1' => null,
- 'B.2.2' => array ( 'B.2.2.1' => null ),
- 'B.2.3' => null,
- ),
- 'B.3' => null,
- ),
- 'C' => array ( 'C.1' => null, 'C.2' => null ),
- 'D' => null
- );
-
- $expectedSubtreeA = array('A' => array ( 'A.1' => null, 'A.2' => null ));
-
- $expectedSubtreeB = array(
- 'B' => array (
- 'B.1' => null,
- 'B.2' =>
- array (
- 'B.2.1' => null,
- 'B.2.2' => array ( 'B.2.2.1' => null ),
- 'B.2.3' => null
- ),
- 'B.3' => null
- )
- );
-
- $expectedSubtreeC = array( 'C.1' => null, 'C.2' => null );
-
- $expectedSubtreeD = array('D' => null);
-
- // Perform assertions
- $wholeTree = hmap(Category::all()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedWholeTree, $wholeTree);
-
- $subtreeA = hmap($this->categories('A')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeA, $subtreeA);
-
- $subtreeB = hmap($this->categories('B')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeB, $subtreeB);
-
- $subtreeC = hmap($this->categories('C')->getDescendants()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeC, $subtreeC);
-
- $subtreeD = hmap($this->categories('D')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeD, $subtreeD);
-
- $this->assertTrue($this->categories('D')->getDescendants()->toHierarchy()->isEmpty());
- }
-
- public function testToHierarchyNestsCorrectlyNotSequential() {
- $parent = $this->categories('Child 1');
-
- $parent->children()->create(array('name' => 'Child 1.1'));
-
- $parent->children()->create(array('name' => 'Child 1.2'));
-
- $this->assertTrue(Category::isValidNestedSet());
-
- $expected = array(
- 'Child 1' => array(
- 'Child 1.1' => null,
- 'Child 1.2' => null
- )
- );
-
- $parent->reload();
- $this->assertArraysAreEqual($expected, hmap($parent->getDescendantsAndSelf()->toHierarchy()->toArray()));
- }
-
- public function testToHierarchyNestsCorrectlyWithOrder() {
- with(new OrderedCategorySeeder)->run();
-
- $expectedWhole = array(
- 'Root A' => null,
- 'Root Z' => array(
- 'Child A' => null,
- 'Child C' => null,
- 'Child G' => array( 'Child G.1' => null )
- )
- );
-
- $this->assertArraysAreEqual($expectedWhole, hmap(OrderedCategory::all()->toHierarchy()->toArray()));
-
- $expectedSubtreeZ = array(
- 'Root Z' => array(
- 'Child A' => null,
- 'Child C' => null,
- 'Child G' => array( 'Child G.1' => null )
- )
- );
- $this->assertArraysAreEqual($expectedSubtreeZ, hmap($this->categories('Root Z', 'OrderedCategory')->getDescendantsAndSelf()->toHierarchy()->toArray()));
- }
-
- public function testGetNestedList() {
- $seperator = ' ';
- $nestedList = Category::getNestedList('name', 'id', $seperator);
-
- $expected = array(
- 1 => str_repeat($seperator, 0). 'Root 1',
- 2 => str_repeat($seperator, 1). 'Child 1',
- 3 => str_repeat($seperator, 1). 'Child 2',
- 4 => str_repeat($seperator, 2). 'Child 2.1',
- 5 => str_repeat($seperator, 1). 'Child 3',
- 6 => str_repeat($seperator, 0). 'Root 2',
- );
-
- $this->assertArraysAreEqual($expected, $nestedList);
- }
+ public function testGetDescendantsAndSelfWithLimit()
+ {
+ with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 3);
+
+ $parent = $this->categories('Root 1');
+
+ $this->assertEquals(array($parent), $parent->getDescendantsAndSelf(0)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 3')
+ ), $parent->getDescendantsAndSelf(1)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendantsAndSelf(2)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendantsAndSelf(3)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 2.1.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendantsAndSelf(4)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 2.1.1.1'),
+ $this->categories('Child 2.1.1.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendantsAndSelf(10)->all());
+ }
+
+ public function testGetDescendants()
+ {
+ $parent = $this->categories('Root 1');
+
+ $expected = array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 3')
+ );
+
+ $this->assertCount(count($expected), $parent->getDescendants());
+
+ $this->assertEquals($expected, $parent->getDescendants()->all());
+ }
+
+ public function testGetDescendantsWithLimit()
+ {
+ with(new CategorySeeder)->nestUptoAt($this->categories('Child 2.1'), 3);
+
+ $parent = $this->categories('Root 1');
+
+ $this->assertEmpty($parent->getDescendants(0)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(1)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(2)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(3)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 2.1.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(4)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 2.1.1.1'),
+ $this->categories('Child 2.1.1.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(5)->all());
+
+ $this->assertEquals(array(
+ $this->categories('Child 1'),
+ $this->categories('Child 2'),
+ $this->categories('Child 2.1'),
+ $this->categories('Child 2.1.1'),
+ $this->categories('Child 2.1.1.1'),
+ $this->categories('Child 2.1.1.1.1'),
+ $this->categories('Child 3')
+ ), $parent->getDescendants(10)->all());
+ }
+
+ public function testDescendantsRecursesChildren()
+ {
+ $a = Category::create(array('name' => 'A'));
+ $b = Category::create(array('name' => 'B'));
+ $c = Category::create(array('name' => 'C'));
+
+ // a > b > c
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+
+ $this->assertEquals(1, $a->children()->count());
+ $this->assertEquals(1, $b->children()->count());
+ $this->assertEquals(2, $a->descendants()->count());
+ }
+
+ public function testGetImmediateDescendants()
+ {
+ $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
+
+ $this->assertEquals($expected, $this->categories('Root 1')->getImmediateDescendants()->all());
+
+ $this->assertEquals(array($this->categories('Child 2.1')), $this->categories('Child 2')->getImmediateDescendants()->all());
+
+ $this->assertEmpty($this->categories('Root 2')->getImmediateDescendants()->all());
+ }
+
+ public function testIsSelfOrAncestorOf()
+ {
+ $this->assertTrue($this->categories('Root 1')->isSelfOrAncestorOf($this->categories('Child 1')));
+ $this->assertTrue($this->categories('Root 1')->isSelfOrAncestorOf($this->categories('Child 2.1')));
+ $this->assertTrue($this->categories('Child 2')->isSelfOrAncestorOf($this->categories('Child 2.1')));
+ $this->assertFalse($this->categories('Child 2.1')->isSelfOrAncestorOf($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 1')->isSelfOrAncestorOf($this->categories('Child 2')));
+ $this->assertTrue($this->categories('Child 1')->isSelfOrAncestorOf($this->categories('Child 1')));
+ }
+
+ public function testIsAncestorOf()
+ {
+ $this->assertTrue($this->categories('Root 1')->isAncestorOf($this->categories('Child 1')));
+ $this->assertTrue($this->categories('Root 1')->isAncestorOf($this->categories('Child 2.1')));
+ $this->assertTrue($this->categories('Child 2')->isAncestorOf($this->categories('Child 2.1')));
+ $this->assertFalse($this->categories('Child 2.1')->isAncestorOf($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 1')->isAncestorOf($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 1')->isAncestorOf($this->categories('Child 1')));
+ }
+
+ public function testIsSelfOrDescendantOf()
+ {
+ $this->assertTrue($this->categories('Child 1')->isSelfOrDescendantOf($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2.1')->isSelfOrDescendantOf($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2.1')->isSelfOrDescendantOf($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 2')->isSelfOrDescendantOf($this->categories('Child 2.1')));
+ $this->assertFalse($this->categories('Child 2')->isSelfOrDescendantOf($this->categories('Child 1')));
+ $this->assertTrue($this->categories('Child 1')->isSelfOrDescendantOf($this->categories('Child 1')));
+ }
+
+ public function testIsDescendantOf()
+ {
+ $this->assertTrue($this->categories('Child 1')->isDescendantOf($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2.1')->isDescendantOf($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2.1')->isDescendantOf($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 2')->isDescendantOf($this->categories('Child 2.1')));
+ $this->assertFalse($this->categories('Child 2')->isDescendantOf($this->categories('Child 1')));
+ $this->assertFalse($this->categories('Child 1')->isDescendantOf($this->categories('Child 1')));
+ }
+
+ public function testGetSiblingsAndSelf()
+ {
+ $child = $this->categories('Child 2');
+
+ $expected = array($this->categories('Child 1'), $child, $this->categories('Child 3'));
+ $this->assertEquals($expected, $child->getSiblingsAndSelf()->all());
+
+ $expected = array($this->categories('Root 1'), $this->categories('Root 2'));
+ $this->assertEquals($expected, $this->categories('Root 1')->getSiblingsAndSelf()->all());
+ }
+
+ public function testGetSiblings()
+ {
+ $child = $this->categories('Child 2');
+
+ $expected = array($this->categories('Child 1'), $this->categories('Child 3'));
+
+ $this->assertEquals($expected, $child->getSiblings()->all());
+ }
+
+ public function testGetLeftSibling()
+ {
+ $this->assertEquals($this->categories('Child 1'), $this->categories('Child 2')->getLeftSibling());
+ $this->assertEquals($this->categories('Child 2'), $this->categories('Child 3')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingOfFirstRootIsNull()
+ {
+ $this->assertNull($this->categories('Root 1')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingWithNoneIsNull()
+ {
+ $this->assertNull($this->categories('Child 2.1')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingOfLeftmostNodeIsNull()
+ {
+ $this->assertNull($this->categories('Child 1')->getLeftSibling());
+ }
+
+ public function testGetRightSibling()
+ {
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 2')->getRightSibling());
+ $this->assertEquals($this->categories('Child 2'), $this->categories('Child 1')->getRightSibling());
+ }
+
+ public function testGetRightSiblingOfRoots()
+ {
+ $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getRightSibling());
+ $this->assertNull($this->categories('Root 2')->getRightSibling());
+ }
+
+ public function testGetRightSiblingWithNoneIsNull()
+ {
+ $this->assertNull($this->categories('Child 2.1')->getRightSibling());
+ }
+
+ public function testGetRightSiblingOfRightmostNodeIsNull()
+ {
+ $this->assertNull($this->categories('Child 3')->getRightSibling());
+ }
+
+ public function testInsideSubtree()
+ {
+ $this->assertFalse($this->categories('Child 1')->insideSubtree($this->categories('Root 2')));
+ $this->assertFalse($this->categories('Child 2')->insideSubtree($this->categories('Root 2')));
+ $this->assertFalse($this->categories('Child 3')->insideSubtree($this->categories('Root 2')));
+
+ $this->assertTrue($this->categories('Child 1')->insideSubtree($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2')->insideSubtree($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 2.1')->insideSubtree($this->categories('Root 1')));
+ $this->assertTrue($this->categories('Child 3')->insideSubtree($this->categories('Root 1')));
+
+ $this->assertTrue($this->categories('Child 2.1')->insideSubtree($this->categories('Child 2')));
+ $this->assertFalse($this->categories('Child 2.1')->insideSubtree($this->categories('Root 2')));
+ }
+
+ public function testGetLevel()
+ {
+ $this->assertEquals(0, $this->categories('Root 1')->getLevel());
+ $this->assertEquals(1, $this->categories('Child 1')->getLevel());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getLevel());
+ }
+
+ public function testToHierarchyReturnsAnEloquentCollection()
+ {
+ $categories = Category::all()->toHierarchy();
+
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $categories);
+ }
+
+ public function testToHierarchyReturnsHierarchicalData()
+ {
+ $categories = Category::all()->toHierarchy();
+
+ $this->assertEquals(2, $categories->count());
+
+ $first = $categories->first();
+ $this->assertEquals('Root 1', $first->name);
+ $this->assertEquals(3, $first->children->count());
+
+ $first_lvl2 = $first->children->first();
+ $this->assertEquals('Child 1', $first_lvl2->name);
+ $this->assertEquals(0, $first_lvl2->children->count());
+ }
+
+ public function testToHierarchyNestsCorrectly()
+ {
+ // Prune all categories
+ Category::query()->delete();
+
+ // Build a sample tree structure:
+ //
+ // - A
+ // |- A.1
+ // |- A.2
+ // - B
+ // |- B.1
+ // |- B.2
+ // |- B.2.1
+ // |- B.2.2
+ // |- B.2.2.1
+ // |- B.2.3
+ // |- B.3
+ // - C
+ // |- C.1
+ // |- C.2
+ // - D
+ //
+ $a = Category::create(array('name' => 'A'));
+ $b = Category::create(array('name' => 'B'));
+ $c = Category::create(array('name' => 'C'));
+ $d = Category::create(array('name' => 'D'));
+
+ $ch = Category::create(array('name' => 'A.1'));
+ $ch->makeChildOf($a);
+
+ $ch = Category::create(array('name' => 'A.2'));
+ $ch->makeChildOf($a);
+
+ $ch = Category::create(array('name' => 'B.1'));
+ $ch->makeChildOf($b);
+
+ $ch = Category::create(array('name' => 'B.2'));
+ $ch->makeChildOf($b);
+
+ $ch2 = Category::create(array('name' => 'B.2.1'));
+ $ch2->makeChildOf($ch);
+
+ $ch2 = Category::create(array('name' => 'B.2.2'));
+ $ch2->makeChildOf($ch);
+
+ $ch3 = Category::create(array('name' => 'B.2.2.1'));
+ $ch3->makeChildOf($ch2);
+
+ $ch2 = Category::create(array('name' => 'B.2.3'));
+ $ch2->makeChildOf($ch);
+
+ $ch = Category::create(array('name' => 'B.3'));
+ $ch->makeChildOf($b);
+
+ $ch = Category::create(array('name' => 'C.1'));
+ $ch->makeChildOf($c);
+
+ $ch = Category::create(array('name' => 'C.2'));
+ $ch->makeChildOf($c);
+
+ $this->assertTrue(Category::isValidNestedSet());
+
+ // Build expectations (expected trees/subtrees)
+ $expectedWholeTree = array(
+ 'A' => array('A.1' => null, 'A.2' => null),
+ 'B' => array(
+ 'B.1' => null,
+ 'B.2' =>
+ array(
+ 'B.2.1' => null,
+ 'B.2.2' => array('B.2.2.1' => null),
+ 'B.2.3' => null,
+ ),
+ 'B.3' => null,
+ ),
+ 'C' => array('C.1' => null, 'C.2' => null),
+ 'D' => null
+ );
+
+ $expectedSubtreeA = array('A' => array('A.1' => null, 'A.2' => null));
+
+ $expectedSubtreeB = array(
+ 'B' => array(
+ 'B.1' => null,
+ 'B.2' =>
+ array(
+ 'B.2.1' => null,
+ 'B.2.2' => array('B.2.2.1' => null),
+ 'B.2.3' => null
+ ),
+ 'B.3' => null
+ )
+ );
+
+ $expectedSubtreeC = array('C.1' => null, 'C.2' => null);
+
+ $expectedSubtreeD = array('D' => null);
+
+ // Perform assertions
+ $wholeTree = hmap(Category::all()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedWholeTree, $wholeTree);
+
+ $subtreeA = hmap($this->categories('A')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeA, $subtreeA);
+
+ $subtreeB = hmap($this->categories('B')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeB, $subtreeB);
+
+ $subtreeC = hmap($this->categories('C')->getDescendants()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeC, $subtreeC);
+
+ $subtreeD = hmap($this->categories('D')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeD, $subtreeD);
+
+ $this->assertTrue($this->categories('D')->getDescendants()->toHierarchy()->isEmpty());
+ }
+
+ public function testToHierarchyNestsCorrectlyNotSequential()
+ {
+ $parent = $this->categories('Child 1');
+
+ $parent->children()->create(array('name' => 'Child 1.1'));
+
+ $parent->children()->create(array('name' => 'Child 1.2'));
+
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $expected = array(
+ 'Child 1' => array(
+ 'Child 1.1' => null,
+ 'Child 1.2' => null
+ )
+ );
+
+ $parent->reload();
+ $this->assertArraysAreEqual($expected, hmap($parent->getDescendantsAndSelf()->toHierarchy()->toArray()));
+ }
+
+ public function testToHierarchyNestsCorrectlyWithOrder()
+ {
+ with(new OrderedCategorySeeder)->run();
+
+ $expectedWhole = array(
+ 'Root A' => null,
+ 'Root Z' => array(
+ 'Child A' => null,
+ 'Child C' => null,
+ 'Child G' => array('Child G.1' => null)
+ )
+ );
+
+ $this->assertArraysAreEqual($expectedWhole, hmap(OrderedCategory::all()->toHierarchy()->toArray()));
+
+ $expectedSubtreeZ = array(
+ 'Root Z' => array(
+ 'Child A' => null,
+ 'Child C' => null,
+ 'Child G' => array('Child G.1' => null)
+ )
+ );
+ $this->assertArraysAreEqual($expectedSubtreeZ, hmap($this->categories('Root Z', 'OrderedCategory')->getDescendantsAndSelf()->toHierarchy()->toArray()));
+ }
+
+ public function testGetNestedList()
+ {
+ $seperator = ' ';
+ $nestedList = Category::getNestedList('name', 'id', $seperator);
+
+ $expected = array(
+ 1 => str_repeat($seperator, 0) . 'Root 1',
+ 2 => str_repeat($seperator, 1) . 'Child 1',
+ 3 => str_repeat($seperator, 1) . 'Child 2',
+ 4 => str_repeat($seperator, 2) . 'Child 2.1',
+ 5 => str_repeat($seperator, 1) . 'Child 3',
+ 6 => str_repeat($seperator, 0) . 'Root 2',
+ );
+
+ $this->assertArraysAreEqual($expected, $nestedList);
+ }
}
diff --git a/tests/suite/Category/CategoryMovementTest.php b/tests/suite/Category/CategoryMovementTest.php
index ddb821fd..3883a5ed 100644
--- a/tests/suite/Category/CategoryMovementTest.php
+++ b/tests/suite/Category/CategoryMovementTest.php
@@ -1,528 +1,568 @@
categories('Child 2')->moveLeft();
+ public function testMoveLeft()
+ {
+ $this->categories('Child 2')->moveLeft();
- $this->assertNull($this->categories('Child 2')->getLeftSibling());
+ $this->assertNull($this->categories('Child 2')->getLeftSibling());
- $this->assertEquals($this->categories('Child 1'), $this->categories('Child 2')->getRightSibling());
+ $this->assertEquals($this->categories('Child 1'), $this->categories('Child 2')->getRightSibling());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveLeftRaisesAnExceptionWhenNotPossible() {
- $node = $this->categories('Child 2');
+ public function testMoveLeftRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $node->moveLeft();
- $node->moveLeft();
- }
+ $node = $this->categories('Child 2');
- public function testMoveLeftDoesNotChangeDepth() {
- $this->categories('Child 2')->moveLeft();
+ $node->moveLeft();
+ $node->moveLeft();
+ }
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ public function testMoveLeftDoesNotChangeDepth()
+ {
+ $this->categories('Child 2')->moveLeft();
- public function testMoveLeftWithSubtree() {
- $this->categories('Root 2')->moveLeft();
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertNull($this->categories('Root 2')->getLeftSibling());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Root 2')->getRightSibling());
- $this->assertTrue(Category::isValidNestedSet());
+ public function testMoveLeftWithSubtree()
+ {
+ $this->categories('Root 2')->moveLeft();
- $this->assertEquals(0, $this->categories('Root 1')->getDepth());
- $this->assertEquals(0, $this->categories('Root 2')->getDepth());
+ $this->assertNull($this->categories('Root 2')->getLeftSibling());
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Root 2')->getRightSibling());
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals(1, $this->categories('Child 1')->getDepth());
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(1, $this->categories('Child 3')->getDepth());
+ $this->assertEquals(0, $this->categories('Root 1')->getDepth());
+ $this->assertEquals(0, $this->categories('Root 2')->getDepth());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $this->assertEquals(1, $this->categories('Child 1')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 3')->getDepth());
- public function testMoveToLeftOf() {
- $this->categories('Child 3')->moveToLeftOf($this->categories('Child 1'));
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertNull($this->categories('Child 3')->getLeftSibling());
+ public function testMoveToLeftOf()
+ {
+ $this->categories('Child 3')->moveToLeftOf($this->categories('Child 1'));
- $this->assertEquals($this->categories('Child 1'), $this->categories('Child 3')->getRightSibling());
+ $this->assertNull($this->categories('Child 3')->getLeftSibling());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertEquals($this->categories('Child 1'), $this->categories('Child 3')->getRightSibling());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveToLeftOfRaisesAnExceptionWhenNotPossible() {
- $this->categories('Child 1')->moveToLeftOf($this->categories('Child 1')->getLeftSibling());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMoveToLeftOfDoesNotChangeDepth() {
- $this->categories('Child 2')->moveToLeftOf($this->categories('Child 1'));
+ public function testMoveToLeftOfRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $this->categories('Child 1')->moveToLeftOf($this->categories('Child 1')->getLeftSibling());
+ }
- public function testMoveToLeftOfWithSubtree() {
- $this->categories('Root 2')->moveToLeftOf($this->categories('Root 1'));
+ public function testMoveToLeftOfDoesNotChangeDepth()
+ {
+ $this->categories('Child 2')->moveToLeftOf($this->categories('Child 1'));
- $this->assertNull($this->categories('Root 2')->getLeftSibling());
- $this->assertEquals($this->categories('Root 1'), $this->categories('Root 2')->getRightSibling());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertEquals(0, $this->categories('Root 1')->getDepth());
- $this->assertEquals(0, $this->categories('Root 2')->getDepth());
+ public function testMoveToLeftOfWithSubtree()
+ {
+ $this->categories('Root 2')->moveToLeftOf($this->categories('Root 1'));
- $this->assertEquals(1, $this->categories('Child 1')->getDepth());
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(1, $this->categories('Child 3')->getDepth());
+ $this->assertNull($this->categories('Root 2')->getLeftSibling());
+ $this->assertEquals($this->categories('Root 1'), $this->categories('Root 2')->getRightSibling());
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $this->assertEquals(0, $this->categories('Root 1')->getDepth());
+ $this->assertEquals(0, $this->categories('Root 2')->getDepth());
- public function testMoveRight() {
- $this->categories('Child 2')->moveRight();
+ $this->assertEquals(1, $this->categories('Child 1')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 3')->getDepth());
- $this->assertNull($this->categories('Child 2')->getRightSibling());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 2')->getLeftSibling());
+ public function testMoveRight()
+ {
+ $this->categories('Child 2')->moveRight();
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertNull($this->categories('Child 2')->getRightSibling());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveRightRaisesAnExceptionWhenNotPossible() {
- $node = $this->categories('Child 2');
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 2')->getLeftSibling());
- $node->moveRight();
- $node->moveRight();
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMoveRightDoesNotChangeDepth() {
- $this->categories('Child 2')->moveRight();
+ public function testMoveRightRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $node = $this->categories('Child 2');
- public function testMoveRightWithSubtree() {
- $this->categories('Root 1')->moveRight();
+ $node->moveRight();
+ $node->moveRight();
+ }
- $this->assertNull($this->categories('Root 1')->getRightSibling());
- $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getLeftSibling());
- $this->assertTrue(Category::isValidNestedSet());
+ public function testMoveRightDoesNotChangeDepth()
+ {
+ $this->categories('Child 2')->moveRight();
- $this->assertEquals(0, $this->categories('Root 1')->getDepth());
- $this->assertEquals(0, $this->categories('Root 2')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertEquals(1, $this->categories('Child 1')->getDepth());
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(1, $this->categories('Child 3')->getDepth());
+ public function testMoveRightWithSubtree()
+ {
+ $this->categories('Root 1')->moveRight();
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $this->assertNull($this->categories('Root 1')->getRightSibling());
+ $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getLeftSibling());
+ $this->assertTrue(Category::isValidNestedSet());
- public function testMoveToRightOf() {
- $this->categories('Child 1')->moveToRightOf($this->categories('Child 3'));
+ $this->assertEquals(0, $this->categories('Root 1')->getDepth());
+ $this->assertEquals(0, $this->categories('Root 2')->getDepth());
- $this->assertNull($this->categories('Child 1')->getRightSibling());
+ $this->assertEquals(1, $this->categories('Child 1')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 3')->getDepth());
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->getLeftSibling());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertTrue(Category::isValidNestedSet());
- }
+ public function testMoveToRightOf()
+ {
+ $this->categories('Child 1')->moveToRightOf($this->categories('Child 3'));
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveToRightOfRaisesAnExceptionWhenNotPossible() {
- $this->categories('Child 3')->moveToRightOf($this->categories('Child 3')->getRightSibling());
- }
+ $this->assertNull($this->categories('Child 1')->getRightSibling());
- public function testMoveToRightOfDoesNotChangeDepth() {
- $this->categories('Child 2')->moveToRightOf($this->categories('Child 3'));
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->getLeftSibling());
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMoveToRightOfWithSubtree() {
- $this->categories('Root 1')->moveToRightOf($this->categories('Root 2'));
+ public function testMoveToRightOfRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertNull($this->categories('Root 1')->getRightSibling());
- $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getLeftSibling());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->categories('Child 3')->moveToRightOf($this->categories('Child 3')->getRightSibling());
+ }
- $this->assertEquals(0, $this->categories('Root 1')->getDepth());
- $this->assertEquals(0, $this->categories('Root 2')->getDepth());
+ public function testMoveToRightOfDoesNotChangeDepth()
+ {
+ $this->categories('Child 2')->moveToRightOf($this->categories('Child 3'));
- $this->assertEquals(1, $this->categories('Child 1')->getDepth());
- $this->assertEquals(1, $this->categories('Child 2')->getDepth());
- $this->assertEquals(1, $this->categories('Child 3')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
- }
+ public function testMoveToRightOfWithSubtree()
+ {
+ $this->categories('Root 1')->moveToRightOf($this->categories('Root 2'));
- public function testMakeRoot() {
- $this->categories('Child 2')->makeRoot();
+ $this->assertNull($this->categories('Root 1')->getRightSibling());
+ $this->assertEquals($this->categories('Root 2'), $this->categories('Root 1')->getLeftSibling());
+ $this->assertTrue(Category::isValidNestedSet());
- $newRoot = $this->categories('Child 2');
+ $this->assertEquals(0, $this->categories('Root 1')->getDepth());
+ $this->assertEquals(0, $this->categories('Root 2')->getDepth());
- $this->assertNull($newRoot->parent()->first());
- $this->assertEquals(0, $newRoot->getLevel());
- $this->assertEquals(9, $newRoot->getLeft());
- $this->assertEquals(12, $newRoot->getRight());
+ $this->assertEquals(1, $this->categories('Child 1')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 2')->getDepth());
+ $this->assertEquals(1, $this->categories('Child 3')->getDepth());
- $this->assertEquals(1, $this->categories('Child 2.1')->getLevel());
+ $this->assertEquals(2, $this->categories('Child 2.1')->getDepth());
+ }
- $this->assertTrue(Category::isValidNestedSet());
- }
+ public function testMakeRoot()
+ {
+ $this->categories('Child 2')->makeRoot();
- public function testNullifyParentColumnMakesItRoot() {
- $node = $this->categories('Child 2');
+ $newRoot = $this->categories('Child 2');
- $node->parent_id = null;
+ $this->assertNull($newRoot->parent()->first());
+ $this->assertEquals(0, $newRoot->getLevel());
+ $this->assertEquals(9, $newRoot->getLeft());
+ $this->assertEquals(12, $newRoot->getRight());
- $node->save();
+ $this->assertEquals(1, $this->categories('Child 2.1')->getLevel());
- $this->assertNull($node->parent()->first());
- $this->assertEquals(0, $node->getLevel());
- $this->assertEquals(9, $node->getLeft());
- $this->assertEquals(12, $node->getRight());
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertEquals(1, $this->categories('Child 2.1')->getLevel());
+ public function testNullifyParentColumnMakesItRoot()
+ {
+ $node = $this->categories('Child 2');
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $node->parent_id = null;
- public function testNullifyParentColumnOnNewNodes() {
- $node = new Category(['name' => 'Root 3']);
+ $node->save();
- $node->parent_id = null;
+ $this->assertNull($node->parent()->first());
+ $this->assertEquals(0, $node->getLevel());
+ $this->assertEquals(9, $node->getLeft());
+ $this->assertEquals(12, $node->getRight());
- $node->save();
+ $this->assertEquals(1, $this->categories('Child 2.1')->getLevel());
- $node->reload();
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertNull($node->parent()->first());
- $this->assertEquals(0, $node->getLevel());
- $this->assertEquals(13, $node->getLeft());
- $this->assertEquals(14, $node->getRight());
+ public function testNullifyParentColumnOnNewNodes()
+ {
+ $node = new Category(['name' => 'Root 3']);
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $node->parent_id = null;
- public function testNewCategoryWithNullParent() {
- $node = new Category(['name' => 'Root 3']);
- $this->assertTrue($node->isRoot());
+ $node->save();
- $node->save();
- $this->assertTrue($node->isRoot());
+ $node->reload();
- $node->makeRoot();
- $this->assertTrue($node->isRoot());
- }
+ $this->assertNull($node->parent()->first());
+ $this->assertEquals(0, $node->getLevel());
+ $this->assertEquals(13, $node->getLeft());
+ $this->assertEquals(14, $node->getRight());
- public function testMakeChildOf() {
- $this->categories('Child 1')->makeChildOf($this->categories('Child 3'));
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
+ public function testNewCategoryWithNullParent()
+ {
+ $node = new Category(['name' => 'Root 3']);
+ $this->assertTrue($node->isRoot());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $node->save();
+ $this->assertTrue($node->isRoot());
- public function testMakeChildOfAppendsAtTheEnd() {
- $newChild = Category::create(array('name' => 'Child 4'));
+ $node->makeRoot();
+ $this->assertTrue($node->isRoot());
+ }
- $newChild->makeChildOf($this->categories('Root 1'));
+ public function testMakeChildOf()
+ {
+ $this->categories('Child 1')->makeChildOf($this->categories('Child 3'));
- $lastChild = $this->categories('Root 1')->children()->get()->last();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMakeChildOfMovesWithSubtree() {
- $this->categories('Child 2')->makeChildOf($this->categories('Child 1'));
+ public function testMakeChildOfAppendsAtTheEnd()
+ {
+ $newChild = Category::create(array('name' => 'Child 4'));
- $this->assertTrue(Category::isValidNestedSet());
+ $newChild->makeChildOf($this->categories('Root 1'));
- $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
+ $lastChild = $this->categories('Root 1')->children()->get()->last();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->categories('Child 2')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2')->getRight());
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->categories('Child 1')->getLeft());
- $this->assertEquals(7, $this->categories('Child 1')->getRight());
- }
+ public function testMakeChildOfMovesWithSubtree()
+ {
+ $this->categories('Child 2')->makeChildOf($this->categories('Child 1'));
- public function testMakeChildOfSwappingRoots() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
- $this->categories('Root 2')->makeChildOf($newRoot);
+ $this->assertEquals(3, $this->categories('Child 2')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2')->getRight());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(2, $this->categories('Child 1')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
+ public function testMakeChildOfSwappingRoots()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->categories('Root 2')->getLeft());
- $this->assertEquals(13, $this->categories('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->categories('Root 2')->makeChildOf($newRoot);
- public function testMakeChildOfSwappingRootsWithSubtrees() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Root 1')->makeChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(12, $this->categories('Root 2')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->categories('Root 1')->getLeft());
- $this->assertEquals(13, $this->categories('Root 1')->getRight());
+ public function testMakeChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
- }
+ $this->categories('Root 1')->makeChildOf($newRoot);
- public function testMakeFirstChildOf() {
- $this->categories('Child 1')->makeFirstChildOf($this->categories('Child 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertEquals(4, $this->categories('Root 1')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 1')->getRight());
- public function testMakeFirstChildOfAppendsAtTheBeginning() {
- $newChild = Category::create(array('name' => 'Child 4'));
+ $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
+ }
- $newChild->makeFirstChildOf($this->categories('Root 1'));
+ public function testMakeFirstChildOf()
+ {
+ $this->categories('Child 1')->makeFirstChildOf($this->categories('Child 3'));
- $lastChild = $this->categories('Root 1')->children()->get()->first();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMakeFirstChildOfMovesWithSubtree() {
- $this->categories('Child 2')->makeFirstChildOf($this->categories('Child 1'));
+ public function testMakeFirstChildOfAppendsAtTheBeginning()
+ {
+ $newChild = Category::create(array('name' => 'Child 4'));
- $this->assertTrue(Category::isValidNestedSet());
+ $newChild->makeFirstChildOf($this->categories('Root 1'));
- $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
+ $lastChild = $this->categories('Root 1')->children()->get()->first();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->categories('Child 2')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2')->getRight());
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->categories('Child 1')->getLeft());
- $this->assertEquals(7, $this->categories('Child 1')->getRight());
- }
+ public function testMakeFirstChildOfMovesWithSubtree()
+ {
+ $this->categories('Child 2')->makeFirstChildOf($this->categories('Child 1'));
- public function testMakeFirstChildOfSwappingRoots() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
- $this->categories('Root 2')->makeFirstChildOf($newRoot);
+ $this->assertEquals(3, $this->categories('Child 2')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2')->getRight());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(2, $this->categories('Child 1')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
+ public function testMakeFirstChildOfSwappingRoots()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->categories('Root 2')->getLeft());
- $this->assertEquals(13, $this->categories('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->categories('Root 2')->makeFirstChildOf($newRoot);
- public function testMakeFirstChildOfSwappingRootsWithSubtrees() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Root 1')->makeFirstChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(12, $this->categories('Root 2')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->categories('Root 1')->getLeft());
- $this->assertEquals(13, $this->categories('Root 1')->getRight());
+ public function testMakeFirstChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
- }
+ $this->categories('Root 1')->makeFirstChildOf($newRoot);
- public function testMakeLastChildOf() {
- $this->categories('Child 1')->makeLastChildOf($this->categories('Child 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertEquals(4, $this->categories('Root 1')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 1')->getRight());
- public function testMakeLastChildOfAppendsAtTheEnd() {
- $newChild = Category::create(array('name' => 'Child 4'));
+ $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
+ }
- $newChild->makeLastChildOf($this->categories('Root 1'));
+ public function testMakeLastChildOf()
+ {
+ $this->categories('Child 1')->makeLastChildOf($this->categories('Child 3'));
- $lastChild = $this->categories('Root 1')->children()->get()->last();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->categories('Child 3'), $this->categories('Child 1')->parent()->first());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testMakeLastChildOfMovesWithSubtree() {
- $this->categories('Child 2')->makeLastChildOf($this->categories('Child 1'));
+ public function testMakeLastChildOfAppendsAtTheEnd()
+ {
+ $newChild = Category::create(array('name' => 'Child 4'));
- $this->assertTrue(Category::isValidNestedSet());
+ $newChild->makeLastChildOf($this->categories('Root 1'));
- $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
+ $lastChild = $this->categories('Root 1')->children()->get()->last();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->categories('Child 2')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2')->getRight());
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->categories('Child 1')->getLeft());
- $this->assertEquals(7, $this->categories('Child 1')->getRight());
- }
+ public function testMakeLastChildOfMovesWithSubtree()
+ {
+ $this->categories('Child 2')->makeLastChildOf($this->categories('Child 1'));
- public function testMakeLastChildOfSwappingRoots() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->categories('Child 1')->getKey(), $this->categories('Child 2')->getParentId());
- $this->categories('Root 2')->makeLastChildOf($newRoot);
+ $this->assertEquals(3, $this->categories('Child 2')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2')->getRight());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(2, $this->categories('Child 1')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
+ public function testMakeLastChildOfSwappingRoots()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->categories('Root 2')->getLeft());
- $this->assertEquals(13, $this->categories('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->categories('Root 2')->makeLastChildOf($newRoot);
- public function testMakeLastChildOfSwappingRootsWithSubtrees() {
- $newRoot = Category::create(array('name' => 'Root 3'));
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Root 1')->makeLastChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 2')->getParentId());
- $this->assertTrue(Category::isValidNestedSet());
+ $this->assertEquals(12, $this->categories('Root 2')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->categories('Root 1')->getLeft());
- $this->assertEquals(13, $this->categories('Root 1')->getRight());
+ public function testMakeLastChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Category::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
- }
+ $this->categories('Root 1')->makeLastChildOf($newRoot);
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testUnpersistedNodeCannotBeMoved() {
- $unpersisted = new Category(array('name' => 'Unpersisted'));
+ $this->assertTrue(Category::isValidNestedSet());
- $unpersisted->moveToRightOf($this->categories('Root 1'));
- }
+ $this->assertEquals($newRoot->getKey(), $this->categories('Root 1')->getParentId());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testUnpersistedNodeCannotBeMadeChild() {
- $unpersisted = new Category(array('name' => 'Unpersisted'));
+ $this->assertEquals(4, $this->categories('Root 1')->getLeft());
+ $this->assertEquals(13, $this->categories('Root 1')->getRight());
- $unpersisted->makeChildOf($this->categories('Root 1'));
- }
+ $this->assertEquals(8, $this->categories('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 2.1')->getRight());
+ }
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMovedToItself() {
- $node = $this->categories('Child 1');
+ public function testUnpersistedNodeCannotBeMoved()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $node->moveToRightOf($node);
- }
+ $unpersisted = new Category(array('name' => 'Unpersisted'));
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMadeChildOfThemselves() {
- $node = $this->categories('Child 1');
+ $unpersisted->moveToRightOf($this->categories('Root 1'));
+ }
- $node->makeChildOf($node);
- }
+ public function testUnpersistedNodeCannotBeMadeChild()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMovedToDescendantsOfThemselves() {
- $node = $this->categories('Root 1');
+ $unpersisted = new Category(array('name' => 'Unpersisted'));
- $node->makeChildOf($this->categories('Child 2.1'));
- }
+ $unpersisted->makeChildOf($this->categories('Root 1'));
+ }
- public function testDepthIsUpdatedWhenMadeChild() {
- $a = Category::create(array('name' => 'A'));
- $b = Category::create(array('name' => 'B'));
- $c = Category::create(array('name' => 'C'));
- $d = Category::create(array('name' => 'D'));
+ public function testNodesCannotBeMovedToItself()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- // a > b > c > d
- $b->makeChildOf($a);
- $c->makeChildOf($b);
- $d->makeChildOf($c);
+ $node = $this->categories('Child 1');
- $a->reload();
- $b->reload();
- $c->reload();
- $d->reload();
+ $node->moveToRightOf($node);
+ }
- $this->assertEquals(0, $a->getDepth());
- $this->assertEquals(1, $b->getDepth());
- $this->assertEquals(2, $c->getDepth());
- $this->assertEquals(3, $d->getDepth());
- }
+ public function testNodesCannotBeMadeChildOfThemselves()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- public function testDepthIsUpdatedOnDescendantsWhenParentMoves() {
- $a = Category::create(array('name' => 'A'));
- $b = Category::create(array('name' => 'B'));
- $c = Category::create(array('name' => 'C'));
- $d = Category::create(array('name' => 'D'));
+ $node = $this->categories('Child 1');
- // a > b > c > d
- $b->makeChildOf($a);
- $c->makeChildOf($b);
- $d->makeChildOf($c);
+ $node->makeChildOf($node);
+ }
- $a->reload(); $b->reload(); $c->reload(); $d->reload();
+ public function testNodesCannotBeMovedToDescendantsOfThemselves()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $b->moveToRightOf($a);
+ $node = $this->categories('Root 1');
- $a->reload(); $b->reload(); $c->reload(); $d->reload();
+ $node->makeChildOf($this->categories('Child 2.1'));
+ }
- $this->assertEquals(0, $b->getDepth());
- $this->assertEquals(1, $c->getDepth());
- $this->assertEquals(2, $d->getDepth());
- }
+ public function testDepthIsUpdatedWhenMadeChild()
+ {
+ $a = Category::create(array('name' => 'A'));
+ $b = Category::create(array('name' => 'B'));
+ $c = Category::create(array('name' => 'C'));
+ $d = Category::create(array('name' => 'D'));
+
+ // a > b > c > d
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+ $d->makeChildOf($c);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $this->assertEquals(0, $a->getDepth());
+ $this->assertEquals(1, $b->getDepth());
+ $this->assertEquals(2, $c->getDepth());
+ $this->assertEquals(3, $d->getDepth());
+ }
+
+ public function testDepthIsUpdatedOnDescendantsWhenParentMoves()
+ {
+ $a = Category::create(array('name' => 'A'));
+ $b = Category::create(array('name' => 'B'));
+ $c = Category::create(array('name' => 'C'));
+ $d = Category::create(array('name' => 'D'));
+
+ // a > b > c > d
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+ $d->makeChildOf($c);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $b->moveToRightOf($a);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $this->assertEquals(0, $b->getDepth());
+ $this->assertEquals(1, $c->getDepth());
+ $this->assertEquals(2, $d->getDepth());
+ }
}
diff --git a/tests/suite/Category/CategoryRelationsTest.php b/tests/suite/Category/CategoryRelationsTest.php
index 7f3e008e..85dbf0a8 100644
--- a/tests/suite/Category/CategoryRelationsTest.php
+++ b/tests/suite/Category/CategoryRelationsTest.php
@@ -1,121 +1,135 @@
assertInstanceOf('Illuminate\Database\Eloquent\Relations\BelongsTo', $category->parent());
- }
-
- public function testParentRelationIsSelfReferential() {
- $category = new Category;
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Relations\BelongsTo', $category->parent());
+ }
- $this->assertInstanceOf('Baum\Node', $category->parent()->getRelated());
- }
+ public function testParentRelationIsSelfReferential()
+ {
+ $category = new Category;
- public function testParentRelationRefersToCorrectField() {
- $category = new Category;
+ $this->assertInstanceOf('Baum\Node', $category->parent()->getRelated());
+ }
- if (method_exists($category->parent(), 'getForeignKeyName')) {
- // For Laravel 5.6+
- $this->assertEquals($category->getParentColumnName(), $category->parent()->getForeignKeyName());
- $this->assertEquals($category->getQualifiedParentColumnName(), $category->parent()->getQualifiedForeignKeyName());
- } else {
- $this->assertEquals($category->getParentColumnName(), $category->parent()->getForeignKey());
- $this->assertEquals($category->getQualifiedParentColumnName(), $category->parent()->getQualifiedForeignKey());
+ public function testParentRelationRefersToCorrectField()
+ {
+ $category = new Category;
+
+ if (method_exists($category->parent(), 'getForeignKeyName')) {
+ // For Laravel 5.6+
+ $this->assertEquals($category->getParentColumnName(), $category->parent()->getForeignKeyName());
+ $this->assertEquals($category->getQualifiedParentColumnName(), $category->parent()->getQualifiedForeignKeyName());
+ } else {
+ $this->assertEquals($category->getParentColumnName(), $category->parent()->getForeignKey());
+ $this->assertEquals($category->getQualifiedParentColumnName(), $category->parent()->getQualifiedForeignKey());
+ }
}
- }
- public function testParentRelation() {
- $this->assertEquals($this->categories('Child 2.1')->parent()->first(), $this->categories('Child 2'));
- $this->assertEquals($this->categories('Child 2')->parent()->first(), $this->categories('Root 1'));
- $this->assertNull($this->categories('Root 1')->parent()->first());
- }
+ public function testParentRelation()
+ {
+ $this->assertEquals($this->categories('Child 2.1')->parent()->first(), $this->categories('Child 2'));
+ $this->assertEquals($this->categories('Child 2')->parent()->first(), $this->categories('Root 1'));
+ $this->assertNull($this->categories('Root 1')->parent()->first());
+ }
- public function testChildrenRelationIsAHasMany() {
- $category = new Category;
+ public function testChildrenRelationIsAHasMany()
+ {
+ $category = new Category;
- $this->assertInstanceOf('Illuminate\Database\Eloquent\Relations\HasMany', $category->children());
- }
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Relations\HasMany', $category->children());
+ }
- public function testChildrenRelationIsSelfReferential() {
- $category = new Category;
+ public function testChildrenRelationIsSelfReferential()
+ {
+ $category = new Category;
- $this->assertInstanceOf('Baum\Node', $category->children()->getRelated());
- }
+ $this->assertInstanceOf('Baum\Node', $category->children()->getRelated());
+ }
- public function testChildrenRelationReferesToCorrectField() {
- $category = new Category;
+ public function testChildrenRelationReferesToCorrectField()
+ {
+ $category = new Category;
- $this->assertEquals($category->getParentColumnName(), $category->children()->getForeignKeyName());
+ $this->assertEquals($category->getParentColumnName(), $category->children()->getForeignKeyName());
- $this->assertEquals($category->getQualifiedParentColumnName(), $category->children()->getQualifiedForeignKeyName());
- }
+ $this->assertEquals($category->getQualifiedParentColumnName(), $category->children()->getQualifiedForeignKeyName());
+ }
- public function testChildrenRelation() {
- $root = $this->categories('Root 1');
+ public function testChildrenRelation()
+ {
+ $root = $this->categories('Root 1');
- foreach($root->children() as $child)
- $this->assertEquals($root->getKey(), $child->getParentId());
+ foreach ($root->children() as $child)
+ $this->assertEquals($root->getKey(), $child->getParentId());
- $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
+ $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
- $this->assertEquals($expected, $root->children()->get()->all());
+ $this->assertEquals($expected, $root->children()->get()->all());
- $this->assertEmpty($this->categories('Child 3')->children()->get()->all());
- }
+ $this->assertEmpty($this->categories('Child 3')->children()->get()->all());
+ }
- public function testChildrenRelationUsesDefaultOrdering() {
- $category = new Category;
+ public function testChildrenRelationUsesDefaultOrdering()
+ {
+ $category = new Category;
- $query = $category->children()->getQuery()->getQuery();
+ $query = $category->children()->getQuery()->getQuery();
- $expected = array('column' => 'lft', 'direction' => 'asc');
- $this->assertEquals($expected, $query->orders[0]);
- }
+ $expected = array('column' => 'lft', 'direction' => 'asc');
+ $this->assertEquals($expected, $query->orders[0]);
+ }
- public function testChildrenRelationUsesCustomOrdering() {
- $category = new OrderedCategory;
+ public function testChildrenRelationUsesCustomOrdering()
+ {
+ $category = new OrderedCategory;
- $query = $category->children()->getQuery()->getQuery();
+ $query = $category->children()->getQuery()->getQuery();
- $expected = array('column' => 'name', 'direction' => 'asc');
- $this->assertEquals($expected, $query->orders[0]);
- }
+ $expected = array('column' => 'name', 'direction' => 'asc');
+ $this->assertEquals($expected, $query->orders[0]);
+ }
- public function testChildrenRelationObeysDefaultOrdering() {
- $children = $this->categories('Root 1')->children()->get()->all();
+ public function testChildrenRelationObeysDefaultOrdering()
+ {
+ $children = $this->categories('Root 1')->children()->get()->all();
- $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
- $this->assertEquals($expected, $children);
+ $expected = array($this->categories('Child 1'), $this->categories('Child 2'), $this->categories('Child 3'));
+ $this->assertEquals($expected, $children);
- // Swap 2 nodes & re-test
- Category::query()->where('id', '=', 2)->update(array('lft' => 8, 'rgt' => 9));
- Category::query()->where('id', '=', 5)->update(array('lft' => 2, 'rgt' => 3));
+ // Swap 2 nodes & re-test
+ Category::query()->where('id', '=', 2)->update(array('lft' => 8, 'rgt' => 9));
+ Category::query()->where('id', '=', 5)->update(array('lft' => 2, 'rgt' => 3));
- $children = $this->categories('Root 1')->children()->get()->all();
+ $children = $this->categories('Root 1')->children()->get()->all();
- $expected = array($this->categories('Child 3'), $this->categories('Child 2'), $this->categories('Child 1'));
- $this->assertEquals($expected, $children);
- }
+ $expected = array($this->categories('Child 3'), $this->categories('Child 2'), $this->categories('Child 1'));
+ $this->assertEquals($expected, $children);
+ }
- public function testChildrenRelationObeysCustomOrdering() {
- with(new OrderedCategorySeeder)->run();
+ public function testChildrenRelationObeysCustomOrdering()
+ {
+ with(new OrderedCategorySeeder)->run();
- $children = OrderedCategory::find(1)->children()->get()->all();
+ $children = OrderedCategory::find(1)->children()->get()->all();
- $expected = array(OrderedCategory::find(5), OrderedCategory::find(2), OrderedCategory::find(3));
- $this->assertEquals($expected, $children);
- }
+ $expected = array(OrderedCategory::find(5), OrderedCategory::find(2), OrderedCategory::find(3));
+ $this->assertEquals($expected, $children);
+ }
- public function testChildrenRelationAllowsNodeCreation() {
- $child = new Category(array('name' => 'Child 3.1'));
+ public function testChildrenRelationAllowsNodeCreation()
+ {
+ $child = new Category(array('name' => 'Child 3.1'));
- $this->categories('Child 3')->children()->save($child);
+ $this->categories('Child 3')->children()->save($child);
- $this->assertTrue($child->exists);
- $this->assertEquals($this->categories('Child 3')->getKey(), $child->getParentId());
- }
+ $this->assertTrue($child->exists);
+ $this->assertEquals($this->categories('Child 3')->getKey(), $child->getParentId());
+ }
}
diff --git a/tests/suite/Category/CategoryScopedTest.php b/tests/suite/Category/CategoryScopedTest.php
index e723e8f3..2570cd77 100644
--- a/tests/suite/Category/CategoryScopedTest.php
+++ b/tests/suite/Category/CategoryScopedTest.php
@@ -1,320 +1,300 @@
run();
- }
+ public function setUp(): void
+ {
+ with(new MultiScopedCategorySeeder)->run();
+ }
- public function testInSameScope() {
- $root1 = $this->categories('Root 1', 'ScopedCategory');
- $child1 = $this->categories('Child 1', 'ScopedCategory');
- $child2 = $this->categories('Child 2', 'ScopedCategory');
+ public function testInSameScope()
+ {
+ $root1 = $this->categories('Root 1', 'ScopedCategory');
+ $child1 = $this->categories('Child 1', 'ScopedCategory');
+ $child2 = $this->categories('Child 2', 'ScopedCategory');
- $root2 = $this->categories('Root 2', 'ScopedCategory');
- $child4 = $this->categories('Child 4', 'ScopedCategory');
- $child5 = $this->categories('Child 5', 'ScopedCategory');
+ $root2 = $this->categories('Root 2', 'ScopedCategory');
+ $child4 = $this->categories('Child 4', 'ScopedCategory');
+ $child5 = $this->categories('Child 5', 'ScopedCategory');
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
- $this->assertTrue($root1->inSameScope($child1));
- $this->assertTrue($child1->inSameScope($child2));
- $this->assertTrue($child2->inSameScope($root1));
+ $this->assertTrue($root1->inSameScope($child1));
+ $this->assertTrue($child1->inSameScope($child2));
+ $this->assertTrue($child2->inSameScope($root1));
- $this->assertTrue($root2->inSameScope($child4));
- $this->assertTrue($child4->inSameScope($child5));
- $this->assertTrue($child5->inSameScope($root2));
+ $this->assertTrue($root2->inSameScope($child4));
+ $this->assertTrue($child4->inSameScope($child5));
+ $this->assertTrue($child5->inSameScope($root2));
- $this->assertFalse($root1->inSameScope($root2));
- $this->assertFalse($root2->inSameScope($root1));
+ $this->assertFalse($root1->inSameScope($root2));
+ $this->assertFalse($root2->inSameScope($root1));
- $this->assertFalse($child1->inSameScope($child4));
- $this->assertFalse($child4->inSameScope($child1));
+ $this->assertFalse($child1->inSameScope($child4));
+ $this->assertFalse($child4->inSameScope($child1));
- $this->assertFalse($child2->inSameScope($child5));
- $this->assertFalse($child5->inSameScope($child2));
- }
+ $this->assertFalse($child2->inSameScope($child5));
+ $this->assertFalse($child5->inSameScope($child2));
+ }
- public function testInSameScopeMultiple() {
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+ public function testInSameScopeMultiple()
+ {
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
- $child1 = $this->categories('Child 1', 'MultiScopedCategory');
- $child2 = $this->categories('Child 2', 'MultiScopedCategory');
+ $child1 = $this->categories('Child 1', 'MultiScopedCategory');
+ $child2 = $this->categories('Child 2', 'MultiScopedCategory');
- $child4 = $this->categories('Child 4', 'MultiScopedCategory');
- $child5 = $this->categories('Child 5', 'MultiScopedCategory');
+ $child4 = $this->categories('Child 4', 'MultiScopedCategory');
+ $child5 = $this->categories('Child 5', 'MultiScopedCategory');
- $enfant1 = $this->categories('Enfant 1', 'MultiScopedCategory');
- $enfant2 = $this->categories('Enfant 2', 'MultiScopedCategory');
+ $enfant1 = $this->categories('Enfant 1', 'MultiScopedCategory');
+ $enfant2 = $this->categories('Enfant 2', 'MultiScopedCategory');
- $hijo1 = $this->categories('Hijo 1', 'MultiScopedCategory');
- $hijo2 = $this->categorieS('Hijo 2', 'MultiScopedCategory');
+ $hijo1 = $this->categories('Hijo 1', 'MultiScopedCategory');
+ $hijo2 = $this->categorieS('Hijo 2', 'MultiScopedCategory');
- $this->assertTrue($child1->inSameScope($child2));
- $this->assertTrue($child4->inSameScope($child5));
- $this->assertTrue($enfant1->inSameScope($enfant2));
- $this->assertTrue($hijo1->inSameScope($hijo2));
+ $this->assertTrue($child1->inSameScope($child2));
+ $this->assertTrue($child4->inSameScope($child5));
+ $this->assertTrue($enfant1->inSameScope($enfant2));
+ $this->assertTrue($hijo1->inSameScope($hijo2));
- $this->assertFalse($child2->inSameScope($child4));
- $this->assertFalse($child5->inSameScope($enfant1));
- $this->assertFalse($enfant2->inSameScope($hijo1));
- $this->assertFalse($hijo2->inSameScope($child1));
- }
+ $this->assertFalse($child2->inSameScope($child4));
+ $this->assertFalse($child5->inSameScope($enfant1));
+ $this->assertFalse($enfant2->inSameScope($hijo1));
+ $this->assertFalse($hijo2->inSameScope($child1));
+ }
- public function testIsSelfOrAncestorOf() {
- $root1 = $this->categories('Root 1', 'ScopedCategory');
- $child21 = $this->categories('Child 2.1', 'ScopedCategory');
+ public function testIsSelfOrAncestorOf()
+ {
+ $root1 = $this->categories('Root 1', 'ScopedCategory');
+ $child21 = $this->categories('Child 2.1', 'ScopedCategory');
- $root2 = $this->categories('Root 2', 'ScopedCategory');
- $child51 = $this->categories('Child 5.1', 'ScopedCategory');
+ $root2 = $this->categories('Root 2', 'ScopedCategory');
+ $child51 = $this->categories('Child 5.1', 'ScopedCategory');
- $this->assertTrue($root1->isSelfOrAncestorOf($child21));
- $this->assertTrue($root2->isSelfOrAncestorOf($child51));
+ $this->assertTrue($root1->isSelfOrAncestorOf($child21));
+ $this->assertTrue($root2->isSelfOrAncestorOf($child51));
- $this->assertFalse($root1->isSelfOrAncestorOf($child51));
- $this->assertFalse($root2->isSelfOrAncestorOf($child21));
- }
+ $this->assertFalse($root1->isSelfOrAncestorOf($child51));
+ $this->assertFalse($root2->isSelfOrAncestorOf($child21));
+ }
- public function testIsSelfOrDescendantOf() {
- $root1 = $this->categories('Root 1', 'ScopedCategory');
- $child21 = $this->categories('Child 2.1', 'ScopedCategory');
+ public function testIsSelfOrDescendantOf()
+ {
+ $root1 = $this->categories('Root 1', 'ScopedCategory');
+ $child21 = $this->categories('Child 2.1', 'ScopedCategory');
- $root2 = $this->categories('Root 2', 'ScopedCategory');
- $child51 = $this->categories('Child 5.1', 'ScopedCategory');
+ $root2 = $this->categories('Root 2', 'ScopedCategory');
+ $child51 = $this->categories('Child 5.1', 'ScopedCategory');
- $this->assertTrue($child21->isSelfOrDescendantOf($root1));
- $this->assertTrue($child51->isSelfOrDescendantOf($root2));
+ $this->assertTrue($child21->isSelfOrDescendantOf($root1));
+ $this->assertTrue($child51->isSelfOrDescendantOf($root2));
- $this->assertFalse($child21->isSelfOrDescendantOf($root2));
- $this->assertFalse($child51->isSelfOrDescendantOf($root1));
- }
+ $this->assertFalse($child21->isSelfOrDescendantOf($root2));
+ $this->assertFalse($child51->isSelfOrDescendantOf($root1));
+ }
- public function testGetSiblingsAndSelf() {
- $root2 = $this->categories('Root 2', 'ScopedCategory');
+ public function testGetSiblingsAndSelf()
+ {
+ $root2 = $this->categories('Root 2', 'ScopedCategory');
- $child1 = $this->categories('Child 1', 'ScopedCategory');
- $child2 = $this->categories('Child 2', 'ScopedCategory');
- $child3 = $this->categories('Child 3', 'ScopedCategory');
+ $child1 = $this->categories('Child 1', 'ScopedCategory');
+ $child2 = $this->categories('Child 2', 'ScopedCategory');
+ $child3 = $this->categories('Child 3', 'ScopedCategory');
- $expected = array($root2);
- $this->assertEquals($expected, $root2->getSiblingsAndSelf()->all());
+ $expected = array($root2);
+ $this->assertEquals($expected, $root2->getSiblingsAndSelf()->all());
- $expected = array($child1, $child2, $child3);
- $this->assertEquals($expected, $child2->getSiblingsAndSelf()->all());
- }
+ $expected = array($child1, $child2, $child3);
+ $this->assertEquals($expected, $child2->getSiblingsAndSelf()->all());
+ }
- public function testGetSiblingsAndSelfMultiple() {
- $root1 = $this->categories('Racine 1', 'MultiScopedCategory');
+ public function testGetSiblingsAndSelfMultiple()
+ {
+ $root1 = $this->categories('Racine 1', 'MultiScopedCategory');
- $child1 = $this->categories('Hijo 1', 'MultiScopedCategory');
- $child2 = $this->categories('Hijo 2', 'MultiScopedCategory');
- $child3 = $this->categories('Hijo 3', 'MultiScopedCategory');
+ $child1 = $this->categories('Hijo 1', 'MultiScopedCategory');
+ $child2 = $this->categories('Hijo 2', 'MultiScopedCategory');
+ $child3 = $this->categories('Hijo 3', 'MultiScopedCategory');
- $expected = array($root1);
- $this->assertEquals($expected, $root1->getSiblingsAndSelf()->all());
+ $expected = array($root1);
+ $this->assertEquals($expected, $root1->getSiblingsAndSelf()->all());
- $expected = array($child1, $child2, $child3);
- $this->assertEquals($expected, $child3->getSiblingsAndSelf()->all());
- }
+ $expected = array($child1, $child2, $child3);
+ $this->assertEquals($expected, $child3->getSiblingsAndSelf()->all());
+ }
- public function testSimpleMovements() {
- with(new ScopedCategorySeeder)->run();
+ public function testSimpleMovements()
+ {
+ with(new ScopedCategorySeeder)->run();
- $this->assertTrue(ScopedCategory::isValidNestedSet());
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
- $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
- $this->assertTrue(ScopedCategory::isValidNestedSet());
+ $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
- $this->categories('Child 6', 'ScopedCategory')->makeChildOf($root3);
- $this->assertTrue(ScopedCategory::isValidNestedSet());
+ $this->categories('Child 6', 'ScopedCategory')->makeChildOf($root3);
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
- $root3->reload();
- $expected = array($this->categories('Child 6', 'ScopedCategory'));
- $this->assertEquals($expected, $root3->children()->get()->all());
- }
+ $root3->reload();
+ $expected = array($this->categories('Child 6', 'ScopedCategory'));
+ $this->assertEquals($expected, $root3->children()->get()->all());
+ }
- public function testSimpleSubtreeMovements() {
- with(new ScopedCategorySeeder)->run();
-
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $this->categories('Child 5', 'ScopedCategory')->makeChildOf($root3);
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $root3->reload();
- $expected = array(
- $this->categories('Child 5', 'ScopedCategory'),
- $this->categories('Child 5.1', 'ScopedCategory')
- );
- $this->assertEquals($expected, $root3->getDescendants()->all());
- }
-
- public function testFullSubtreeMovements() {
- with(new ScopedCategorySeeder)->run();
-
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $this->categories('Root 2', 'ScopedCategory')->makeChildOf($root3);
- $this->assertTrue(ScopedCategory::isValidNestedSet());
-
- $root3->reload();
- $expected = array(
- $this->categories('Root 2' , 'ScopedCategory'),
- $this->categories('Child 4' , 'ScopedCategory'),
- $this->categories('Child 5' , 'ScopedCategory'),
- $this->categories('Child 5.1' , 'ScopedCategory'),
- $this->categories('Child 6' , 'ScopedCategory')
- );
- $this->assertEquals($expected, $root3->getDescendants()->all());
- }
-
- public function testSimpleMovementsMultiple() {
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $this->categories('Hijo 1', 'MultiScopedCategory')->makeChildOf($root2);
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2->reload();
- $expected = array($this->categories('Hijo 1', 'MultiScopedCategory'));
- $this->assertEquals($expected, $root2->children()->get()->all());
- }
-
- public function testSimpleSubtreeMovementsMultiple() {
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $this->categories('Hijo 2', 'MultiScopedCategory')->makeChildOf($root2);
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2->reload();
- $expected = array(
- $this->categories('Hijo 2', 'MultiScopedCategory'),
- $this->categories('Hijo 2.1', 'MultiScopedCategory')
- );
- $this->assertEquals($expected, $root2->getDescendants()->all());
- }
-
- public function testFullSubtreeMovementsMultiple() {
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $this->categories('Raiz 1', 'MultiScopedCategory')->makeChildOf($root2);
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
-
- $root2->reload();
- $expected = array(
- $this->categories('Raiz 1', 'MultiScopedCategory'),
- $this->categories('Hijo 1', 'MultiScopedCategory'),
- $this->categories('Hijo 2', 'MultiScopedCategory'),
- $this->categories('Hijo 2.1', 'MultiScopedCategory'),
- $this->categories('Hijo 3', 'MultiScopedCategory')
- );
- $this->assertEquals($expected, $root2->getDescendants()->all());
- }
-
- public function testToHierarchyNestsCorrectlyWithScopedOrder() {
- with(new OrderedScopedCategorySeeder)->run();
-
- $expectedWhole1 = array(
- 'Root 1' => array(
- 'Child 1' => null,
- 'Child 2' => array (
- 'Child 2.1' => null
- ),
- 'Child 3' => null
- )
- );
-
- $expectedWhole2 = array(
- 'Root 2' => array(
- 'Child 4' => null,
- 'Child 5' => array (
- 'Child 5.1' => null
- ),
- 'Child 6' => null
- )
- );
-
- $this->assertArraysAreEqual($expectedWhole1, hmap(OrderedScopedCategory::where('company_id', 1)->get()->toHierarchy()->toArray()));
- $this->assertArraysAreEqual($expectedWhole2, hmap(OrderedScopedCategory::where('company_id', 2)->get()->toHierarchy()->toArray()));
- }
-
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotMoveBetweenScopes() {
- $child4 = $this->categories('Child 4', 'ScopedCategory');
- $root1 = $this->categories('Root 1', 'ScopedCategory');
-
- $child4->makeChildOf($root1);
- }
-
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotMoveBetweenScopesMultiple() {
- $root1 = $this->categories('Root 1', 'MultiScopedCategory');
- $child4 = $this->categories('Child 4', 'MultiScopedCategory');
-
- $child4->makeChildOf($root1);
- }
-
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotMoveBetweenScopesMultiple2() {
- $root1 = $this->categories('Racine 1', 'MultiScopedCategory');
- $child2 = $this->categories('Hijo 2', 'MultiScopedCategory');
-
- $child2->makeChildOf($root1);
- }
-
- // TODO: Moving nodes between scopes is problematic ATM. Fix it or find a work-around.
- public function testMoveNodeBetweenScopes() {
- $this->markTestSkipped();
-
- // $root1 = Menu::create(array('caption' => 'TL1', 'site_id' => 1, 'language' => 'en'));
- // $child11 = Menu::create(array('caption' => 'C11', 'site_id' => 1, 'language' => 'en'));
- // $child12 = Menu::create(array('caption' => 'C12', 'site_id' => 1, 'language' => 'en'));
-
- // $this->assertTrue(Menu::isValidNestedSet());
-
- // $child11->makeChildOf($root1);
- // $child12->makeChildOf($root1);
-
- // $this->assertTrue(Menu::isValidNestedSet());
-
- // $root2 = Menu::create(array('caption' => 'TL2', 'site_id' => 2, 'language' => 'en'));
- // $child21 = Menu::create(array('caption' => 'C21', 'site_id' => 2, 'language' => 'en'));
- // $child22 = Menu::create(array('caption' => 'C22', 'site_id' => 2, 'language' => 'en'));
- // $child21->makeChildOf($root2);
- // $child22->makeChildOf($root2);
-
- // $this->assertTrue(Menu::isValidNestedSet());
-
- // $child11->update(array('site_id' => 2));
- // $child11->makeChildOf($root2);
-
- // $this->assertTrue(Menu::isValidNestedSet());
-
- // $expected = array($this->menus('C12'));
- // $this->assertEquals($expected, $root1->children()->get()->all());
-
- // $expected = array($this->menus('C21'), $this->menus('C22'), $this->menus('C11'));
- // $this->assertEquals($expected, $root2->children()->get()->all());
- }
+ public function testSimpleSubtreeMovements()
+ {
+ with(new ScopedCategorySeeder)->run();
+
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $this->categories('Child 5', 'ScopedCategory')->makeChildOf($root3);
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $root3->reload();
+ $expected = array(
+ $this->categories('Child 5', 'ScopedCategory'),
+ $this->categories('Child 5.1', 'ScopedCategory')
+ );
+ $this->assertEquals($expected, $root3->getDescendants()->all());
+ }
+
+ public function testFullSubtreeMovements()
+ {
+ with(new ScopedCategorySeeder)->run();
+
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $root3 = ScopedCategory::create(array('name' => 'Root 3', 'company_id' => 2));
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $this->categories('Root 2', 'ScopedCategory')->makeChildOf($root3);
+ $this->assertTrue(ScopedCategory::isValidNestedSet());
+
+ $root3->reload();
+ $expected = array(
+ $this->categories('Root 2', 'ScopedCategory'),
+ $this->categories('Child 4', 'ScopedCategory'),
+ $this->categories('Child 5', 'ScopedCategory'),
+ $this->categories('Child 5.1', 'ScopedCategory'),
+ $this->categories('Child 6', 'ScopedCategory')
+ );
+ $this->assertEquals($expected, $root3->getDescendants()->all());
+ }
+
+ public function testSimpleMovementsMultiple()
+ {
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $this->categories('Hijo 1', 'MultiScopedCategory')->makeChildOf($root2);
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2->reload();
+ $expected = array($this->categories('Hijo 1', 'MultiScopedCategory'));
+ $this->assertEquals($expected, $root2->children()->get()->all());
+ }
+
+ public function testSimpleSubtreeMovementsMultiple()
+ {
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $this->categories('Hijo 2', 'MultiScopedCategory')->makeChildOf($root2);
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2->reload();
+ $expected = array(
+ $this->categories('Hijo 2', 'MultiScopedCategory'),
+ $this->categories('Hijo 2.1', 'MultiScopedCategory')
+ );
+ $this->assertEquals($expected, $root2->getDescendants()->all());
+ }
+
+ public function testFullSubtreeMovementsMultiple()
+ {
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2 = MultiScopedCategory::create(array('name' => 'Raiz 2', 'company_id' => 3, 'language' => 'es'));
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $this->categories('Raiz 1', 'MultiScopedCategory')->makeChildOf($root2);
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+
+ $root2->reload();
+ $expected = array(
+ $this->categories('Raiz 1', 'MultiScopedCategory'),
+ $this->categories('Hijo 1', 'MultiScopedCategory'),
+ $this->categories('Hijo 2', 'MultiScopedCategory'),
+ $this->categories('Hijo 2.1', 'MultiScopedCategory'),
+ $this->categories('Hijo 3', 'MultiScopedCategory')
+ );
+ $this->assertEquals($expected, $root2->getDescendants()->all());
+ }
+
+ public function testToHierarchyNestsCorrectlyWithScopedOrder()
+ {
+ with(new OrderedScopedCategorySeeder)->run();
+
+ $expectedWhole1 = array(
+ 'Root 1' => array(
+ 'Child 1' => null,
+ 'Child 2' => array(
+ 'Child 2.1' => null
+ ),
+ 'Child 3' => null
+ )
+ );
+
+ $expectedWhole2 = array(
+ 'Root 2' => array(
+ 'Child 4' => null,
+ 'Child 5' => array(
+ 'Child 5.1' => null
+ ),
+ 'Child 6' => null
+ )
+ );
+
+ $this->assertArraysAreEqual($expectedWhole1, hmap(OrderedScopedCategory::where('company_id', 1)->get()->toHierarchy()->toArray()));
+ $this->assertArraysAreEqual($expectedWhole2, hmap(OrderedScopedCategory::where('company_id', 2)->get()->toHierarchy()->toArray()));
+ }
+
+ public function testNodesCannotMoveBetweenScopes()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
+
+ $child4 = $this->categories('Child 4', 'ScopedCategory');
+ $root1 = $this->categories('Root 1', 'ScopedCategory');
+
+ $child4->makeChildOf($root1);
+ }
+
+ public function testNodesCannotMoveBetweenScopesMultiple()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
+
+ $root1 = $this->categories('Root 1', 'MultiScopedCategory');
+ $child4 = $this->categories('Child 4', 'MultiScopedCategory');
+
+ $child4->makeChildOf($root1);
+ }
+
+ public function testNodesCannotMoveBetweenScopesMultiple2()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
+
+ $root1 = $this->categories('Racine 1', 'MultiScopedCategory');
+ $child2 = $this->categories('Hijo 2', 'MultiScopedCategory');
+
+ $child2->makeChildOf($root1);
+ }
}
diff --git a/tests/suite/Category/CategorySoftDeletesTest.php b/tests/suite/Category/CategorySoftDeletesTest.php
index 62ccbe55..946bb5aa 100644
--- a/tests/suite/Category/CategorySoftDeletesTest.php
+++ b/tests/suite/Category/CategorySoftDeletesTest.php
@@ -1,259 +1,273 @@
categories('Child 3', 'SoftCategory');
+ public function testReload()
+ {
+ $node = $this->categories('Child 3', 'SoftCategory');
- $this->assertTrue($node->exists);
- $this->assertFalse($node->trashed());
+ $this->assertTrue($node->exists);
+ $this->assertFalse($node->trashed());
- $node->delete();
+ $node->delete();
- $this->assertTrue($node->trashed());
+ $this->assertTrue($node->trashed());
- $node->reload();
+ $node->reload();
- $this->assertTrue($node->trashed());
- $this->assertTrue($node->exists);
- }
+ $this->assertTrue($node->trashed());
+ $this->assertTrue($node->exists);
+ }
- public function testDeleteMaintainsTreeValid() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testDeleteMaintainsTreeValid()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child3 = $this->categories('Child 3', 'SoftCategory');
- $child3->delete();
+ $child3 = $this->categories('Child 3', 'SoftCategory');
+ $child3->delete();
- $this->assertTrue($child3->trashed());
- $this->assertTrue(SoftCategory::isValidNestedSet());
- }
+ $this->assertTrue($child3->trashed());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
+ }
- public function testDeleteMaintainsTreeValidWithSubtrees() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testDeleteMaintainsTreeValidWithSubtrees()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child2 = $this->categories('Child 2', 'SoftCategory');
- $child2->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $child2 = $this->categories('Child 2', 'SoftCategory');
+ $child2->delete();
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1', 'SoftCategory'),
- $this->categories('Child 3', 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- }
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ }
- public function testDeleteShiftsIndexes() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testDeleteShiftsIndexes()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Child 1', 'SoftCategory')->delete();
+ $this->categories('Child 1', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 2' , 'SoftCategory'),
- $this->categories('Child 2.1' , 'SoftCategory'),
- $this->categories('Child 3' , 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ $expected = array(
+ $this->categories('Child 2', 'SoftCategory'),
+ $this->categories('Child 2.1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
- $this->assertEquals(8, $this->categories('Root 1', 'SoftCategory')->getRight());
+ $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(8, $this->categories('Root 1', 'SoftCategory')->getRight());
- $this->assertEquals(2, $this->categories('Child 2', 'SoftCategory')->getLeft());
- $this->assertEquals(5, $this->categories('Child 2', 'SoftCategory')->getRight());
+ $this->assertEquals(2, $this->categories('Child 2', 'SoftCategory')->getLeft());
+ $this->assertEquals(5, $this->categories('Child 2', 'SoftCategory')->getRight());
- $this->assertEquals(3, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
- $this->assertEquals(4, $this->categories('Child 2.1', 'SoftCategory')->getRight());
+ $this->assertEquals(3, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
+ $this->assertEquals(4, $this->categories('Child 2.1', 'SoftCategory')->getRight());
- $this->assertEquals(6, $this->categories('Child 3', 'SoftCategory')->getLeft());
- $this->assertEquals(7, $this->categories('Child 3', 'SoftCategory')->getRight());
- }
+ $this->assertEquals(6, $this->categories('Child 3', 'SoftCategory')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 3', 'SoftCategory')->getRight());
+ }
- public function testDeleteShiftsIndexesSubtree() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testDeleteShiftsIndexesSubtree()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Child 2', 'SoftCategory')->delete();
+ $this->categories('Child 2', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1', 'SoftCategory'),
- $this->categories('Child 3', 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
- $this->assertEquals(6, $this->categories('Root 1', 'SoftCategory')->getRight());
+ $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(6, $this->categories('Root 1', 'SoftCategory')->getRight());
- $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
- $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
+ $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
- $this->assertEquals(4, $this->categories('Child 3', 'SoftCategory')->getLeft());
- $this->assertEquals(5, $this->categories('Child 3', 'SoftCategory')->getRight());
- }
+ $this->assertEquals(4, $this->categories('Child 3', 'SoftCategory')->getLeft());
+ $this->assertEquals(5, $this->categories('Child 3', 'SoftCategory')->getRight());
+ }
- public function testDeleteShiftsIndexesFullSubtree() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testDeleteShiftsIndexesFullSubtree()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Root 1', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->categories('Root 1', 'SoftCategory')->delete();
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->assertEmpty($this->categories('Root 2', 'SoftCategory')->getSiblings()->all());
- $this->assertEquals(1, $this->categories('Root 2', 'SoftCategory')->getLeft());
- $this->assertEquals(2, $this->categories('Root 2', 'SoftCategory')->getRight());
- }
+ $this->assertEmpty($this->categories('Root 2', 'SoftCategory')->getSiblings()->all());
+ $this->assertEquals(1, $this->categories('Root 2', 'SoftCategory')->getLeft());
+ $this->assertEquals(2, $this->categories('Root 2', 'SoftCategory')->getRight());
+ }
- public function testRestoreMaintainsTreeValid() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testRestoreMaintainsTreeValid()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child3 = $this->categories('Child 3', 'SoftCategory');
- $child3->delete();
+ $child3 = $this->categories('Child 3', 'SoftCategory');
+ $child3->delete();
- $this->assertTrue($child3->trashed());
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue($child3->trashed());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child3->reload();
- $child3->restore();
+ $child3->reload();
+ $child3->restore();
- $this->assertFalse($child3->trashed());
- $this->assertTrue(SoftCategory::isValidNestedSet());
- }
+ $this->assertFalse($child3->trashed());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
+ }
- public function testRestoreMaintainsTreeValidWithSubtrees() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testRestoreMaintainsTreeValidWithSubtrees()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child2 = $this->categories('Child 2', 'SoftCategory');
- $child2->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $child2 = $this->categories('Child 2', 'SoftCategory');
+ $child2->delete();
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $child2->reload();
- $child2->restore();
+ $child2->reload();
+ $child2->restore();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1' , 'SoftCategory'),
- $this->categories('Child 2' , 'SoftCategory'),
- $this->categories('Child 2.1' , 'SoftCategory'),
- $this->categories('Child 3' , 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- }
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 2', 'SoftCategory'),
+ $this->categories('Child 2.1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ }
- public function testRestoreUnshiftsIndexes() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testRestoreUnshiftsIndexes()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Child 1', 'SoftCategory')->delete();
+ $this->categories('Child 1', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- SoftCategory::withTrashed()->where('name', 'Child 1')->first()->restore();
+ SoftCategory::withTrashed()->where('name', 'Child 1')->first()->restore();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1' , 'SoftCategory'),
- $this->categories('Child 2' , 'SoftCategory'),
- $this->categories('Child 2.1' , 'SoftCategory'),
- $this->categories('Child 3' , 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 2', 'SoftCategory'),
+ $this->categories('Child 2.1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
- $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
+ $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
- $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
- $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
+ $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
- $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
- $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
- $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
+ $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
+ $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
- $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
- $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
- }
+ $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
+ }
- public function testRestoreUnshiftsIndexesSubtree() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testRestoreUnshiftsIndexesSubtree()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Child 2', 'SoftCategory')->delete();
+ $this->categories('Child 2', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- SoftCategory::withTrashed()->where('name', 'Child 2')->first()->restore();
+ SoftCategory::withTrashed()->where('name', 'Child 2')->first()->restore();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1' , 'SoftCategory'),
- $this->categories('Child 2' , 'SoftCategory'),
- $this->categories('Child 2.1' , 'SoftCategory'),
- $this->categories('Child 3' , 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 2', 'SoftCategory'),
+ $this->categories('Child 2.1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
- $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
+ $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
- $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
- $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
+ $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
- $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
- $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
- $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
+ $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
+ $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
- $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
- $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
- }
+ $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
+ }
- public function testRestoreUnshiftsIndexesFullSubtree() {
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ public function testRestoreUnshiftsIndexesFullSubtree()
+ {
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $this->categories('Root 1', 'SoftCategory')->delete();
+ $this->categories('Root 1', 'SoftCategory')->delete();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- SoftCategory::withTrashed()->where('name', 'Root 1')->first()->restore();
+ SoftCategory::withTrashed()->where('name', 'Root 1')->first()->restore();
- $this->assertTrue(SoftCategory::isValidNestedSet());
+ $this->assertTrue(SoftCategory::isValidNestedSet());
- $expected = array(
- $this->categories('Child 1' , 'SoftCategory'),
- $this->categories('Child 2' , 'SoftCategory'),
- $this->categories('Child 2.1' , 'SoftCategory'),
- $this->categories('Child 3' , 'SoftCategory')
- );
- $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
+ $expected = array(
+ $this->categories('Child 1', 'SoftCategory'),
+ $this->categories('Child 2', 'SoftCategory'),
+ $this->categories('Child 2.1', 'SoftCategory'),
+ $this->categories('Child 3', 'SoftCategory')
+ );
+ $this->assertEquals($expected, $this->categories('Root 1', 'SoftCategory')->getDescendants()->all());
- $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
- $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
+ $this->assertEquals(1, $this->categories('Root 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(10, $this->categories('Root 1', 'SoftCategory')->getRight());
- $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
- $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
+ $this->assertEquals(2, $this->categories('Child 1', 'SoftCategory')->getLeft());
+ $this->assertEquals(3, $this->categories('Child 1', 'SoftCategory')->getRight());
- $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
- $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
- $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
- $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
+ $this->assertEquals(4, $this->categories('Child 2', 'SoftCategory')->getLeft());
+ $this->assertEquals(7, $this->categories('Child 2', 'SoftCategory')->getRight());
+ $this->assertEquals(5, $this->categories('Child 2.1', 'SoftCategory')->getLeft());
+ $this->assertEquals(6, $this->categories('Child 2.1', 'SoftCategory')->getRight());
- $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
- $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
- }
+ $this->assertEquals(8, $this->categories('Child 3', 'SoftCategory')->getLeft());
+ $this->assertEquals(9, $this->categories('Child 3', 'SoftCategory')->getRight());
+ }
- public function testAllStatic() {
- $expected = array('Root 1', 'Child 1', 'Child 2', 'Child 2.1', 'Child 3', 'Root 2');
+ public function testAllStatic()
+ {
+ $expected = array('Root 1', 'Child 1', 'Child 2', 'Child 2.1', 'Child 3', 'Root 2');
- $this->assertArraysAreEqual($expected, SoftCategory::all()->pluck('name')->all());
- }
+ $this->assertArraysAreEqual($expected, SoftCategory::all()->pluck('name')->all());
+ }
- public function testAllStaticWithSoftDeletes() {
- $this->categories('Child 1', 'SoftCategory')->delete();
- $this->categories('Child 3', 'SoftCategory')->delete();
+ public function testAllStaticWithSoftDeletes()
+ {
+ $this->categories('Child 1', 'SoftCategory')->delete();
+ $this->categories('Child 3', 'SoftCategory')->delete();
- $expected = array('Root 1', 'Child 2', 'Child 2.1', 'Root 2');
- $this->assertArraysAreEqual($expected, SoftCategory::all()->pluck('name')->all());
- }
+ $expected = array('Root 1', 'Child 2', 'Child 2.1', 'Root 2');
+ $this->assertArraysAreEqual($expected, SoftCategory::all()->pluck('name')->all());
+ }
}
diff --git a/tests/suite/Category/CategoryTreeMapperTest.php b/tests/suite/Category/CategoryTreeMapperTest.php
index 8edd5336..d94bccaf 100644
--- a/tests/suite/Category/CategoryTreeMapperTest.php
+++ b/tests/suite/Category/CategoryTreeMapperTest.php
@@ -2,209 +2,215 @@
use Illuminate\Database\Capsule\Manager as DB;
-class CategoryTreeMapperTest extends BaumTestCase {
-
- public function setUp() {
- with(new CategoryMigrator)->up();
- }
-
- public function testBuildTree() {
- $tree = array(
- array('id' => 1, 'name' => 'A'),
- array('id' => 2, 'name' => 'B'),
- array('id' => 3, 'name' => 'C', 'children' => array(
- array('id' => 4, 'name' => 'C.1', 'children' => array(
- array('id' => 5, 'name' => 'C.1.1'),
- array('id' => 6, 'name' => 'C.1.2')
- )),
- array('id' => 7, 'name' => 'C.2'),
- array('id' => 8, 'name' => 'C.3')
- )),
- array('id' => 9, 'name' => 'D')
- );
- $this->assertTrue(Category::buildTree($tree));
- $this->assertTrue(Category::isValidNestedSet());
-
- $hierarchy = Category::all()->toHierarchy()->toArray();
- $this->assertArraysAreEqual($tree, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
- }
-
- public function testBuildTreePrunesAndInserts() {
- $tree = array(
- array('id' => 1, 'name' => 'A'),
- array('id' => 2, 'name' => 'B'),
- array('id' => 3, 'name' => 'C', 'children' => array(
- array('id' => 4, 'name' => 'C.1', 'children' => array(
- array('id' => 5, 'name' => 'C.1.1'),
- array('id' => 6, 'name' => 'C.1.2')
- )),
- array('id' => 7, 'name' => 'C.2'),
- array('id' => 8, 'name' => 'C.3')
- )),
- array('id' => 9, 'name' => 'D')
- );
- $this->assertTrue(Category::buildTree($tree));
- $this->assertTrue(Category::isValidNestedSet());
-
- // Postgres fix
- if ( DB::connection()->getDriverName() === 'pgsql' ) {
- $tablePrefix = DB::connection()->getTablePrefix();
-
- $sequenceName = $tablePrefix . 'categories_id_seq';
-
- DB::connection()->statement('ALTER SEQUENCE ' . $sequenceName . ' RESTART WITH 10');
+class CategoryTreeMapperTest extends BaumTestCase
+{
+
+ public function setUp(): void
+ {
+ with(new CategoryMigrator)->up();
+ }
+
+ public function testBuildTree()
+ {
+ $tree = array(
+ array('id' => 1, 'name' => 'A'),
+ array('id' => 2, 'name' => 'B'),
+ array('id' => 3, 'name' => 'C', 'children' => array(
+ array('id' => 4, 'name' => 'C.1', 'children' => array(
+ array('id' => 5, 'name' => 'C.1.1'),
+ array('id' => 6, 'name' => 'C.1.2')
+ )),
+ array('id' => 7, 'name' => 'C.2'),
+ array('id' => 8, 'name' => 'C.3')
+ )),
+ array('id' => 9, 'name' => 'D')
+ );
+ $this->assertTrue(Category::buildTree($tree));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $hierarchy = Category::all()->toHierarchy()->toArray();
+ $this->assertArraysAreEqual($tree, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
+ }
+
+ public function testBuildTreePrunesAndInserts()
+ {
+ $tree = array(
+ array('id' => 1, 'name' => 'A'),
+ array('id' => 2, 'name' => 'B'),
+ array('id' => 3, 'name' => 'C', 'children' => array(
+ array('id' => 4, 'name' => 'C.1', 'children' => array(
+ array('id' => 5, 'name' => 'C.1.1'),
+ array('id' => 6, 'name' => 'C.1.2')
+ )),
+ array('id' => 7, 'name' => 'C.2'),
+ array('id' => 8, 'name' => 'C.3')
+ )),
+ array('id' => 9, 'name' => 'D')
+ );
+ $this->assertTrue(Category::buildTree($tree));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ // Postgres fix
+ if (DB::connection()->getDriverName() === 'pgsql') {
+ $tablePrefix = DB::connection()->getTablePrefix();
+
+ $sequenceName = $tablePrefix . 'categories_id_seq';
+
+ DB::connection()->statement('ALTER SEQUENCE ' . $sequenceName . ' RESTART WITH 10');
+ }
+
+ $updated = array(
+ array('id' => 1, 'name' => 'A'),
+ array('id' => 2, 'name' => 'B'),
+ array('id' => 3, 'name' => 'C', 'children' => array(
+ array('id' => 4, 'name' => 'C.1', 'children' => array(
+ array('id' => 5, 'name' => 'C.1.1'),
+ array('id' => 6, 'name' => 'C.1.2')
+ )),
+ array('id' => 7, 'name' => 'C.2', 'children' => array(
+ array('name' => 'C.2.1'),
+ array('name' => 'C.2.2')
+ ))
+ )),
+ array('id' => 9, 'name' => 'D')
+ );
+ $this->assertTrue(Category::buildTree($updated));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $expected = array(
+ array('id' => 1, 'name' => 'A'),
+ array('id' => 2, 'name' => 'B'),
+ array('id' => 3, 'name' => 'C', 'children' => array(
+ array('id' => 4, 'name' => 'C.1', 'children' => array(
+ array('id' => 5, 'name' => 'C.1.1'),
+ array('id' => 6, 'name' => 'C.1.2')
+ )),
+ array('id' => 7, 'name' => 'C.2', 'children' => array(
+ array('id' => 10, 'name' => 'C.2.1'),
+ array('id' => 11, 'name' => 'C.2.2')
+ ))
+ )),
+ array('id' => 9, 'name' => 'D')
+ );
+
+ $hierarchy = Category::all()->toHierarchy()->toArray();
+ $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
+ }
+
+ public function testMakeTree()
+ {
+ with(new CategorySeeder)->run();
+
+ $parent = Category::find(3);
+
+ $subtree = array(
+ array('id' => 4, 'name' => 'Child 2.1'),
+ array('name' => 'Child 2.2'),
+ array('name' => 'Child 2.3', 'children' => array(
+ array('name' => 'Child 2.3.1', 'children' => array(
+ array('name' => 'Child 2.3.1.1'),
+ array('name' => 'Child 2.3.1.1')
+ )),
+ array('name' => 'Child 2.3.2'),
+ array('name' => 'Child 2.3.3')
+ )),
+ array('name' => 'Child 2.4')
+ );
+
+ $this->assertTrue($parent->makeTree($subtree));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $expected = array(
+ array('id' => 4, 'name' => 'Child 2.1'),
+ array('id' => 7, 'name' => 'Child 2.2'),
+ array('id' => 8, 'name' => 'Child 2.3', 'children' => array(
+ array('id' => 9, 'name' => 'Child 2.3.1', 'children' => array(
+ array('id' => 10, 'name' => 'Child 2.3.1.1'),
+ array('id' => 11, 'name' => 'Child 2.3.1.1')
+ )),
+ array('id' => 12, 'name' => 'Child 2.3.2'),
+ array('id' => 13, 'name' => 'Child 2.3.3')
+ )),
+ array('id' => 14, 'name' => 'Child 2.4')
+ );
+
+ $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
+ $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
}
- $updated = array(
- array('id' => 1, 'name' => 'A'),
- array('id' => 2, 'name' => 'B'),
- array('id' => 3, 'name' => 'C', 'children' => array(
- array('id' => 4, 'name' => 'C.1', 'children' => array(
- array('id' => 5, 'name' => 'C.1.1'),
- array('id' => 6, 'name' => 'C.1.2')
- )),
- array('id' => 7, 'name' => 'C.2', 'children' => array(
- array('name' => 'C.2.1'),
- array('name' => 'C.2.2')
- ))
- )),
- array('id' => 9, 'name' => 'D')
- );
- $this->assertTrue(Category::buildTree($updated));
- $this->assertTrue(Category::isValidNestedSet());
-
- $expected = array(
- array('id' => 1, 'name' => 'A'),
- array('id' => 2, 'name' => 'B'),
- array('id' => 3, 'name' => 'C', 'children' => array(
- array('id' => 4, 'name' => 'C.1', 'children' => array(
- array('id' => 5, 'name' => 'C.1.1'),
- array('id' => 6, 'name' => 'C.1.2')
- )),
- array('id' => 7, 'name' => 'C.2', 'children' => array(
- array('id' => 10, 'name' => 'C.2.1'),
- array('id' => 11, 'name' => 'C.2.2')
- ))
- )),
- array('id' => 9, 'name' => 'D')
- );
-
- $hierarchy = Category::all()->toHierarchy()->toArray();
- $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
- }
-
- public function testMakeTree() {
- with(new CategorySeeder)->run();
-
- $parent = Category::find(3);
-
- $subtree = array(
- array('id' => 4, 'name' => 'Child 2.1'),
- array('name' => 'Child 2.2'),
- array('name' => 'Child 2.3', 'children' => array(
- array('name' => 'Child 2.3.1', 'children' => array(
- array('name' => 'Child 2.3.1.1'),
- array('name' => 'Child 2.3.1.1')
- )),
- array('name' => 'Child 2.3.2'),
- array('name' => 'Child 2.3.3')
- )),
- array('name' => 'Child 2.4')
- );
-
- $this->assertTrue($parent->makeTree($subtree));
- $this->assertTrue(Category::isValidNestedSet());
-
- $expected = array(
- array('id' => 4, 'name' => 'Child 2.1'),
- array('id' => 7, 'name' => 'Child 2.2'),
- array('id' => 8, 'name' => 'Child 2.3', 'children' => array(
- array('id' => 9, 'name' => 'Child 2.3.1', 'children' => array(
- array('id' => 10, 'name' => 'Child 2.3.1.1'),
- array('id' => 11, 'name' => 'Child 2.3.1.1')
- )),
- array('id' => 12, 'name' => 'Child 2.3.2'),
- array('id' => 13, 'name' => 'Child 2.3.3')
- )),
- array('id' => 14, 'name' => 'Child 2.4')
- );
-
- $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
- $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
- }
-
- public function testMakeTreePrunesAndInserts() {
- with(new CategorySeeder)->run();
-
- $parent = Category::find(3);
-
- $subtree = array(
- array('id' => 4, 'name' => 'Child 2.1'),
- array('name' => 'Child 2.2'),
- array('name' => 'Child 2.3', 'children' => array(
- array('name' => 'Child 2.3.1', 'children' => array(
- array('name' => 'Child 2.3.1.1'),
- array('name' => 'Child 2.3.1.1')
- )),
- array('name' => 'Child 2.3.2'),
- array('name' => 'Child 2.3.3')
- )),
- array('name' => 'Child 2.4')
- );
-
- $this->assertTrue($parent->makeTree($subtree));
- $this->assertTrue(Category::isValidNestedSet());
-
- $expected = array(
- array('id' => 4, 'name' => 'Child 2.1'),
- array('id' => 7, 'name' => 'Child 2.2'),
- array('id' => 8, 'name' => 'Child 2.3', 'children' => array(
- array('id' => 9, 'name' => 'Child 2.3.1', 'children' => array(
- array('id' => 10, 'name' => 'Child 2.3.1.1'),
- array('id' => 11, 'name' => 'Child 2.3.1.1')
- )),
- array('id' => 12, 'name' => 'Child 2.3.2'),
- array('id' => 13, 'name' => 'Child 2.3.3')
- )),
- array('id' => 14, 'name' => 'Child 2.4')
- );
-
- $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
- $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
-
- $modified = array(
- array('id' => 7, 'name' => 'Child 2.2'),
- array('id' => 8, 'name' => 'Child 2.3'),
- array('id' => 14, 'name' => 'Child 2.4'),
- array('name' => 'Child 2.5', 'children' => array(
- array('name' => 'Child 2.5.1', 'children' => array(
- array('name' => 'Child 2.5.1.1'),
- array('name' => 'Child 2.5.1.1')
- )),
- array('name' => 'Child 2.5.2'),
- array('name' => 'Child 2.5.3')
- ))
- );
-
- $this->assertTrue($parent->makeTree($modified));
- $this->assertTrue(Category::isValidNestedSet());
-
- $expected = array(
- array('id' => 7 , 'name' => 'Child 2.2'),
- array('id' => 8 , 'name' => 'Child 2.3'),
- array('id' => 14, 'name' => 'Child 2.4'),
- array('id' => 15, 'name' => 'Child 2.5', 'children' => array(
- array('id' => 16, 'name' => 'Child 2.5.1', 'children' => array(
- array('id' => 17, 'name' => 'Child 2.5.1.1'),
- array('id' => 18, 'name' => 'Child 2.5.1.1')
- )),
- array('id' => 19, 'name' => 'Child 2.5.2'),
- array('id' => 20, 'name' => 'Child 2.5.3')
- ))
- );
-
- $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
- $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
- }
+ public function testMakeTreePrunesAndInserts()
+ {
+ with(new CategorySeeder)->run();
+
+ $parent = Category::find(3);
+
+ $subtree = array(
+ array('id' => 4, 'name' => 'Child 2.1'),
+ array('name' => 'Child 2.2'),
+ array('name' => 'Child 2.3', 'children' => array(
+ array('name' => 'Child 2.3.1', 'children' => array(
+ array('name' => 'Child 2.3.1.1'),
+ array('name' => 'Child 2.3.1.1')
+ )),
+ array('name' => 'Child 2.3.2'),
+ array('name' => 'Child 2.3.3')
+ )),
+ array('name' => 'Child 2.4')
+ );
+
+ $this->assertTrue($parent->makeTree($subtree));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $expected = array(
+ array('id' => 4, 'name' => 'Child 2.1'),
+ array('id' => 7, 'name' => 'Child 2.2'),
+ array('id' => 8, 'name' => 'Child 2.3', 'children' => array(
+ array('id' => 9, 'name' => 'Child 2.3.1', 'children' => array(
+ array('id' => 10, 'name' => 'Child 2.3.1.1'),
+ array('id' => 11, 'name' => 'Child 2.3.1.1')
+ )),
+ array('id' => 12, 'name' => 'Child 2.3.2'),
+ array('id' => 13, 'name' => 'Child 2.3.3')
+ )),
+ array('id' => 14, 'name' => 'Child 2.4')
+ );
+
+ $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
+ $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
+
+ $modified = array(
+ array('id' => 7, 'name' => 'Child 2.2'),
+ array('id' => 8, 'name' => 'Child 2.3'),
+ array('id' => 14, 'name' => 'Child 2.4'),
+ array('name' => 'Child 2.5', 'children' => array(
+ array('name' => 'Child 2.5.1', 'children' => array(
+ array('name' => 'Child 2.5.1.1'),
+ array('name' => 'Child 2.5.1.1')
+ )),
+ array('name' => 'Child 2.5.2'),
+ array('name' => 'Child 2.5.3')
+ ))
+ );
+
+ $this->assertTrue($parent->makeTree($modified));
+ $this->assertTrue(Category::isValidNestedSet());
+
+ $expected = array(
+ array('id' => 7, 'name' => 'Child 2.2'),
+ array('id' => 8, 'name' => 'Child 2.3'),
+ array('id' => 14, 'name' => 'Child 2.4'),
+ array('id' => 15, 'name' => 'Child 2.5', 'children' => array(
+ array('id' => 16, 'name' => 'Child 2.5.1', 'children' => array(
+ array('id' => 17, 'name' => 'Child 2.5.1.1'),
+ array('id' => 18, 'name' => 'Child 2.5.1.1')
+ )),
+ array('id' => 19, 'name' => 'Child 2.5.2'),
+ array('id' => 20, 'name' => 'Child 2.5.3')
+ ))
+ );
+
+ $hierarchy = $parent->reload()->getDescendants()->toHierarchy()->toArray();
+ $this->assertArraysAreEqual($expected, array_ints_keys(hmap($hierarchy, array('id', 'name'))));
+ }
}
diff --git a/tests/suite/Category/CategoryTreeRebuildingTest.php b/tests/suite/Category/CategoryTreeRebuildingTest.php
index 8e951d58..471c92bd 100644
--- a/tests/suite/Category/CategoryTreeRebuildingTest.php
+++ b/tests/suite/Category/CategoryTreeRebuildingTest.php
@@ -1,96 +1,106 @@
assertTrue(Category::isValidNestedSet());
+ public function testRebuild()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $root = Category::root();
- Category::query()->update(array('lft' => null, 'rgt' => null));
- $this->assertFalse(Category::isValidNestedSet());
+ $root = Category::root();
+ Category::query()->update(array('lft' => null, 'rgt' => null));
+ $this->assertFalse(Category::isValidNestedSet());
- Category::rebuild();
- $this->assertTrue(Category::isValidNestedSet());
+ Category::rebuild();
+ $this->assertTrue(Category::isValidNestedSet());
- $this->assertEquals($root, Category::root());
- }
+ $this->assertEquals($root, Category::root());
+ }
- public function testRebuildPresevesRootNodes() {
- $root1 = Category::create(array('name' => 'Test Root 1'));
- $root2 = Category::create(array('name' => 'Test Root 2'));
- $root3 = Category::create(array('name' => 'Test Root 3'));
+ public function testRebuildPresevesRootNodes()
+ {
+ $root1 = Category::create(array('name' => 'Test Root 1'));
+ $root2 = Category::create(array('name' => 'Test Root 2'));
+ $root3 = Category::create(array('name' => 'Test Root 3'));
- $root2->makeChildOf($root1);
- $root3->makeChildOf($root1);
+ $root2->makeChildOf($root1);
+ $root3->makeChildOf($root1);
- $lastRoot = Category::roots()->reOrderBy($root1->getLeftColumnName(), 'desc')->first();
+ $lastRoot = Category::roots()->reOrderBy($root1->getLeftColumnName(), 'desc')->first();
- Category::query()->update(array('lft' => null, 'rgt' => null));
- Category::rebuild();
+ Category::query()->update(array('lft' => null, 'rgt' => null));
+ Category::rebuild();
- $this->assertEquals($lastRoot, Category::roots()->reOrderBy($root1->getLeftColumnName(), 'desc')->first());
- }
+ $this->assertEquals($lastRoot, Category::roots()->reOrderBy($root1->getLeftColumnName(), 'desc')->first());
+ }
- public function testRebuildRecomputesDepth() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testRebuildRecomputesDepth()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- Category::query()->update(array('lft' => null, 'rgt' => null, 'depth' => 0));
- $this->assertFalse(Category::isValidNestedSet());
+ Category::query()->update(array('lft' => null, 'rgt' => null, 'depth' => 0));
+ $this->assertFalse(Category::isValidNestedSet());
- Category::rebuild();
+ Category::rebuild();
- $expected = array(0, 1, 1, 2, 1, 0);
- $this->assertEquals($expected, Category::all()->map(function($n) { return $n->getDepth(); })->all());
- }
+ $expected = array(0, 1, 1, 2, 1, 0);
+ $this->assertEquals($expected, Category::all()->map(function ($n) {
+ return $n->getDepth();
+ })->all());
+ }
- public function testRebuildWithScope() {
- MultiScopedCategory::query()->delete();
+ public function testRebuildWithScope()
+ {
+ MultiScopedCategory::query()->delete();
- $root = MultiScopedCategory::create(array('name' => 'A' , 'company_id' => 721, 'language' => 'es'));
- $child1 = MultiScopedCategory::create(array('name' => 'A.1' , 'company_id' => 721, 'language' => 'es'));
- $child2 = MultiscopedCategory::create(array('name' => 'A.2' , 'company_id' => 721, 'language' => 'es'));
+ $root = MultiScopedCategory::create(array('name' => 'A', 'company_id' => 721, 'language' => 'es'));
+ $child1 = MultiScopedCategory::create(array('name' => 'A.1', 'company_id' => 721, 'language' => 'es'));
+ $child2 = MultiscopedCategory::create(array('name' => 'A.2', 'company_id' => 721, 'language' => 'es'));
- $child1->makeChildOf($root);
- $child2->makeChildOf($root);
+ $child1->makeChildOf($root);
+ $child2->makeChildOf($root);
- MultiscopedCategory::query()->update(array('lft' => null, 'rgt' => null));
- $this->assertFalse(MultiscopedCategory::isValidNestedSet());
+ MultiscopedCategory::query()->update(array('lft' => null, 'rgt' => null));
+ $this->assertFalse(MultiscopedCategory::isValidNestedSet());
- MultiscopedCategory::rebuild();
- $this->assertTrue(MultiscopedCategory::isValidNestedSet());
+ MultiscopedCategory::rebuild();
+ $this->assertTrue(MultiscopedCategory::isValidNestedSet());
- $this->assertEquals($root->getAttributes(), $this->categories('A', 'MultiScopedCategory')->getAttributes());
+ $this->assertEquals($root->getAttributes(), $this->categories('A', 'MultiScopedCategory')->getAttributes());
- $expected = array($child1->getAttributes(), $child2->getAttributes());
- $actual = array_map(function ($ch) { return $ch->getAttributes(); }, $this->categories('A', 'MultiScopedCategory')->children()->get()->all());
+ $expected = array($child1->getAttributes(), $child2->getAttributes());
+ $actual = array_map(function ($ch) {
+ return $ch->getAttributes();
+ }, $this->categories('A', 'MultiScopedCategory')->children()->get()->all());
- $this->assertEquals($expected, $actual);
- }
+ $this->assertEquals($expected, $actual);
+ }
- public function testRebuildWithMultipleScopes() {
- MultiScopedCategory::query()->delete();
+ public function testRebuildWithMultipleScopes()
+ {
+ MultiScopedCategory::query()->delete();
- $root1 = MultiScopedCategory::create(array('name' => 'TL1', 'company_id' => 1, 'language' => 'en'));
- $child11 = MultiScopedCategory::create(array('name' => 'C11', 'company_id' => 1, 'language' => 'en'));
- $child12 = MultiScopedCategory::create(array('name' => 'C12', 'company_id' => 1, 'language' => 'en'));
- $child11->makeChildOf($root1);
- $child12->makeChildOf($root1);
+ $root1 = MultiScopedCategory::create(array('name' => 'TL1', 'company_id' => 1, 'language' => 'en'));
+ $child11 = MultiScopedCategory::create(array('name' => 'C11', 'company_id' => 1, 'language' => 'en'));
+ $child12 = MultiScopedCategory::create(array('name' => 'C12', 'company_id' => 1, 'language' => 'en'));
+ $child11->makeChildOf($root1);
+ $child12->makeChildOf($root1);
- $root2 = MultiScopedCategory::create(array('name' => 'TL2', 'company_id' => 2, 'language' => 'en'));
- $child21 = MultiScopedCategory::create(array('name' => 'C21', 'company_id' => 2, 'language' => 'en'));
- $child22 = MultiScopedCategory::create(array('name' => 'C22', 'company_id' => 2, 'language' => 'en'));
- $child21->makeChildOf($root2);
- $child22->makeChildOf($root2);
+ $root2 = MultiScopedCategory::create(array('name' => 'TL2', 'company_id' => 2, 'language' => 'en'));
+ $child21 = MultiScopedCategory::create(array('name' => 'C21', 'company_id' => 2, 'language' => 'en'));
+ $child22 = MultiScopedCategory::create(array('name' => 'C22', 'company_id' => 2, 'language' => 'en'));
+ $child21->makeChildOf($root2);
+ $child22->makeChildOf($root2);
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
- $tree = MultiScopedCategory::query()->orderBy($root1->getKeyName())->get()->all();
+ $tree = MultiScopedCategory::query()->orderBy($root1->getKeyName())->get()->all();
- MultiScopedCategory::query()->update(array('lft' => null, 'rgt' => null));
- MultiScopedCategory::rebuild();
+ MultiScopedCategory::query()->update(array('lft' => null, 'rgt' => null));
+ MultiScopedCategory::rebuild();
- $this->assertTrue(MultiScopedCategory::isValidNestedSet());
- $this->assertEquals($tree, MultiScopedCategory::query()->orderBy($root1->getKeyName())->get()->all());
- }
+ $this->assertTrue(MultiScopedCategory::isValidNestedSet());
+ $this->assertEquals($tree, MultiScopedCategory::query()->orderBy($root1->getKeyName())->get()->all());
+ }
}
diff --git a/tests/suite/Category/CategoryTreeValidationTest.php b/tests/suite/Category/CategoryTreeValidationTest.php
index c00992e9..035c312f 100644
--- a/tests/suite/Category/CategoryTreeValidationTest.php
+++ b/tests/suite/Category/CategoryTreeValidationTest.php
@@ -1,84 +1,94 @@
assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWithNullLefts()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- Category::query()->update(array('lft' => null));
- $this->assertFalse(Category::isValidNestedSet());
- }
+ Category::query()->update(array('lft' => null));
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testTreeIsNotValidWithNullRights() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWithNullRights()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- Category::query()->update(array('rgt' => null));
- $this->assertFalse(Category::isValidNestedSet());
- }
+ Category::query()->update(array('rgt' => null));
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testTreeIsNotValidWhenRightsEqualLefts() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWhenRightsEqualLefts()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $child2 = $this->categories('Child 2');
- $child2->rgt = $child2->lft;
- $child2->save();
+ $child2 = $this->categories('Child 2');
+ $child2->rgt = $child2->lft;
+ $child2->save();
- $this->assertFalse(Category::isValidNestedSet());
- }
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testTreeIsNotValidWhenLeftEqualsParent() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWhenLeftEqualsParent()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $child2 = $this->categories('Child 2');
- $child2->lft = $this->categories('Root 1')->getLeft();
- $child2->save();
+ $child2 = $this->categories('Child 2');
+ $child2->lft = $this->categories('Root 1')->getLeft();
+ $child2->save();
- $this->assertFalse(Category::isValidNestedSet());
- }
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testTreeIsNotValidWhenRightEqualsParent() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWhenRightEqualsParent()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $child2 = $this->categories('Child 2');
- $child2->rgt = $this->categories('Root 1')->getRight();
- $child2->save();
+ $child2 = $this->categories('Child 2');
+ $child2->rgt = $this->categories('Root 1')->getRight();
+ $child2->save();
- $this->assertFalse(Category::isValidNestedSet());
- }
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testTreeIsValidWithMissingMiddleNode() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsValidWithMissingMiddleNode()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- Category::query()->delete($this->categories('Child 2')->getKey());
- $this->assertTrue(Category::isValidNestedSet());
- }
+ Category::query()->delete($this->categories('Child 2')->getKey());
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testTreeIsNotValidWithOverlappingRoots() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testTreeIsNotValidWithOverlappingRoots()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- // Force Root 2 to overlap with Root 1
- $root = $this->categories('Root 2');
- $root->lft = 0;
- $root->save();
+ // Force Root 2 to overlap with Root 1
+ $root = $this->categories('Root 2');
+ $root->lft = 0;
+ $root->save();
- $this->assertFalse(Category::isValidNestedSet());
- }
+ $this->assertFalse(Category::isValidNestedSet());
+ }
- public function testNodeDeletionDoesNotMakeTreeInvalid() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testNodeDeletionDoesNotMakeTreeInvalid()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Root 2')->delete();
- $this->assertTrue(Category::isValidNestedSet());
+ $this->categories('Root 2')->delete();
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Child 1')->delete();
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->categories('Child 1')->delete();
+ $this->assertTrue(Category::isValidNestedSet());
+ }
- public function testNodeDeletionWithSubtreeDoesNotMakeTreeInvalid() {
- $this->assertTrue(Category::isValidNestedSet());
+ public function testNodeDeletionWithSubtreeDoesNotMakeTreeInvalid()
+ {
+ $this->assertTrue(Category::isValidNestedSet());
- $this->categories('Child 2')->delete();
- $this->assertTrue(Category::isValidNestedSet());
- }
+ $this->categories('Child 2')->delete();
+ $this->assertTrue(Category::isValidNestedSet());
+ }
}
diff --git a/tests/suite/CategoryTestCase.php b/tests/suite/CategoryTestCase.php
index b7998406..1424190e 100644
--- a/tests/suite/CategoryTestCase.php
+++ b/tests/suite/CategoryTestCase.php
@@ -1,17 +1,21 @@
up();
- }
+ public static function setUpBeforeClass(): void
+ {
+ with(new CategoryMigrator)->up();
+ }
- public function setUp() {
- with(new CategorySeeder)->run();
- }
+ public function setUp(): void
+ {
+ with(new CategorySeeder)->run();
+ }
- protected function categories($name, $className = 'Category') {
- return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
- }
+ protected function categories($name, $className = 'Category')
+ {
+ return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
+ }
}
diff --git a/tests/suite/Cluster/ClusterColumnsTest.php b/tests/suite/Cluster/ClusterColumnsTest.php
index 72279f3e..b1b0d417 100644
--- a/tests/suite/Cluster/ClusterColumnsTest.php
+++ b/tests/suite/Cluster/ClusterColumnsTest.php
@@ -1,19 +1,22 @@
assertTrue(is_string($root->getKey()));
- $this->assertFalse(is_numeric($root->getKey()));
- }
+ $this->assertTrue(is_string($root->getKey()));
+ $this->assertFalse(is_numeric($root->getKey()));
+ }
- public function testParentKeyIsNonNumeric() {
- $child1 = $this->clusters('Child 1');
+ public function testParentKeyIsNonNumeric()
+ {
+ $child1 = $this->clusters('Child 1');
- $this->assertTrue(is_string($child1->getParentId()));
- $this->assertFalse(is_numeric($child1->getParentId()));
- }
+ $this->assertTrue(is_string($child1->getParentId()));
+ $this->assertFalse(is_numeric($child1->getParentId()));
+ }
}
diff --git a/tests/suite/Cluster/ClusterHierarchyTest.php b/tests/suite/Cluster/ClusterHierarchyTest.php
index c660ee73..88670156 100644
--- a/tests/suite/Cluster/ClusterHierarchyTest.php
+++ b/tests/suite/Cluster/ClusterHierarchyTest.php
@@ -1,708 +1,764 @@
orderBy('lft')->get();
+ public function testAllStatic()
+ {
+ $results = Cluster::all();
+ $expected = Cluster::query()->orderBy('lft')->get();
- $this->assertEquals($results, $expected);
- }
+ $this->assertEquals($results, $expected);
+ }
- public function testAllStaticWithCustomOrder() {
- $results = OrderedCluster::all();
- $expected = OrderedCluster::query()->orderBy('name')->get();
+ public function testAllStaticWithCustomOrder()
+ {
+ $results = OrderedCluster::all();
+ $expected = OrderedCluster::query()->orderBy('name')->get();
- $this->assertEquals($results, $expected);
- }
+ $this->assertEquals($results, $expected);
+ }
- public function testRootsStatic() {
- $query = Cluster::whereNull('parent_id')->get();
+ public function testRootsStatic()
+ {
+ $query = Cluster::whereNull('parent_id')->get();
- $roots = Cluster::roots()->get();
+ $roots = Cluster::roots()->get();
- $this->assertEquals($query->count(), $roots->count());
- $this->assertCount(2, $roots);
+ $this->assertEquals($query->count(), $roots->count());
+ $this->assertCount(2, $roots);
- foreach ($query->pluck('id') as $node)
- $this->assertContains($node, $roots->pluck('id'));
- }
+ foreach ($query->pluck('id') as $node)
+ $this->assertContains($node, $roots->pluck('id'));
+ }
- public function testRootsStaticWithCustomOrder() {
- $cluster = OrderedCluster::create(array('name' => 'A new root is born'));
- $cluster->syncOriginal(); // ¿? --> This should be done already !?
+ public function testRootsStaticWithCustomOrder()
+ {
+ $cluster = OrderedCluster::create(array('name' => 'A new root is born'));
+ $cluster->syncOriginal(); // ¿? --> This should be done already !?
- $roots = OrderedCluster::roots()->get();
+ $roots = OrderedCluster::roots()->get();
- $this->assertCount(3, $roots);
- $this->assertEquals($cluster->getAttributes(), $roots->first()->getAttributes());
- }
+ $this->assertCount(3, $roots);
+ $this->assertEquals($cluster->getAttributes(), $roots->first()->getAttributes());
+ }
- public function testRootStatic() {
- $this->assertEquals(Cluster::root(), $this->clusters('Root 1'));
- }
+ public function testRootStatic()
+ {
+ $this->assertEquals(Cluster::root(), $this->clusters('Root 1'));
+ }
- public function testAllLeavesStatic() {
- $allLeaves = Cluster::allLeaves()->get();
+ public function testAllLeavesStatic()
+ {
+ $allLeaves = Cluster::allLeaves()->get();
- $this->assertCount(4, $allLeaves);
+ $this->assertCount(4, $allLeaves);
- $leaves = $allLeaves->pluck('name');
+ $leaves = $allLeaves->pluck('name');
- $this->assertContains('Child 1' , $leaves);
- $this->assertContains('Child 2.1' , $leaves);
- $this->assertContains('Child 3' , $leaves);
- $this->assertContains('Root 2' , $leaves);
- }
+ $this->assertContains('Child 1', $leaves);
+ $this->assertContains('Child 2.1', $leaves);
+ $this->assertContains('Child 3', $leaves);
+ $this->assertContains('Root 2', $leaves);
+ }
- public function testAllTrunksStatic() {
- $allTrunks = Cluster::allTrunks()->get();
+ public function testAllTrunksStatic()
+ {
+ $allTrunks = Cluster::allTrunks()->get();
- $this->assertCount(1, $allTrunks);
+ $this->assertCount(1, $allTrunks);
- $trunks = $allTrunks->pluck('name');
- $this->assertContains('Child 2', $trunks);
- }
+ $trunks = $allTrunks->pluck('name');
+ $this->assertContains('Child 2', $trunks);
+ }
- public function testGetRoot() {
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 1')->getRoot());
- $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 2')->getRoot());
+ public function testGetRoot()
+ {
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 1')->getRoot());
+ $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 2')->getRoot());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 1')->getRoot());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 2')->getRoot());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 2.1')->getRoot());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 3')->getRoot());
- }
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 1')->getRoot());
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 2')->getRoot());
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 2.1')->getRoot());
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Child 3')->getRoot());
+ }
- public function testGetRootEqualsSelfIfUnpersisted() {
- $cluster = new Cluster;
+ public function testGetRootEqualsSelfIfUnpersisted()
+ {
+ $cluster = new Cluster;
- $this->assertEquals($cluster->getRoot(), $cluster);
- }
+ $this->assertEquals($cluster->getRoot(), $cluster);
+ }
- public function testGetRootEqualsValueIfSetIfUnpersisted() {
- $parent = Cluster::roots()->first();
+ public function testGetRootEqualsValueIfSetIfUnpersisted()
+ {
+ $parent = Cluster::roots()->first();
- $child = new Cluster;
- $child->setAttribute($child->getParentColumnName(), $parent->getKey());
+ $child = new Cluster;
+ $child->setAttribute($child->getParentColumnName(), $parent->getKey());
- $this->assertEquals($child->getRoot(), $parent);
- }
+ $this->assertEquals($child->getRoot(), $parent);
+ }
- public function testIsRoot() {
- $this->assertTrue($this->clusters('Root 1')->isRoot());
- $this->assertTrue($this->clusters('Root 2')->isRoot());
+ public function testIsRoot()
+ {
+ $this->assertTrue($this->clusters('Root 1')->isRoot());
+ $this->assertTrue($this->clusters('Root 2')->isRoot());
- $this->assertFalse($this->clusters('Child 1')->isRoot());
- $this->assertFalse($this->clusters('Child 2')->isRoot());
- $this->assertFalse($this->clusters('Child 2.1')->isRoot());
- $this->assertFalse($this->clusters('Child 3')->isRoot());
- }
+ $this->assertFalse($this->clusters('Child 1')->isRoot());
+ $this->assertFalse($this->clusters('Child 2')->isRoot());
+ $this->assertFalse($this->clusters('Child 2.1')->isRoot());
+ $this->assertFalse($this->clusters('Child 3')->isRoot());
+ }
- public function testGetLeaves() {
- $leaves = array($this->clusters('Child 1'), $this->clusters('Child 2.1'), $this->clusters('Child 3'));
+ public function testGetLeaves()
+ {
+ $leaves = array($this->clusters('Child 1'), $this->clusters('Child 2.1'), $this->clusters('Child 3'));
- $this->assertEquals($leaves, $this->clusters('Root 1')->getLeaves()->all());
- }
+ $this->assertEquals($leaves, $this->clusters('Root 1')->getLeaves()->all());
+ }
- public function testGetLeavesInIteration() {
- $node = $this->clusters('Root 1');
+ public function testGetLeavesInIteration()
+ {
+ $node = $this->clusters('Root 1');
- $expectedIds = array(
- '5d7ce1fd-6151-46d3-a5b3-0ebb9988dc57',
- '3315a297-af87-4ad3-9fa5-19785407573d',
- '054476d2-6830-4014-a181-4de010ef7114'
- );
+ $expectedIds = array(
+ '5d7ce1fd-6151-46d3-a5b3-0ebb9988dc57',
+ '3315a297-af87-4ad3-9fa5-19785407573d',
+ '054476d2-6830-4014-a181-4de010ef7114'
+ );
- foreach($node->getLeaves() as $i => $leaf)
- $this->assertEquals($expectedIds[$i], $leaf->getKey());
- }
+ foreach ($node->getLeaves() as $i => $leaf)
+ $this->assertEquals($expectedIds[$i], $leaf->getKey());
+ }
- public function testGetTrunks() {
- $trunks = array($this->clusters('Child 2'));
+ public function testGetTrunks()
+ {
+ $trunks = array($this->clusters('Child 2'));
- $this->assertEquals($trunks, $this->clusters('Root 1')->getTrunks()->all());
- }
+ $this->assertEquals($trunks, $this->clusters('Root 1')->getTrunks()->all());
+ }
- public function testGetTrunksInIteration() {
- $node = $this->clusters('Root 1');
+ public function testGetTrunksInIteration()
+ {
+ $node = $this->clusters('Root 1');
- $expectedIds = array('07c1fc8c-53b5-4fe7-b9c4-e09f266a455c');
+ $expectedIds = array('07c1fc8c-53b5-4fe7-b9c4-e09f266a455c');
- foreach($node->getTrunks() as $i => $trunk)
- $this->assertEquals($expectedIds[$i], $trunk->getKey());
- }
+ foreach ($node->getTrunks() as $i => $trunk)
+ $this->assertEquals($expectedIds[$i], $trunk->getKey());
+ }
- public function testIsLeaf() {
- $this->assertTrue($this->clusters('Child 1')->isLeaf());
- $this->assertTrue($this->clusters('Child 2.1')->isLeaf());
- $this->assertTrue($this->clusters('Child 3')->isLeaf());
- $this->assertTrue($this->clusters('Root 2')->isLeaf());
+ public function testIsLeaf()
+ {
+ $this->assertTrue($this->clusters('Child 1')->isLeaf());
+ $this->assertTrue($this->clusters('Child 2.1')->isLeaf());
+ $this->assertTrue($this->clusters('Child 3')->isLeaf());
+ $this->assertTrue($this->clusters('Root 2')->isLeaf());
- $this->assertFalse($this->clusters('Root 1')->isLeaf());
- $this->assertFalse($this->clusters('Child 2')->isLeaf());
+ $this->assertFalse($this->clusters('Root 1')->isLeaf());
+ $this->assertFalse($this->clusters('Child 2')->isLeaf());
- $new = new Cluster;
- $this->assertFalse($new->isLeaf());
- }
+ $new = new Cluster;
+ $this->assertFalse($new->isLeaf());
+ }
- public function testIsTrunk() {
- $this->assertFalse($this->clusters('Child 1')->isTrunk());
- $this->assertFalse($this->clusters('Child 2.1')->isTrunk());
- $this->assertFalse($this->clusters('Child 3')->isTrunk());
- $this->assertFalse($this->clusters('Root 2')->isTrunk());
+ public function testIsTrunk()
+ {
+ $this->assertFalse($this->clusters('Child 1')->isTrunk());
+ $this->assertFalse($this->clusters('Child 2.1')->isTrunk());
+ $this->assertFalse($this->clusters('Child 3')->isTrunk());
+ $this->assertFalse($this->clusters('Root 2')->isTrunk());
- $this->assertFalse($this->clusters('Root 1')->isTrunk());
- $this->assertTrue($this->clusters('Child 2')->isTrunk());
+ $this->assertFalse($this->clusters('Root 1')->isTrunk());
+ $this->assertTrue($this->clusters('Child 2')->isTrunk());
- $new = new Cluster;
- $this->assertFalse($new->isTrunk());
- }
+ $new = new Cluster;
+ $this->assertFalse($new->isTrunk());
+ }
- public function testWithoutNodeScope() {
- $child = $this->clusters('Child 2.1');
+ public function testWithoutNodeScope()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Root 1'), $child);
+ $expected = array($this->clusters('Root 1'), $child);
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutNode($this->clusters('Child 2'))->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutNode($this->clusters('Child 2'))->get()->all());
+ }
- public function testWithoutSelfScope() {
- $child = $this->clusters('Child 2.1');
+ public function testWithoutSelfScope()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'));
+ $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'));
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutSelf()->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutSelf()->get()->all());
+ }
- public function testWithoutRootScope() {
- $child = $this->clusters('Child 2.1');
+ public function testWithoutRootScope()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Child 2'), $child);
+ $expected = array($this->clusters('Child 2'), $child);
- $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutRoot()->get()->all());
- }
+ $this->assertEquals($expected, $child->ancestorsAndSelf()->withoutRoot()->get()->all());
+ }
- public function testLimitDepthScope() {
- with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 10);
+ public function testLimitDepthScope()
+ {
+ with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 10);
- $node = $this->clusters('Child 2');
+ $node = $this->clusters('Child 2');
- $descendancy = $node->descendants()->pluck('id')->all();
+ $descendancy = $node->descendants()->pluck('id')->all();
- $this->assertEmpty($node->descendants()->limitDepth(0)->pluck('id')->all());
- $this->assertEquals($node->getAttributes(), $node->descendantsAndSelf()->limitDepth(0)->first()->getAttributes());
+ $this->assertEmpty($node->descendants()->limitDepth(0)->pluck('id')->all());
+ $this->assertEquals($node->getAttributes(), $node->descendantsAndSelf()->limitDepth(0)->first()->getAttributes());
- $this->assertEquals(array_slice($descendancy, 0, 3), $node->descendants()->limitDepth(3)->pluck('id')->all());
- $this->assertEquals(array_slice($descendancy, 0, 5), $node->descendants()->limitDepth(5)->pluck('id')->all());
- $this->assertEquals(array_slice($descendancy, 0, 7), $node->descendants()->limitDepth(7)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 3), $node->descendants()->limitDepth(3)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 5), $node->descendants()->limitDepth(5)->pluck('id')->all());
+ $this->assertEquals(array_slice($descendancy, 0, 7), $node->descendants()->limitDepth(7)->pluck('id')->all());
- $this->assertEquals($descendancy, $node->descendants()->limitDepth(1000)->pluck('id')->all());
- }
+ $this->assertEquals($descendancy, $node->descendants()->limitDepth(1000)->pluck('id')->all());
+ }
- public function testGetAncestorsAndSelf() {
- $child = $this->clusters('Child 2.1');
+ public function testGetAncestorsAndSelf()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'), $child);
+ $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'), $child);
- $this->assertEquals($expected, $child->getAncestorsAndSelf()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsAndSelf()->all());
+ }
- public function testGetAncestorsAndSelfWithoutRoot() {
- $child = $this->clusters('Child 2.1');
+ public function testGetAncestorsAndSelfWithoutRoot()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Child 2'), $child);
+ $expected = array($this->clusters('Child 2'), $child);
- $this->assertEquals($expected, $child->getAncestorsAndSelfWithoutRoot()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsAndSelfWithoutRoot()->all());
+ }
- public function testGetAncestors() {
- $child = $this->clusters('Child 2.1');
+ public function testGetAncestors()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'));
+ $expected = array($this->clusters('Root 1'), $this->clusters('Child 2'));
- $this->assertEquals($expected, $child->getAncestors()->all());
- }
+ $this->assertEquals($expected, $child->getAncestors()->all());
+ }
- public function testGetAncestorsWithoutRoot() {
- $child = $this->clusters('Child 2.1');
+ public function testGetAncestorsWithoutRoot()
+ {
+ $child = $this->clusters('Child 2.1');
- $expected = array($this->clusters('Child 2'));
+ $expected = array($this->clusters('Child 2'));
- $this->assertEquals($expected, $child->getAncestorsWithoutRoot()->all());
- }
+ $this->assertEquals($expected, $child->getAncestorsWithoutRoot()->all());
+ }
- public function testGetDescendantsAndSelf() {
- $parent = $this->clusters('Root 1');
+ public function testGetDescendantsAndSelf()
+ {
+ $parent = $this->clusters('Root 1');
- $expected = array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 3')
- );
+ $expected = array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 3')
+ );
- $this->assertCount(count($expected), $parent->getDescendantsAndSelf());
+ $this->assertCount(count($expected), $parent->getDescendantsAndSelf());
- $this->assertEquals($expected, $parent->getDescendantsAndSelf()->all());
- }
+ $this->assertEquals($expected, $parent->getDescendantsAndSelf()->all());
+ }
- public function testGetDescendantsAndSelfWithLimit() {
- with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 3);
-
- $parent = $this->clusters('Root 1');
-
- $this->assertEquals(array($parent), $parent->getDescendantsAndSelf(0)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 3')
- ), $parent->getDescendantsAndSelf(1)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendantsAndSelf(2)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendantsAndSelf(3)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 2.1.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendantsAndSelf(4)->all());
-
- $this->assertEquals(array(
- $parent,
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 2.1.1.1'),
- $this->clusters('Child 2.1.1.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendantsAndSelf(10)->all());
- }
-
- public function testGetDescendants() {
- $parent = $this->clusters('Root 1');
-
- $expected = array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 3')
- );
-
- $this->assertCount(count($expected), $parent->getDescendants());
-
- $this->assertEquals($expected, $parent->getDescendants()->all());
- }
-
- public function testGetDescendantsWithLimit() {
- with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 3);
-
- $parent = $this->clusters('Root 1');
-
- $this->assertEmpty($parent->getDescendants(0)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(1)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(2)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(3)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 2.1.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(4)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 2.1.1.1'),
- $this->clusters('Child 2.1.1.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(5)->all());
-
- $this->assertEquals(array(
- $this->clusters('Child 1'),
- $this->clusters('Child 2'),
- $this->clusters('Child 2.1'),
- $this->clusters('Child 2.1.1'),
- $this->clusters('Child 2.1.1.1'),
- $this->clusters('Child 2.1.1.1.1'),
- $this->clusters('Child 3')
- ), $parent->getDescendants(10)->all());
- }
-
- public function testDescendantsRecursesChildren() {
- $a = Cluster::create(array('name' => 'A'));
- $b = Cluster::create(array('name' => 'B'));
- $c = Cluster::create(array('name' => 'C'));
-
- // a > b > c
- $b->makeChildOf($a);
- $c->makeChildOf($b);
-
- $a->reload(); $b->reload(); $c->reload();
-
- $this->assertEquals(1, $a->children()->count());
- $this->assertEquals(1, $b->children()->count());
- $this->assertEquals(2, $a->descendants()->count());
- }
-
- public function testGetImmediateDescendants() {
- $expected = array($this->clusters('Child 1'), $this->clusters('Child 2'), $this->clusters('Child 3'));
-
- $this->assertEquals($expected, $this->clusters('Root 1')->getImmediateDescendants()->all());
-
- $this->assertEquals(array($this->clusters('Child 2.1')), $this->clusters('Child 2')->getImmediateDescendants()->all());
-
- $this->assertEmpty($this->clusters('Root 2')->getImmediateDescendants()->all());
- }
-
- public function testIsSelfOrAncestorOf() {
- $this->assertTrue($this->clusters('Root 1')->isSelfOrAncestorOf($this->clusters('Child 1')));
- $this->assertTrue($this->clusters('Root 1')->isSelfOrAncestorOf($this->clusters('Child 2.1')));
- $this->assertTrue($this->clusters('Child 2')->isSelfOrAncestorOf($this->clusters('Child 2.1')));
- $this->assertFalse($this->clusters('Child 2.1')->isSelfOrAncestorOf($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 1')->isSelfOrAncestorOf($this->clusters('Child 2')));
- $this->assertTrue($this->clusters('Child 1')->isSelfOrAncestorOf($this->clusters('Child 1')));
- }
-
- public function testIsAncestorOf() {
- $this->assertTrue($this->clusters('Root 1')->isAncestorOf($this->clusters('Child 1')));
- $this->assertTrue($this->clusters('Root 1')->isAncestorOf($this->clusters('Child 2.1')));
- $this->assertTrue($this->clusters('Child 2')->isAncestorOf($this->clusters('Child 2.1')));
- $this->assertFalse($this->clusters('Child 2.1')->isAncestorOf($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 1')->isAncestorOf($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 1')->isAncestorOf($this->clusters('Child 1')));
- }
-
- public function testIsSelfOrDescendantOf() {
- $this->assertTrue($this->clusters('Child 1')->isSelfOrDescendantOf($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2.1')->isSelfOrDescendantOf($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2.1')->isSelfOrDescendantOf($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 2')->isSelfOrDescendantOf($this->clusters('Child 2.1')));
- $this->assertFalse($this->clusters('Child 2')->isSelfOrDescendantOf($this->clusters('Child 1')));
- $this->assertTrue($this->clusters('Child 1')->isSelfOrDescendantOf($this->clusters('Child 1')));
- }
-
- public function testIsDescendantOf() {
- $this->assertTrue($this->clusters('Child 1')->isDescendantOf($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2.1')->isDescendantOf($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2.1')->isDescendantOf($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 2')->isDescendantOf($this->clusters('Child 2.1')));
- $this->assertFalse($this->clusters('Child 2')->isDescendantOf($this->clusters('Child 1')));
- $this->assertFalse($this->clusters('Child 1')->isDescendantOf($this->clusters('Child 1')));
- }
-
- public function testGetSiblingsAndSelf() {
- $child = $this->clusters('Child 2');
-
- $expected = array($this->clusters('Child 1'), $child, $this->clusters('Child 3'));
- $this->assertEquals($expected, $child->getSiblingsAndSelf()->all());
-
- $expected = array($this->clusters('Root 1'), $this->clusters('Root 2'));
- $this->assertEquals($expected, $this->clusters('Root 1')->getSiblingsAndSelf()->all());
- }
-
- public function testGetSiblings() {
- $child = $this->clusters('Child 2');
-
- $expected = array($this->clusters('Child 1'), $this->clusters('Child 3'));
-
- $this->assertEquals($expected, $child->getSiblings()->all());
- }
-
- public function testGetLeftSibling() {
- $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 2')->getLeftSibling());
- $this->assertEquals($this->clusters('Child 2'), $this->clusters('Child 3')->getLeftSibling());
- }
-
- public function testGetLeftSiblingOfFirstRootIsNull() {
- $this->assertNull($this->clusters('Root 1')->getLeftSibling());
- }
-
- public function testGetLeftSiblingWithNoneIsNull() {
- $this->assertNull($this->clusters('Child 2.1')->getLeftSibling());
- }
-
- public function testGetLeftSiblingOfLeftmostNodeIsNull() {
- $this->assertNull($this->clusters('Child 1')->getLeftSibling());
- }
-
- public function testGetRightSibling() {
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 2')->getRightSibling());
- $this->assertEquals($this->clusters('Child 2'), $this->clusters('Child 1')->getRightSibling());
- }
-
- public function testGetRightSiblingOfRoots() {
- $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getRightSibling());
- $this->assertNull($this->clusters('Root 2')->getRightSibling());
- }
-
- public function testGetRightSiblingWithNoneIsNull() {
- $this->assertNull($this->clusters('Child 2.1')->getRightSibling());
- }
-
- public function testGetRightSiblingOfRightmostNodeIsNull() {
- $this->assertNull($this->clusters('Child 3')->getRightSibling());
- }
-
- public function testInsideSubtree() {
- $this->assertFalse($this->clusters('Child 1')->insideSubtree($this->clusters('Root 2')));
- $this->assertFalse($this->clusters('Child 2')->insideSubtree($this->clusters('Root 2')));
- $this->assertFalse($this->clusters('Child 3')->insideSubtree($this->clusters('Root 2')));
-
- $this->assertTrue($this->clusters('Child 1')->insideSubtree($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2')->insideSubtree($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 2.1')->insideSubtree($this->clusters('Root 1')));
- $this->assertTrue($this->clusters('Child 3')->insideSubtree($this->clusters('Root 1')));
-
- $this->assertTrue($this->clusters('Child 2.1')->insideSubtree($this->clusters('Child 2')));
- $this->assertFalse($this->clusters('Child 2.1')->insideSubtree($this->clusters('Root 2')));
- }
-
- public function testGetLevel() {
- $this->assertEquals(0, $this->clusters('Root 1')->getLevel());
- $this->assertEquals(1, $this->clusters('Child 1')->getLevel());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getLevel());
- }
-
- public function testToHierarchyReturnsAnEloquentCollection() {
- $categories = Cluster::all()->toHierarchy();
-
- $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $categories);
- }
-
- public function testToHierarchyReturnsHierarchicalData() {
- $categories = Cluster::all()->toHierarchy();
-
- $this->assertEquals(2, $categories->count());
-
- $first = $categories->first();
- $this->assertEquals('Root 1', $first->name);
- $this->assertEquals(3, $first->children->count());
-
- $first_lvl2 = $first->children->first();
- $this->assertEquals('Child 1', $first_lvl2->name);
- $this->assertEquals(0, $first_lvl2->children->count());
- }
-
- public function testToHierarchyNestsCorrectly() {
- // Prune all categories
- Cluster::query()->delete();
-
- // Build a sample tree structure:
- //
- // - A
- // |- A.1
- // |- A.2
- // - B
- // |- B.1
- // |- B.2
- // |- B.2.1
- // |- B.2.2
- // |- B.2.2.1
- // |- B.2.3
- // |- B.3
- // - C
- // |- C.1
- // |- C.2
- // - D
- //
- $a = Cluster::create(array('name' => 'A'));
- $b = Cluster::create(array('name' => 'B'));
- $c = Cluster::create(array('name' => 'C'));
- $d = Cluster::create(array('name' => 'D'));
-
- $ch = Cluster::create(array('name' => 'A.1'));
- $ch->makeChildOf($a);
-
- $ch = Cluster::create(array('name' => 'A.2'));
- $ch->makeChildOf($a);
-
- $ch = Cluster::create(array('name' => 'B.1'));
- $ch->makeChildOf($b);
-
- $ch = Cluster::create(array('name' => 'B.2'));
- $ch->makeChildOf($b);
-
- $ch2 = Cluster::create(array('name' => 'B.2.1'));
- $ch2->makeChildOf($ch);
-
- $ch2 = Cluster::create(array('name' => 'B.2.2'));
- $ch2->makeChildOf($ch);
-
- $ch3 = Cluster::create(array('name' => 'B.2.2.1'));
- $ch3->makeChildOf($ch2);
-
- $ch2 = Cluster::create(array('name' => 'B.2.3'));
- $ch2->makeChildOf($ch);
-
- $ch = Cluster::create(array('name' => 'B.3'));
- $ch->makeChildOf($b);
-
- $ch = Cluster::create(array('name' => 'C.1'));
- $ch->makeChildOf($c);
-
- $ch = Cluster::create(array('name' => 'C.2'));
- $ch->makeChildOf($c);
-
- $this->assertTrue(Cluster::isValidNestedSet());
-
- // Build expectations (expected trees/subtrees)
- $expectedWholeTree = array(
- 'A' => array ( 'A.1' => null, 'A.2' => null ),
- 'B' => array (
- 'B.1' => null,
- 'B.2' =>
- array (
- 'B.2.1' => null,
- 'B.2.2' => array ( 'B.2.2.1' => null ),
- 'B.2.3' => null,
- ),
- 'B.3' => null,
- ),
- 'C' => array ( 'C.1' => null, 'C.2' => null ),
- 'D' => null
- );
-
- $expectedSubtreeA = array('A' => array ( 'A.1' => null, 'A.2' => null ));
-
- $expectedSubtreeB = array(
- 'B' => array (
- 'B.1' => null,
- 'B.2' =>
- array (
- 'B.2.1' => null,
- 'B.2.2' => array ( 'B.2.2.1' => null ),
- 'B.2.3' => null
- ),
- 'B.3' => null
- )
- );
-
- $expectedSubtreeC = array( 'C.1' => null, 'C.2' => null );
-
- $expectedSubtreeD = array('D' => null);
-
- // Perform assertions
- $wholeTree = hmap(Cluster::all()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedWholeTree, $wholeTree);
-
- $subtreeA = hmap($this->clusters('A')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeA, $subtreeA);
-
- $subtreeB = hmap($this->clusters('B')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeB, $subtreeB);
-
- $subtreeC = hmap($this->clusters('C')->getDescendants()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeC, $subtreeC);
-
- $subtreeD = hmap($this->clusters('D')->getDescendantsAndSelf()->toHierarchy()->toArray());
- $this->assertArraysAreEqual($expectedSubtreeD, $subtreeD);
-
- $this->assertTrue($this->clusters('D')->getDescendants()->toHierarchy()->isEmpty());
- }
-
- public function testToHierarchyNestsCorrectlyNotSequential() {
- $parent = $this->clusters('Child 1');
-
- $parent->children()->create(array('name' => 'Child 1.1'));
-
- $parent->children()->create(array('name' => 'Child 1.2'));
-
- $this->assertTrue(Cluster::isValidNestedSet());
-
- $expected = array(
- 'Child 1' => array(
- 'Child 1.1' => null,
- 'Child 1.2' => null
- )
- );
-
- $parent->reload();
- $this->assertArraysAreEqual($expected, hmap($parent->getDescendantsAndSelf()->toHierarchy()->toArray()));
- }
-
- public function testToHierarchyNestsCorrectlyWithOrder() {
- with(new OrderedClusterSeeder)->run();
-
- $expectedWhole = array(
- 'Root A' => null,
- 'Root Z' => array(
- 'Child A' => null,
- 'Child C' => null,
- 'Child G' => array( 'Child G.1' => null )
- )
- );
- $this->assertArraysAreEqual($expectedWhole, hmap(OrderedCluster::all()->toHierarchy()->toArray()));
-
- $expectedSubtreeZ = array(
- 'Root Z' => array(
- 'Child A' => null,
- 'Child C' => null,
- 'Child G' => array( 'Child G.1' => null )
- )
- );
- $this->assertArraysAreEqual($expectedSubtreeZ, hmap($this->clusters('Root Z', 'OrderedCluster')->getDescendantsAndSelf()->toHierarchy()->toArray()));
- }
-
- public function testGetNestedList() {
- $seperator = ' ';
- $nestedList = Cluster::getNestedList('name', 'id', $seperator);
-
- $expected = array(
- '7461d8f5-2ea9-4788-99c4-9d0244f0bfb1' => str_repeat($seperator, 0). 'Root 1',
- '5d7ce1fd-6151-46d3-a5b3-0ebb9988dc57' => str_repeat($seperator, 1). 'Child 1',
- '07c1fc8c-53b5-4fe7-b9c4-e09f266a455c' => str_repeat($seperator, 1). 'Child 2',
- '3315a297-af87-4ad3-9fa5-19785407573d' => str_repeat($seperator, 2). 'Child 2.1',
- '054476d2-6830-4014-a181-4de010ef7114' => str_repeat($seperator, 1). 'Child 3',
- '3bb62314-9e1e-49c6-a5cb-17a9ab9b1b9a' => str_repeat($seperator, 0). 'Root 2',
- );
-
- $this->assertArraysAreEqual($expected, $nestedList);
- }
+ public function testGetDescendantsAndSelfWithLimit()
+ {
+ with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 3);
+
+ $parent = $this->clusters('Root 1');
+
+ $this->assertEquals(array($parent), $parent->getDescendantsAndSelf(0)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendantsAndSelf(1)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendantsAndSelf(2)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendantsAndSelf(3)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 2.1.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendantsAndSelf(4)->all());
+
+ $this->assertEquals(array(
+ $parent,
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 2.1.1.1'),
+ $this->clusters('Child 2.1.1.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendantsAndSelf(10)->all());
+ }
+
+ public function testGetDescendants()
+ {
+ $parent = $this->clusters('Root 1');
+
+ $expected = array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 3')
+ );
+
+ $this->assertCount(count($expected), $parent->getDescendants());
+
+ $this->assertEquals($expected, $parent->getDescendants()->all());
+ }
+
+ public function testGetDescendantsWithLimit()
+ {
+ with(new ClusterSeeder)->nestUptoAt($this->clusters('Child 2.1'), 3);
+
+ $parent = $this->clusters('Root 1');
+
+ $this->assertEmpty($parent->getDescendants(0)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(1)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(2)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(3)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 2.1.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(4)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 2.1.1.1'),
+ $this->clusters('Child 2.1.1.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(5)->all());
+
+ $this->assertEquals(array(
+ $this->clusters('Child 1'),
+ $this->clusters('Child 2'),
+ $this->clusters('Child 2.1'),
+ $this->clusters('Child 2.1.1'),
+ $this->clusters('Child 2.1.1.1'),
+ $this->clusters('Child 2.1.1.1.1'),
+ $this->clusters('Child 3')
+ ), $parent->getDescendants(10)->all());
+ }
+
+ public function testDescendantsRecursesChildren()
+ {
+ $a = Cluster::create(array('name' => 'A'));
+ $b = Cluster::create(array('name' => 'B'));
+ $c = Cluster::create(array('name' => 'C'));
+
+ // a > b > c
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+
+ $this->assertEquals(1, $a->children()->count());
+ $this->assertEquals(1, $b->children()->count());
+ $this->assertEquals(2, $a->descendants()->count());
+ }
+
+ public function testGetImmediateDescendants()
+ {
+ $expected = array($this->clusters('Child 1'), $this->clusters('Child 2'), $this->clusters('Child 3'));
+
+ $this->assertEquals($expected, $this->clusters('Root 1')->getImmediateDescendants()->all());
+
+ $this->assertEquals(array($this->clusters('Child 2.1')), $this->clusters('Child 2')->getImmediateDescendants()->all());
+
+ $this->assertEmpty($this->clusters('Root 2')->getImmediateDescendants()->all());
+ }
+
+ public function testIsSelfOrAncestorOf()
+ {
+ $this->assertTrue($this->clusters('Root 1')->isSelfOrAncestorOf($this->clusters('Child 1')));
+ $this->assertTrue($this->clusters('Root 1')->isSelfOrAncestorOf($this->clusters('Child 2.1')));
+ $this->assertTrue($this->clusters('Child 2')->isSelfOrAncestorOf($this->clusters('Child 2.1')));
+ $this->assertFalse($this->clusters('Child 2.1')->isSelfOrAncestorOf($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 1')->isSelfOrAncestorOf($this->clusters('Child 2')));
+ $this->assertTrue($this->clusters('Child 1')->isSelfOrAncestorOf($this->clusters('Child 1')));
+ }
+
+ public function testIsAncestorOf()
+ {
+ $this->assertTrue($this->clusters('Root 1')->isAncestorOf($this->clusters('Child 1')));
+ $this->assertTrue($this->clusters('Root 1')->isAncestorOf($this->clusters('Child 2.1')));
+ $this->assertTrue($this->clusters('Child 2')->isAncestorOf($this->clusters('Child 2.1')));
+ $this->assertFalse($this->clusters('Child 2.1')->isAncestorOf($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 1')->isAncestorOf($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 1')->isAncestorOf($this->clusters('Child 1')));
+ }
+
+ public function testIsSelfOrDescendantOf()
+ {
+ $this->assertTrue($this->clusters('Child 1')->isSelfOrDescendantOf($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2.1')->isSelfOrDescendantOf($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2.1')->isSelfOrDescendantOf($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 2')->isSelfOrDescendantOf($this->clusters('Child 2.1')));
+ $this->assertFalse($this->clusters('Child 2')->isSelfOrDescendantOf($this->clusters('Child 1')));
+ $this->assertTrue($this->clusters('Child 1')->isSelfOrDescendantOf($this->clusters('Child 1')));
+ }
+
+ public function testIsDescendantOf()
+ {
+ $this->assertTrue($this->clusters('Child 1')->isDescendantOf($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2.1')->isDescendantOf($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2.1')->isDescendantOf($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 2')->isDescendantOf($this->clusters('Child 2.1')));
+ $this->assertFalse($this->clusters('Child 2')->isDescendantOf($this->clusters('Child 1')));
+ $this->assertFalse($this->clusters('Child 1')->isDescendantOf($this->clusters('Child 1')));
+ }
+
+ public function testGetSiblingsAndSelf()
+ {
+ $child = $this->clusters('Child 2');
+
+ $expected = array($this->clusters('Child 1'), $child, $this->clusters('Child 3'));
+ $this->assertEquals($expected, $child->getSiblingsAndSelf()->all());
+
+ $expected = array($this->clusters('Root 1'), $this->clusters('Root 2'));
+ $this->assertEquals($expected, $this->clusters('Root 1')->getSiblingsAndSelf()->all());
+ }
+
+ public function testGetSiblings()
+ {
+ $child = $this->clusters('Child 2');
+
+ $expected = array($this->clusters('Child 1'), $this->clusters('Child 3'));
+
+ $this->assertEquals($expected, $child->getSiblings()->all());
+ }
+
+ public function testGetLeftSibling()
+ {
+ $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 2')->getLeftSibling());
+ $this->assertEquals($this->clusters('Child 2'), $this->clusters('Child 3')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingOfFirstRootIsNull()
+ {
+ $this->assertNull($this->clusters('Root 1')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingWithNoneIsNull()
+ {
+ $this->assertNull($this->clusters('Child 2.1')->getLeftSibling());
+ }
+
+ public function testGetLeftSiblingOfLeftmostNodeIsNull()
+ {
+ $this->assertNull($this->clusters('Child 1')->getLeftSibling());
+ }
+
+ public function testGetRightSibling()
+ {
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 2')->getRightSibling());
+ $this->assertEquals($this->clusters('Child 2'), $this->clusters('Child 1')->getRightSibling());
+ }
+
+ public function testGetRightSiblingOfRoots()
+ {
+ $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getRightSibling());
+ $this->assertNull($this->clusters('Root 2')->getRightSibling());
+ }
+
+ public function testGetRightSiblingWithNoneIsNull()
+ {
+ $this->assertNull($this->clusters('Child 2.1')->getRightSibling());
+ }
+
+ public function testGetRightSiblingOfRightmostNodeIsNull()
+ {
+ $this->assertNull($this->clusters('Child 3')->getRightSibling());
+ }
+
+ public function testInsideSubtree()
+ {
+ $this->assertFalse($this->clusters('Child 1')->insideSubtree($this->clusters('Root 2')));
+ $this->assertFalse($this->clusters('Child 2')->insideSubtree($this->clusters('Root 2')));
+ $this->assertFalse($this->clusters('Child 3')->insideSubtree($this->clusters('Root 2')));
+
+ $this->assertTrue($this->clusters('Child 1')->insideSubtree($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2')->insideSubtree($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 2.1')->insideSubtree($this->clusters('Root 1')));
+ $this->assertTrue($this->clusters('Child 3')->insideSubtree($this->clusters('Root 1')));
+
+ $this->assertTrue($this->clusters('Child 2.1')->insideSubtree($this->clusters('Child 2')));
+ $this->assertFalse($this->clusters('Child 2.1')->insideSubtree($this->clusters('Root 2')));
+ }
+
+ public function testGetLevel()
+ {
+ $this->assertEquals(0, $this->clusters('Root 1')->getLevel());
+ $this->assertEquals(1, $this->clusters('Child 1')->getLevel());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getLevel());
+ }
+
+ public function testToHierarchyReturnsAnEloquentCollection()
+ {
+ $categories = Cluster::all()->toHierarchy();
+
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $categories);
+ }
+
+ public function testToHierarchyReturnsHierarchicalData()
+ {
+ $categories = Cluster::all()->toHierarchy();
+
+ $this->assertEquals(2, $categories->count());
+
+ $first = $categories->first();
+ $this->assertEquals('Root 1', $first->name);
+ $this->assertEquals(3, $first->children->count());
+
+ $first_lvl2 = $first->children->first();
+ $this->assertEquals('Child 1', $first_lvl2->name);
+ $this->assertEquals(0, $first_lvl2->children->count());
+ }
+
+ public function testToHierarchyNestsCorrectly()
+ {
+ // Prune all categories
+ Cluster::query()->delete();
+
+ // Build a sample tree structure:
+ //
+ // - A
+ // |- A.1
+ // |- A.2
+ // - B
+ // |- B.1
+ // |- B.2
+ // |- B.2.1
+ // |- B.2.2
+ // |- B.2.2.1
+ // |- B.2.3
+ // |- B.3
+ // - C
+ // |- C.1
+ // |- C.2
+ // - D
+ //
+ $a = Cluster::create(array('name' => 'A'));
+ $b = Cluster::create(array('name' => 'B'));
+ $c = Cluster::create(array('name' => 'C'));
+ $d = Cluster::create(array('name' => 'D'));
+
+ $ch = Cluster::create(array('name' => 'A.1'));
+ $ch->makeChildOf($a);
+
+ $ch = Cluster::create(array('name' => 'A.2'));
+ $ch->makeChildOf($a);
+
+ $ch = Cluster::create(array('name' => 'B.1'));
+ $ch->makeChildOf($b);
+
+ $ch = Cluster::create(array('name' => 'B.2'));
+ $ch->makeChildOf($b);
+
+ $ch2 = Cluster::create(array('name' => 'B.2.1'));
+ $ch2->makeChildOf($ch);
+
+ $ch2 = Cluster::create(array('name' => 'B.2.2'));
+ $ch2->makeChildOf($ch);
+
+ $ch3 = Cluster::create(array('name' => 'B.2.2.1'));
+ $ch3->makeChildOf($ch2);
+
+ $ch2 = Cluster::create(array('name' => 'B.2.3'));
+ $ch2->makeChildOf($ch);
+
+ $ch = Cluster::create(array('name' => 'B.3'));
+ $ch->makeChildOf($b);
+
+ $ch = Cluster::create(array('name' => 'C.1'));
+ $ch->makeChildOf($c);
+
+ $ch = Cluster::create(array('name' => 'C.2'));
+ $ch->makeChildOf($c);
+
+ $this->assertTrue(Cluster::isValidNestedSet());
+
+ // Build expectations (expected trees/subtrees)
+ $expectedWholeTree = array(
+ 'A' => array('A.1' => null, 'A.2' => null),
+ 'B' => array(
+ 'B.1' => null,
+ 'B.2' =>
+ array(
+ 'B.2.1' => null,
+ 'B.2.2' => array('B.2.2.1' => null),
+ 'B.2.3' => null,
+ ),
+ 'B.3' => null,
+ ),
+ 'C' => array('C.1' => null, 'C.2' => null),
+ 'D' => null
+ );
+
+ $expectedSubtreeA = array('A' => array('A.1' => null, 'A.2' => null));
+
+ $expectedSubtreeB = array(
+ 'B' => array(
+ 'B.1' => null,
+ 'B.2' =>
+ array(
+ 'B.2.1' => null,
+ 'B.2.2' => array('B.2.2.1' => null),
+ 'B.2.3' => null
+ ),
+ 'B.3' => null
+ )
+ );
+
+ $expectedSubtreeC = array('C.1' => null, 'C.2' => null);
+
+ $expectedSubtreeD = array('D' => null);
+
+ // Perform assertions
+ $wholeTree = hmap(Cluster::all()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedWholeTree, $wholeTree);
+
+ $subtreeA = hmap($this->clusters('A')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeA, $subtreeA);
+
+ $subtreeB = hmap($this->clusters('B')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeB, $subtreeB);
+
+ $subtreeC = hmap($this->clusters('C')->getDescendants()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeC, $subtreeC);
+
+ $subtreeD = hmap($this->clusters('D')->getDescendantsAndSelf()->toHierarchy()->toArray());
+ $this->assertArraysAreEqual($expectedSubtreeD, $subtreeD);
+
+ $this->assertTrue($this->clusters('D')->getDescendants()->toHierarchy()->isEmpty());
+ }
+
+ public function testToHierarchyNestsCorrectlyNotSequential()
+ {
+ $parent = $this->clusters('Child 1');
+
+ $parent->children()->create(array('name' => 'Child 1.1'));
+
+ $parent->children()->create(array('name' => 'Child 1.2'));
+
+ $this->assertTrue(Cluster::isValidNestedSet());
+
+ $expected = array(
+ 'Child 1' => array(
+ 'Child 1.1' => null,
+ 'Child 1.2' => null
+ )
+ );
+
+ $parent->reload();
+ $this->assertArraysAreEqual($expected, hmap($parent->getDescendantsAndSelf()->toHierarchy()->toArray()));
+ }
+
+ public function testToHierarchyNestsCorrectlyWithOrder()
+ {
+ with(new OrderedClusterSeeder)->run();
+
+ $expectedWhole = array(
+ 'Root A' => null,
+ 'Root Z' => array(
+ 'Child A' => null,
+ 'Child C' => null,
+ 'Child G' => array('Child G.1' => null)
+ )
+ );
+ $this->assertArraysAreEqual($expectedWhole, hmap(OrderedCluster::all()->toHierarchy()->toArray()));
+
+ $expectedSubtreeZ = array(
+ 'Root Z' => array(
+ 'Child A' => null,
+ 'Child C' => null,
+ 'Child G' => array('Child G.1' => null)
+ )
+ );
+ $this->assertArraysAreEqual($expectedSubtreeZ, hmap($this->clusters('Root Z', 'OrderedCluster')->getDescendantsAndSelf()->toHierarchy()->toArray()));
+ }
+
+ public function testGetNestedList()
+ {
+ $seperator = ' ';
+ $nestedList = Cluster::getNestedList('name', 'id', $seperator);
+
+ $expected = array(
+ '7461d8f5-2ea9-4788-99c4-9d0244f0bfb1' => str_repeat($seperator, 0) . 'Root 1',
+ '5d7ce1fd-6151-46d3-a5b3-0ebb9988dc57' => str_repeat($seperator, 1) . 'Child 1',
+ '07c1fc8c-53b5-4fe7-b9c4-e09f266a455c' => str_repeat($seperator, 1) . 'Child 2',
+ '3315a297-af87-4ad3-9fa5-19785407573d' => str_repeat($seperator, 2) . 'Child 2.1',
+ '054476d2-6830-4014-a181-4de010ef7114' => str_repeat($seperator, 1) . 'Child 3',
+ '3bb62314-9e1e-49c6-a5cb-17a9ab9b1b9a' => str_repeat($seperator, 0) . 'Root 2',
+ );
+
+ $this->assertArraysAreEqual($expected, $nestedList);
+ }
}
diff --git a/tests/suite/Cluster/ClusterMovementTest.php b/tests/suite/Cluster/ClusterMovementTest.php
index 967a68ea..cc06a7f0 100644
--- a/tests/suite/Cluster/ClusterMovementTest.php
+++ b/tests/suite/Cluster/ClusterMovementTest.php
@@ -1,528 +1,568 @@
clusters('Child 2')->moveLeft();
+ public function testMoveLeft()
+ {
+ $this->clusters('Child 2')->moveLeft();
- $this->assertNull($this->clusters('Child 2')->getLeftSibling());
+ $this->assertNull($this->clusters('Child 2')->getLeftSibling());
- $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 2')->getRightSibling());
+ $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 2')->getRightSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveLeftRaisesAnExceptionWhenNotPossible() {
- $node = $this->clusters('Child 2');
+ public function testMoveLeftRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $node->moveLeft();
- $node->moveLeft();
- }
+ $node = $this->clusters('Child 2');
- public function testMoveLeftDoesNotChangeDepth() {
- $this->clusters('Child 2')->moveLeft();
+ $node->moveLeft();
+ $node->moveLeft();
+ }
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ public function testMoveLeftDoesNotChangeDepth()
+ {
+ $this->clusters('Child 2')->moveLeft();
- public function testMoveLeftWithSubtree() {
- $this->clusters('Root 2')->moveLeft();
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertNull($this->clusters('Root 2')->getLeftSibling());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 2')->getRightSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
+ public function testMoveLeftWithSubtree()
+ {
+ $this->clusters('Root 2')->moveLeft();
- $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
- $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
+ $this->assertNull($this->clusters('Root 2')->getLeftSibling());
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 2')->getRightSibling());
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
+ $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
+ $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
- public function testMoveToLeftOf() {
- $this->clusters('Child 3')->moveToLeftOf($this->clusters('Child 1'));
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertNull($this->clusters('Child 3')->getLeftSibling());
+ public function testMoveToLeftOf()
+ {
+ $this->clusters('Child 3')->moveToLeftOf($this->clusters('Child 1'));
- $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 3')->getRightSibling());
+ $this->assertNull($this->clusters('Child 3')->getLeftSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertEquals($this->clusters('Child 1'), $this->clusters('Child 3')->getRightSibling());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveToLeftOfRaisesAnExceptionWhenNotPossible() {
- $this->clusters('Child 1')->moveToLeftOf($this->clusters('Child 1')->getLeftSibling());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMoveToLeftOfDoesNotChangeDepth() {
- $this->clusters('Child 2')->moveToLeftOf($this->clusters('Child 1'));
+ public function testMoveToLeftOfRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $this->clusters('Child 1')->moveToLeftOf($this->clusters('Child 1')->getLeftSibling());
+ }
- public function testMoveToLeftOfWithSubtree() {
- $this->clusters('Root 2')->moveToLeftOf($this->clusters('Root 1'));
+ public function testMoveToLeftOfDoesNotChangeDepth()
+ {
+ $this->clusters('Child 2')->moveToLeftOf($this->clusters('Child 1'));
- $this->assertNull($this->clusters('Root 2')->getLeftSibling());
- $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 2')->getRightSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
- $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
+ public function testMoveToLeftOfWithSubtree()
+ {
+ $this->clusters('Root 2')->moveToLeftOf($this->clusters('Root 1'));
- $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
+ $this->assertNull($this->clusters('Root 2')->getLeftSibling());
+ $this->assertEquals($this->clusters('Root 1'), $this->clusters('Root 2')->getRightSibling());
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
+ $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
- public function testMoveRight() {
- $this->clusters('Child 2')->moveRight();
+ $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
- $this->assertNull($this->clusters('Child 2')->getRightSibling());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 2')->getLeftSibling());
+ public function testMoveRight()
+ {
+ $this->clusters('Child 2')->moveRight();
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertNull($this->clusters('Child 2')->getRightSibling());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveRightRaisesAnExceptionWhenNotPossible() {
- $node = $this->clusters('Child 2');
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 2')->getLeftSibling());
- $node->moveRight();
- $node->moveRight();
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMoveRightDoesNotChangeDepth() {
- $this->clusters('Child 2')->moveRight();
+ public function testMoveRightRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $node = $this->clusters('Child 2');
- public function testMoveRightWithSubtree() {
- $this->clusters('Root 1')->moveRight();
+ $node->moveRight();
+ $node->moveRight();
+ }
- $this->assertNull($this->clusters('Root 1')->getRightSibling());
- $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getLeftSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
+ public function testMoveRightDoesNotChangeDepth()
+ {
+ $this->clusters('Child 2')->moveRight();
- $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
- $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
+ public function testMoveRightWithSubtree()
+ {
+ $this->clusters('Root 1')->moveRight();
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $this->assertNull($this->clusters('Root 1')->getRightSibling());
+ $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getLeftSibling());
+ $this->assertTrue(Cluster::isValidNestedSet());
- public function testMoveToRightOf() {
- $this->clusters('Child 1')->moveToRightOf($this->clusters('Child 3'));
+ $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
+ $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
- $this->assertNull($this->clusters('Child 1')->getRightSibling());
+ $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->getLeftSibling());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ public function testMoveToRightOf()
+ {
+ $this->clusters('Child 1')->moveToRightOf($this->clusters('Child 3'));
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testMoveToRightOfRaisesAnExceptionWhenNotPossible() {
- $this->clusters('Child 3')->moveToRightOf($this->clusters('Child 3')->getRightSibling());
- }
+ $this->assertNull($this->clusters('Child 1')->getRightSibling());
- public function testMoveToRightOfDoesNotChangeDepth() {
- $this->clusters('Child 2')->moveToRightOf($this->clusters('Child 3'));
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->getLeftSibling());
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMoveToRightOfWithSubtree() {
- $this->clusters('Root 1')->moveToRightOf($this->clusters('Root 2'));
+ public function testMoveToRightOfRaisesAnExceptionWhenNotPossible()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $this->assertNull($this->clusters('Root 1')->getRightSibling());
- $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getLeftSibling());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->clusters('Child 3')->moveToRightOf($this->clusters('Child 3')->getRightSibling());
+ }
- $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
- $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
+ public function testMoveToRightOfDoesNotChangeDepth()
+ {
+ $this->clusters('Child 2')->moveToRightOf($this->clusters('Child 3'));
- $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
- }
+ public function testMoveToRightOfWithSubtree()
+ {
+ $this->clusters('Root 1')->moveToRightOf($this->clusters('Root 2'));
- public function testMakeRoot() {
- $this->clusters('Child 2')->makeRoot();
+ $this->assertNull($this->clusters('Root 1')->getRightSibling());
+ $this->assertEquals($this->clusters('Root 2'), $this->clusters('Root 1')->getLeftSibling());
+ $this->assertTrue(Cluster::isValidNestedSet());
- $newRoot = $this->clusters('Child 2');
+ $this->assertEquals(0, $this->clusters('Root 1')->getDepth());
+ $this->assertEquals(0, $this->clusters('Root 2')->getDepth());
- $this->assertNull($newRoot->parent()->first());
- $this->assertEquals(0, $newRoot->getLevel());
- $this->assertEquals(9, $newRoot->getLeft());
- $this->assertEquals(12, $newRoot->getRight());
+ $this->assertEquals(1, $this->clusters('Child 1')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 2')->getDepth());
+ $this->assertEquals(1, $this->clusters('Child 3')->getDepth());
- $this->assertEquals(1, $this->clusters('Child 2.1')->getLevel());
+ $this->assertEquals(2, $this->clusters('Child 2.1')->getDepth());
+ }
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ public function testMakeRoot()
+ {
+ $this->clusters('Child 2')->makeRoot();
- public function testNullifyParentColumnMakesItRoot() {
- $node = $this->clusters('Child 2');
+ $newRoot = $this->clusters('Child 2');
- $node->parent_id = null;
+ $this->assertNull($newRoot->parent()->first());
+ $this->assertEquals(0, $newRoot->getLevel());
+ $this->assertEquals(9, $newRoot->getLeft());
+ $this->assertEquals(12, $newRoot->getRight());
- $node->save();
+ $this->assertEquals(1, $this->clusters('Child 2.1')->getLevel());
- $this->assertNull($node->parent()->first());
- $this->assertEquals(0, $node->getLevel());
- $this->assertEquals(9, $node->getLeft());
- $this->assertEquals(12, $node->getRight());
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertEquals(1, $this->clusters('Child 2.1')->getLevel());
+ public function testNullifyParentColumnMakesItRoot()
+ {
+ $node = $this->clusters('Child 2');
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $node->parent_id = null;
- public function testNullifyParentColumnOnNewNodes() {
- $node = new Cluster(['name' => 'Root 3']);
+ $node->save();
- $node->parent_id = null;
+ $this->assertNull($node->parent()->first());
+ $this->assertEquals(0, $node->getLevel());
+ $this->assertEquals(9, $node->getLeft());
+ $this->assertEquals(12, $node->getRight());
- $node->save();
+ $this->assertEquals(1, $this->clusters('Child 2.1')->getLevel());
- $node->reload();
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertNull($node->parent()->first());
- $this->assertEquals(0, $node->getLevel());
- $this->assertEquals(13, $node->getLeft());
- $this->assertEquals(14, $node->getRight());
+ public function testNullifyParentColumnOnNewNodes()
+ {
+ $node = new Cluster(['name' => 'Root 3']);
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $node->parent_id = null;
- public function testNewClusterWithNullParent() {
- $node = new Cluster(['name' => 'Root 3']);
- $this->assertTrue($node->isRoot());
+ $node->save();
- $node->save();
- $this->assertTrue($node->isRoot());
+ $node->reload();
- $node->makeRoot();
- $this->assertTrue($node->isRoot());
- }
+ $this->assertNull($node->parent()->first());
+ $this->assertEquals(0, $node->getLevel());
+ $this->assertEquals(13, $node->getLeft());
+ $this->assertEquals(14, $node->getRight());
- public function testMakeChildOf() {
- $this->clusters('Child 1')->makeChildOf($this->clusters('Child 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
+ public function testNewClusterWithNullParent()
+ {
+ $node = new Cluster(['name' => 'Root 3']);
+ $this->assertTrue($node->isRoot());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $node->save();
+ $this->assertTrue($node->isRoot());
- public function testMakeChildOfAppendsAtTheEnd() {
- $newChild = Cluster::create(array('name' => 'Child 4'));
+ $node->makeRoot();
+ $this->assertTrue($node->isRoot());
+ }
- $newChild->makeChildOf($this->clusters('Root 1'));
+ public function testMakeChildOf()
+ {
+ $this->clusters('Child 1')->makeChildOf($this->clusters('Child 3'));
- $lastChild = $this->clusters('Root 1')->children()->get()->last();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMakeChildOfMovesWithSubtree() {
- $this->clusters('Child 2')->makeChildOf($this->clusters('Child 1'));
+ public function testMakeChildOfAppendsAtTheEnd()
+ {
+ $newChild = Cluster::create(array('name' => 'Child 4'));
- $this->assertTrue(Cluster::isValidNestedSet());
+ $newChild->makeChildOf($this->clusters('Root 1'));
- $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
+ $lastChild = $this->clusters('Root 1')->children()->get()->last();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
- $this->assertEquals(6, $this->clusters('Child 2')->getRight());
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
- $this->assertEquals(7, $this->clusters('Child 1')->getRight());
- }
+ public function testMakeChildOfMovesWithSubtree()
+ {
+ $this->clusters('Child 2')->makeChildOf($this->clusters('Child 1'));
- public function testMakeChildOfSwappingRoots() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
- $this->clusters('Root 2')->makeChildOf($newRoot);
+ $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
+ $this->assertEquals(6, $this->clusters('Child 2')->getRight());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
+ $this->assertEquals(7, $this->clusters('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
+ public function testMakeChildOfSwappingRoots()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->clusters('Root 2')->makeChildOf($newRoot);
- public function testMakeChildOfSwappingRootsWithSubtrees() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->clusters('Root 1')->makeChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 1')->getRight());
+ public function testMakeChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
- }
+ $this->clusters('Root 1')->makeChildOf($newRoot);
- public function testMakeFirstChildOf() {
- $this->clusters('Child 1')->makeFirstChildOf($this->clusters('Child 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 1')->getRight());
- public function testMakeFirstChildOfAppendsAtTheBeginning() {
- $newChild = Cluster::create(array('name' => 'Child 4'));
+ $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
+ }
- $newChild->makeFirstChildOf($this->clusters('Root 1'));
+ public function testMakeFirstChildOf()
+ {
+ $this->clusters('Child 1')->makeFirstChildOf($this->clusters('Child 3'));
- $lastChild = $this->clusters('Root 1')->children()->get()->first();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMakeFirstChildOfMovesWithSubtree() {
- $this->clusters('Child 2')->makeFirstChildOf($this->clusters('Child 1'));
+ public function testMakeFirstChildOfAppendsAtTheBeginning()
+ {
+ $newChild = Cluster::create(array('name' => 'Child 4'));
- $this->assertTrue(Cluster::isValidNestedSet());
+ $newChild->makeFirstChildOf($this->clusters('Root 1'));
- $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
+ $lastChild = $this->clusters('Root 1')->children()->get()->first();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
- $this->assertEquals(6, $this->clusters('Child 2')->getRight());
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
- $this->assertEquals(7, $this->clusters('Child 1')->getRight());
- }
+ public function testMakeFirstChildOfMovesWithSubtree()
+ {
+ $this->clusters('Child 2')->makeFirstChildOf($this->clusters('Child 1'));
- public function testMakeFirstChildOfSwappingRoots() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
- $this->clusters('Root 2')->makeFirstChildOf($newRoot);
+ $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
+ $this->assertEquals(6, $this->clusters('Child 2')->getRight());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
+ $this->assertEquals(7, $this->clusters('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
+ public function testMakeFirstChildOfSwappingRoots()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->clusters('Root 2')->makeFirstChildOf($newRoot);
- public function testMakeFirstChildOfSwappingRootsWithSubtrees() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->clusters('Root 1')->makeFirstChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 1')->getRight());
+ public function testMakeFirstChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
- }
+ $this->clusters('Root 1')->makeFirstChildOf($newRoot);
- public function testMakeLastChildOf() {
- $this->clusters('Child 1')->makeLastChildOf($this->clusters('Child 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 1')->getRight());
- public function testMakeLastChildOfAppendsAtTheEnd() {
- $newChild = Cluster::create(array('name' => 'Child 4'));
+ $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
+ }
- $newChild->makeLastChildOf($this->clusters('Root 1'));
+ public function testMakeLastChildOf()
+ {
+ $this->clusters('Child 1')->makeLastChildOf($this->clusters('Child 3'));
- $lastChild = $this->clusters('Root 1')->children()->get()->last();
- $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
+ $this->assertEquals($this->clusters('Child 3'), $this->clusters('Child 1')->parent()->first());
- $this->assertTrue(Cluster::isValidNestedSet());
- }
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- public function testMakeLastChildOfMovesWithSubtree() {
- $this->clusters('Child 2')->makeLastChildOf($this->clusters('Child 1'));
+ public function testMakeLastChildOfAppendsAtTheEnd()
+ {
+ $newChild = Cluster::create(array('name' => 'Child 4'));
- $this->assertTrue(Cluster::isValidNestedSet());
+ $newChild->makeLastChildOf($this->clusters('Root 1'));
- $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
+ $lastChild = $this->clusters('Root 1')->children()->get()->last();
+ $this->assertEquals($newChild->getAttributes(), $lastChild->getAttributes());
- $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
- $this->assertEquals(6, $this->clusters('Child 2')->getRight());
+ $this->assertTrue(Cluster::isValidNestedSet());
+ }
- $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
- $this->assertEquals(7, $this->clusters('Child 1')->getRight());
- }
+ public function testMakeLastChildOfMovesWithSubtree()
+ {
+ $this->clusters('Child 2')->makeLastChildOf($this->clusters('Child 1'));
- public function testMakeLastChildOfSwappingRoots() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->assertEquals(13, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
+ $this->assertEquals($this->clusters('Child 1')->getKey(), $this->clusters('Child 2')->getParentId());
- $this->clusters('Root 2')->makeLastChildOf($newRoot);
+ $this->assertEquals(3, $this->clusters('Child 2')->getLeft());
+ $this->assertEquals(6, $this->clusters('Child 2')->getRight());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(2, $this->clusters('Child 1')->getLeft());
+ $this->assertEquals(7, $this->clusters('Child 1')->getRight());
+ }
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
+ public function testMakeLastChildOfSwappingRoots()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 2')->getRight());
+ $this->assertEquals(13, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
- $this->assertEquals(11, $newRoot->getLeft());
- $this->assertEquals(14, $newRoot->getRight());
- }
+ $this->clusters('Root 2')->makeLastChildOf($newRoot);
- public function testMakeLastChildOfSwappingRootsWithSubtrees() {
- $newRoot = Cluster::create(array('name' => 'Root 3'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $this->clusters('Root 1')->makeLastChildOf($newRoot);
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 2')->getParentId());
- $this->assertTrue(Cluster::isValidNestedSet());
+ $this->assertEquals(12, $this->clusters('Root 2')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 2')->getRight());
- $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
+ $this->assertEquals(11, $newRoot->getLeft());
+ $this->assertEquals(14, $newRoot->getRight());
+ }
- $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
- $this->assertEquals(13, $this->clusters('Root 1')->getRight());
+ public function testMakeLastChildOfSwappingRootsWithSubtrees()
+ {
+ $newRoot = Cluster::create(array('name' => 'Root 3'));
- $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
- $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
- }
+ $this->clusters('Root 1')->makeLastChildOf($newRoot);
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testUnpersistedNodeCannotBeMoved() {
- $unpersisted = new Cluster(array('name' => 'Unpersisted'));
+ $this->assertTrue(Cluster::isValidNestedSet());
- $unpersisted->moveToRightOf($this->clusters('Root 1'));
- }
+ $this->assertEquals($newRoot->getKey(), $this->clusters('Root 1')->getParentId());
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testUnpersistedNodeCannotBeMadeChild() {
- $unpersisted = new Cluster(array('name' => 'Unpersisted'));
+ $this->assertEquals(4, $this->clusters('Root 1')->getLeft());
+ $this->assertEquals(13, $this->clusters('Root 1')->getRight());
- $unpersisted->makeChildOf($this->clusters('Root 1'));
- }
+ $this->assertEquals(8, $this->clusters('Child 2.1')->getLeft());
+ $this->assertEquals(9, $this->clusters('Child 2.1')->getRight());
+ }
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMovedToItself() {
- $node = $this->clusters('Child 1');
+ public function testUnpersistedNodeCannotBeMoved()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $node->moveToRightOf($node);
- }
+ $unpersisted = new Cluster(array('name' => 'Unpersisted'));
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMadeChildOfThemselves() {
- $node = $this->clusters('Child 1');
+ $unpersisted->moveToRightOf($this->clusters('Root 1'));
+ }
- $node->makeChildOf($node);
- }
+ public function testUnpersistedNodeCannotBeMadeChild()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- /**
- * @expectedException Baum\MoveNotPossibleException
- */
- public function testNodesCannotBeMovedToDescendantsOfThemselves() {
- $node = $this->clusters('Root 1');
+ $unpersisted = new Cluster(array('name' => 'Unpersisted'));
- $node->makeChildOf($this->clusters('Child 2.1'));
- }
+ $unpersisted->makeChildOf($this->clusters('Root 1'));
+ }
- public function testDepthIsUpdatedWhenMadeChild() {
- $a = Cluster::create(array('name' => 'A'));
- $b = Cluster::create(array('name' => 'B'));
- $c = Cluster::create(array('name' => 'C'));
- $d = Cluster::create(array('name' => 'D'));
+ public function testNodesCannotBeMovedToItself()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- // a > b > c > d
- $b->makeChildOf($a);
- $c->makeChildOf($b);
- $d->makeChildOf($c);
+ $node = $this->clusters('Child 1');
- $a->reload();
- $b->reload();
- $c->reload();
- $d->reload();
+ $node->moveToRightOf($node);
+ }
- $this->assertEquals(0, $a->getDepth());
- $this->assertEquals(1, $b->getDepth());
- $this->assertEquals(2, $c->getDepth());
- $this->assertEquals(3, $d->getDepth());
- }
+ public function testNodesCannotBeMadeChildOfThemselves()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- public function testDepthIsUpdatedOnDescendantsWhenParentMoves() {
- $a = Cluster::create(array('name' => 'A'));
- $b = Cluster::create(array('name' => 'B'));
- $c = Cluster::create(array('name' => 'C'));
- $d = Cluster::create(array('name' => 'D'));
+ $node = $this->clusters('Child 1');
- // a > b > c > d
- $b->makeChildOf($a);
- $c->makeChildOf($b);
- $d->makeChildOf($c);
+ $node->makeChildOf($node);
+ }
- $a->reload(); $b->reload(); $c->reload(); $d->reload();
+ public function testNodesCannotBeMovedToDescendantsOfThemselves()
+ {
+ $this->expectException(Baum\MoveNotPossibleException::class);
- $b->moveToRightOf($a);
+ $node = $this->clusters('Root 1');
- $a->reload(); $b->reload(); $c->reload(); $d->reload();
+ $node->makeChildOf($this->clusters('Child 2.1'));
+ }
- $this->assertEquals(0, $b->getDepth());
- $this->assertEquals(1, $c->getDepth());
- $this->assertEquals(2, $d->getDepth());
- }
+ public function testDepthIsUpdatedWhenMadeChild()
+ {
+ $a = Cluster::create(array('name' => 'A'));
+ $b = Cluster::create(array('name' => 'B'));
+ $c = Cluster::create(array('name' => 'C'));
+ $d = Cluster::create(array('name' => 'D'));
+
+ // a > b > c > d
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+ $d->makeChildOf($c);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $this->assertEquals(0, $a->getDepth());
+ $this->assertEquals(1, $b->getDepth());
+ $this->assertEquals(2, $c->getDepth());
+ $this->assertEquals(3, $d->getDepth());
+ }
+
+ public function testDepthIsUpdatedOnDescendantsWhenParentMoves()
+ {
+ $a = Cluster::create(array('name' => 'A'));
+ $b = Cluster::create(array('name' => 'B'));
+ $c = Cluster::create(array('name' => 'C'));
+ $d = Cluster::create(array('name' => 'D'));
+
+ // a > b > c > d
+ $b->makeChildOf($a);
+ $c->makeChildOf($b);
+ $d->makeChildOf($c);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $b->moveToRightOf($a);
+
+ $a->reload();
+ $b->reload();
+ $c->reload();
+ $d->reload();
+
+ $this->assertEquals(0, $b->getDepth());
+ $this->assertEquals(1, $c->getDepth());
+ $this->assertEquals(2, $d->getDepth());
+ }
}
diff --git a/tests/suite/ClusterTestCase.php b/tests/suite/ClusterTestCase.php
index 81038ad0..c17d8425 100644
--- a/tests/suite/ClusterTestCase.php
+++ b/tests/suite/ClusterTestCase.php
@@ -1,17 +1,21 @@
up();
- }
+ public static function setUpBeforeClass(): void
+ {
+ with(new ClusterMigrator)->up();
+ }
- public function setUp() {
- with(new ClusterSeeder)->run();
- }
+ public function setUp(): void
+ {
+ with(new ClusterSeeder)->run();
+ }
- protected function clusters($name, $className = 'Cluster') {
- return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
- }
+ protected function clusters($name, $className = 'Cluster')
+ {
+ return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
+ }
}
diff --git a/tests/suite/NodeModelExtensionsTest.php b/tests/suite/NodeModelExtensionsTest.php
index 0714d888..d5ff4066 100644
--- a/tests/suite/NodeModelExtensionsTest.php
+++ b/tests/suite/NodeModelExtensionsTest.php
@@ -4,179 +4,202 @@
use Illuminate\Database\Capsule\Manager as DB;
use PHPUnit\Framework\TestCase;
-class NodeModelExtensionsTest extends TestCase {
+class NodeModelExtensionsTest extends TestCase
+{
- public static function setUpBeforeClass() {
- with(new CategoryMigrator)->up();
- }
+ public static function setUpBeforeClass(): void
+ {
+ with(new CategoryMigrator)->up();
+ }
- public function setUp() {
- DB::table('categories')->delete();
- }
+ public function setUp(): void
+ {
+ DB::table('categories')->delete();
+ }
- protected function categories($name, $className = 'Category') {
- return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
- }
+ protected function categories($name, $className = 'Category')
+ {
+ return forward_static_call_array(array($className, 'where'), array('name', '=', $name))->first();
+ }
- public function tearDown() {
- m::close();
- }
+ public function tearDown(): void
+ {
+ m::close();
+ }
- public function testNewQueryReturnsEloquentBuilderWithExtendedQueryBuilder() {
- $query = with(new Category)->newQuery()->getQuery();
+ public function testNewQueryReturnsEloquentBuilderWithExtendedQueryBuilder()
+ {
+ $query = with(new Category)->newQuery()->getQuery();
- $this->assertInstanceOf('Baum\Extensions\Query\Builder', $query);
- }
+ $this->assertInstanceOf('Baum\Extensions\Query\Builder', $query);
+ }
- public function testNewCollectionReturnsCustomOne() {
- $this->assertInstanceOf('\Baum\Extensions\Eloquent\Collection', with(new Category)->newCollection());
- }
+ public function testNewCollectionReturnsCustomOne()
+ {
+ $this->assertInstanceOf('\Baum\Extensions\Eloquent\Collection', with(new Category)->newCollection());
+ }
- public function testGetObservableEventsIncludesMovingEvents() {
- $events = with(new Category)->getObservableEvents();
+ public function testGetObservableEventsIncludesMovingEvents()
+ {
+ $events = with(new Category)->getObservableEvents();
- $this->assertContains('moving', $events);
- $this->assertContains('moved', $events);
- }
+ $this->assertContains('moving', $events);
+ $this->assertContains('moved', $events);
+ }
- public function testAreSoftDeletesEnabled() {
- $this->assertFalse(with(new Category)->areSoftDeletesEnabled());
- $this->assertTrue(with(new SoftCategory)->areSoftDeletesEnabled());
- }
+ public function testAreSoftDeletesEnabled()
+ {
+ $this->assertFalse(with(new Category)->areSoftDeletesEnabled());
+ $this->assertTrue(with(new SoftCategory)->areSoftDeletesEnabled());
+ }
- public function testSoftDeletesEnabledStatic() {
- $this->assertFalse(Category::softDeletesEnabled());
- $this->assertTrue(SoftCategory::softDeletesEnabled());
- }
+ public function testSoftDeletesEnabledStatic()
+ {
+ $this->assertFalse(Category::softDeletesEnabled());
+ $this->assertTrue(SoftCategory::softDeletesEnabled());
+ }
- public function testMoving() {
- $dispatcher = Category::getEventDispatcher();
+ public function testMoving()
+ {
+ $dispatcher = Category::getEventDispatcher();
- Category::setEventDispatcher($events = m::mock('Illuminate\Contracts\Events\Dispatcher'));
+ Category::setEventDispatcher($events = m::mock('Illuminate\Contracts\Events\Dispatcher'));
- $closure = function() {};
+ $closure = function () {
+ };
- $events->shouldReceive('listen')->once()->with('eloquent.moving: ' . Category::class, $closure);
+ $events->shouldReceive('listen')->once()->with('eloquent.moving: ' . Category::class, $closure);
- Category::moving($closure);
+ Category::moving($closure);
- Category::unsetEventDispatcher();
+ Category::unsetEventDispatcher();
- Category::setEventDispatcher($dispatcher);
- }
+ Category::setEventDispatcher($dispatcher);
+ }
- public function testMoved() {
- $dispatcher = Category::getEventDispatcher();
+ public function testMoved()
+ {
+ $dispatcher = Category::getEventDispatcher();
- Category::setEventDispatcher($events = m::mock('Illuminate\Contracts\Events\Dispatcher'));
+ Category::setEventDispatcher($events = m::mock('Illuminate\Contracts\Events\Dispatcher'));
- $closure = function() {};
+ $closure = function () {
+ };
- $events->shouldReceive('listen')->once()->with('eloquent.moved: ' . Category::class, $closure);
+ $events->shouldReceive('listen')->once()->with('eloquent.moved: ' . Category::class, $closure);
- Category::moved($closure);
+ Category::moved($closure);
- Category::unsetEventDispatcher();
+ Category::unsetEventDispatcher();
- Category::setEventDispatcher($dispatcher);
- }
+ Category::setEventDispatcher($dispatcher);
+ }
- public function testReloadResetsChangesOnFreshNodes() {
- $new = new Category;
+ public function testReloadResetsChangesOnFreshNodes()
+ {
+ $new = new Category;
- $new->name = 'Some new category';
- $new->reload();
+ $new->name = 'Some new category';
+ $new->reload();
+
+ $this->assertNull($new->name);
+ }
+
+ public function testReloadResetsChangesOnPersistedNodes()
+ {
+ $node = Category::create(['name' => 'Some node']);
+
+ $node->name = 'A better node';
+ $node->lft = 10;
+ $node->reload();
+
+ $this->assertEquals($this->categories('Some node')->getAttributes(), $node->getAttributes());
+ }
- $this->assertNull($new->name);
- }
+ public function testReloadResetsChangesOnDeletedNodes()
+ {
+ $node = Category::create(['name' => 'Some node']);
+ $this->assertNotNull($node->getKey());
- public function testReloadResetsChangesOnPersistedNodes() {
- $node = Category::create(['name' => 'Some node']);
+ $node->delete();
+ $this->assertNull($this->categories('Some node'));
- $node->name = 'A better node';
- $node->lft = 10;
- $node->reload();
+ $node->name = 'A better node';
+ $node->reload();
- $this->assertEquals($this->categories('Some node')->getAttributes(), $node->getAttributes());
- }
+ $this->assertEquals('Some node', $node->name);
+ }
- public function testReloadResetsChangesOnDeletedNodes() {
- $node = Category::create(['name' => 'Some node']);
- $this->assertNotNull($node->getKey());
+ public function testReloadThrowsExceptionIfNodeCannotBeLocated()
+ {
+ $this->expectException(Illuminate\Database\Eloquent\ModelNotFoundException::class);
- $node->delete();
- $this->assertNull($this->categories('Some node'));
+ $node = Category::create(['name' => 'Some node']);
+ $this->assertNotNull($node->getKey());
- $node->name = 'A better node';
- $node->reload();
+ $node->delete();
+ $this->assertNull($this->categories('Some node'));
+ $this->assertFalse($node->exists);
- $this->assertEquals('Some node', $node->name);
- }
+ // Fake persisted state, reload & expect failure
+ $node->exists = true;
+ $node->reload();
+ }
- /**
- * @expectedException Illuminate\Database\Eloquent\ModelNotFoundException
- */
- public function testReloadThrowsExceptionIfNodeCannotBeLocated() {
- $node = Category::create(['name' => 'Some node']);
- $this->assertNotNull($node->getKey());
+ public function testNewNestedSetQueryUsesInternalBuilder()
+ {
+ $category = new Category;
+ $builder = $category->newNestedSetQuery();
+ $query = $builder->getQuery();
- $node->delete();
- $this->assertNull($this->categories('Some node'));
- $this->assertFalse($node->exists);
+ $this->assertInstanceOf('Baum\Extensions\Query\Builder', $query);
+ }
- // Fake persisted state, reload & expect failure
- $node->exists = true;
- $node->reload();
- }
+ public function testNewNestedSetQueryIsOrderedByDefault()
+ {
+ $category = new Category;
+ $builder = $category->newNestedSetQuery();
+ $query = $builder->getQuery();
- public function testNewNestedSetQueryUsesInternalBuilder() {
- $category = new Category;
- $builder = $category->newNestedSetQuery();
- $query = $builder->getQuery();
+ $this->assertEmpty($query->wheres);
+ $this->assertNotEmpty($query->orders);
+ $this->assertEquals($category->getLeftColumnName(), $category->getOrderColumnName());
+ $this->assertEquals($category->getQualifiedLeftColumnName(), $category->getQualifiedOrderColumnName());
+ $this->assertEquals($category->getQualifiedOrderColumnName(), $query->orders[0]['column']);
+ }
- $this->assertInstanceOf('Baum\Extensions\Query\Builder', $query);
- }
-
- public function testNewNestedSetQueryIsOrderedByDefault() {
- $category = new Category;
- $builder = $category->newNestedSetQuery();
- $query = $builder->getQuery();
-
- $this->assertEmpty($query->wheres);
- $this->assertNotEmpty($query->orders);
- $this->assertEquals($category->getLeftColumnName(), $category->getOrderColumnName());
- $this->assertEquals($category->getQualifiedLeftColumnName(), $category->getQualifiedOrderColumnName());
- $this->assertEquals($category->getQualifiedOrderColumnName(), $query->orders[0]['column']);
- }
-
- public function testNewNestedSetQueryIsOrderedByCustom() {
- $category = new OrderedCategory;
- $builder = $category->newNestedSetQuery();
- $query = $builder->getQuery();
-
- $this->assertEmpty($query->wheres);
- $this->assertNotEmpty($query->orders);
- $this->assertEquals('name', $category->getOrderColumnName());
- $this->assertEquals('categories.name', $category->getQualifiedOrderColumnName());
- $this->assertEquals($category->getQualifiedOrderColumnName(), $query->orders[0]['column']);
- }
-
- public function testNewNestedSetQueryIncludesScopedColumns() {
- $category = new Category;
- $simpleQuery = $category->newNestedSetQuery()->getQuery();
- $this->assertEmpty($simpleQuery->wheres);
-
- $scopedCategory = new ScopedCategory;
- $scopedQuery = $scopedCategory->newNestedSetQuery()->getQuery();
- $this->assertCount(1, $scopedQuery->wheres);
- $this->assertEquals($scopedCategory->getScopedColumns(), array_map(function($elem) {
- return $elem['column']; }, $scopedQuery->wheres));
-
- $multiScopedCategory = new MultiScopedCategory;
- $multiScopedQuery = $multiScopedCategory->newNestedSetQuery()->getQuery();
- $this->assertCount(2, $multiScopedQuery->wheres);
- $this->assertEquals($multiScopedCategory->getScopedColumns(), array_map(function($elem) {
- return $elem['column']; }, $multiScopedQuery->wheres));
- }
+ public function testNewNestedSetQueryIsOrderedByCustom()
+ {
+ $category = new OrderedCategory;
+ $builder = $category->newNestedSetQuery();
+ $query = $builder->getQuery();
+
+ $this->assertEmpty($query->wheres);
+ $this->assertNotEmpty($query->orders);
+ $this->assertEquals('name', $category->getOrderColumnName());
+ $this->assertEquals('categories.name', $category->getQualifiedOrderColumnName());
+ $this->assertEquals($category->getQualifiedOrderColumnName(), $query->orders[0]['column']);
+ }
+
+ public function testNewNestedSetQueryIncludesScopedColumns()
+ {
+ $category = new Category;
+ $simpleQuery = $category->newNestedSetQuery()->getQuery();
+ $this->assertEmpty($simpleQuery->wheres);
+
+ $scopedCategory = new ScopedCategory;
+ $scopedQuery = $scopedCategory->newNestedSetQuery()->getQuery();
+ $this->assertCount(1, $scopedQuery->wheres);
+ $this->assertEquals($scopedCategory->getScopedColumns(), array_map(function ($elem) {
+ return $elem['column'];
+ }, $scopedQuery->wheres));
+
+ $multiScopedCategory = new MultiScopedCategory;
+ $multiScopedQuery = $multiScopedCategory->newNestedSetQuery()->getQuery();
+ $this->assertCount(2, $multiScopedQuery->wheres);
+ $this->assertEquals($multiScopedCategory->getScopedColumns(), array_map(function ($elem) {
+ return $elem['column'];
+ }, $multiScopedQuery->wheres));
+ }
}
diff --git a/tests/suite/QueryBuilderExtensionTest.php b/tests/suite/QueryBuilderExtensionTest.php
index 06aa2b89..e130536f 100644
--- a/tests/suite/QueryBuilderExtensionTest.php
+++ b/tests/suite/QueryBuilderExtensionTest.php
@@ -7,58 +7,71 @@
use Baum\Extensions\Query\Builder;
use PHPUnit\Framework\TestCase;
-class QueryBuilderExtensionTest extends TestCase {
-
- public function tearDown() {
- m::close();
- }
-
- protected function getBuilder() {
- $grammar = new Grammar;
-
- $processor = m::mock(Processor::class);
-
- return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor);
- }
-
- public function testReorderBy() {
- $builder = $this->getBuilder();
-
- $builder->select('*')->from('users')->orderBy('email')->orderBy('age', 'desc')->reOrderBy('full_name', 'asc');
-
- $this->assertEquals('select * from "users" order by "full_name" asc', $builder->toSql());
- }
-
- public function testAggregatesRemoveOrderBy() {
- $builder = $this->getBuilder();
- $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
- $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; });
- $results = $builder->from('users')->orderBy('age', 'desc')->count();
- $this->assertEquals(1, $results);
-
- $builder = $this->getBuilder();
-
- $builder->getConnection()->shouldReceive('select')->once()->with('select exists(select * from "users") as "exists"', [], true)->andReturn([['exists' => 1]]);
- $results = $builder->from('users')->orderBy('age', 'desc')->exists();
- $this->assertTrue($results);
-
- $builder = $this->getBuilder();
- $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
- $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; });
- $results = $builder->from('users')->orderBy('age', 'desc')->max('id');
- $this->assertEquals(1, $results);
-
- $builder = $this->getBuilder();
- $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
- $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; });
- $results = $builder->from('users')->orderBy('age', 'desc')->min('id');
- $this->assertEquals(1, $results);
-
- $builder = $this->getBuilder();
- $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
- $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; });
- $results = $builder->from('users')->orderBy('age', 'desc')->sum('id');
- $this->assertEquals(1, $results);
- }
+class QueryBuilderExtensionTest extends TestCase
+{
+
+ public function tearDown(): void
+ {
+ m::close();
+ }
+
+ protected function getBuilder()
+ {
+ $grammar = new Grammar;
+
+ $processor = m::mock(Processor::class);
+
+ return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor);
+ }
+
+ public function testReorderBy()
+ {
+ $builder = $this->getBuilder();
+
+ $builder->select('*')->from('users')->orderBy('email')->orderBy('age', 'desc')->reOrderBy('full_name', 'asc');
+
+ $this->assertEquals('select * from "users" order by "full_name" asc', $builder->toSql());
+ }
+
+ public function testAggregatesRemoveOrderBy()
+ {
+ $builder = $this->getBuilder();
+ $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
+ $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) {
+ return $results;
+ });
+ $results = $builder->from('users')->orderBy('age', 'desc')->count();
+ $this->assertEquals(1, $results);
+
+ $builder = $this->getBuilder();
+
+ $builder->getConnection()->shouldReceive('select')->once()->with('select exists(select * from "users") as "exists"', [], true)->andReturn([['exists' => 1]]);
+ $results = $builder->from('users')->orderBy('age', 'desc')->exists();
+ $this->assertTrue($results);
+
+ $builder = $this->getBuilder();
+ $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
+ $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) {
+ return $results;
+ });
+ $results = $builder->from('users')->orderBy('age', 'desc')->max('id');
+ $this->assertEquals(1, $results);
+
+ $builder = $this->getBuilder();
+ $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
+ $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) {
+ return $results;
+ });
+ $results = $builder->from('users')->orderBy('age', 'desc')->min('id');
+ $this->assertEquals(1, $results);
+
+ $builder = $this->getBuilder();
+ $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]);
+ $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) {
+ return $results;
+ });
+ $results = $builder->from('users')->orderBy('age', 'desc')->sum('id');
+ $this->assertEquals(1, $results);
+ }
}
diff --git a/tests/suite/support.php b/tests/suite/support.php
index 54c7777f..ebb19cd4 100644
--- a/tests/suite/support.php
+++ b/tests/suite/support.php
@@ -1,59 +1,63 @@
0 )
- $current['children'] = hmap($children, $preserve);
+use Illuminate\Support\Arr;
+
+if (!function_exists('hmap')) {
+
+ /**
+ * Simple function which aids in converting the tree hierarchy into something
+ * more easily testable...
+ *
+ * @param array $nodes
+ * @return array
+ */
+ function hmap(array $nodes, $preserve = null)
+ {
+ $output = array();
+
+ foreach ($nodes as $node) {
+ if (is_null($preserve)) {
+ $output[$node['name']] = empty($node['children']) ? null : hmap($node['children']);
+ } else {
+ $preserve = is_string($preserve) ? array($preserve) : $preserve;
+
+ $current = Arr::only($node, $preserve);
+ if (array_key_exists('children', $node)) {
+ $children = $node['children'];
+
+ if (count($children) > 0)
+ $current['children'] = hmap($children, $preserve);
+ }
+
+ $output[] = $current;
+ }
}
- $output[] = $current;
- }
+ return $output;
}
- return $output;
- }
-
}
-if ( !function_exists('array_ints_keys') ) {
-
- /**
- * Cast provided keys's values into ints. This is to wrestle with PDO driver
- * inconsistencies.
- *
- * @param array $input
- * @param mixed $keys
- * @return array
- */
- function array_ints_keys(array $input, $keys='id') {
- $keys = is_string($keys) ? array($keys) : $keys;
-
- array_walk_recursive($input, function(&$value, $key) use ($keys) {
- if ( array_search($key, $keys) !== false )
- $value = (int) $value;
- });
-
- return $input;
- }
+if (!function_exists('array_ints_keys')) {
+
+ /**
+ * Cast provided keys's values into ints. This is to wrestle with PDO driver
+ * inconsistencies.
+ *
+ * @param array $input
+ * @param mixed $keys
+ * @return array
+ */
+ function array_ints_keys(array $input, $keys = 'id')
+ {
+ $keys = is_string($keys) ? array($keys) : $keys;
+
+ array_walk_recursive($input, function (&$value, $key) use ($keys) {
+ if (array_search($key, $keys) !== false)
+ $value = (int)$value;
+ });
+
+ return $input;
+ }
}