diff --git a/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php b/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php index 3c7b54c23897..783dc88e2c33 100755 --- a/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php @@ -5,11 +5,12 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Concerns\ComparesWithModels; use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels; class BelongsTo extends Relation { - use SupportsDefaultModels; + use ComparesWithModels, SupportsDefaultModels; /** * The child model instance of the relation. @@ -340,6 +341,16 @@ public function getQualifiedForeignKeyName() return $this->child->qualifyColumn($this->foreignKey); } + /** + * Get the key value of the child's foreign key. + * + * @return mixed + */ + public function getParentKey() + { + return $this->child->{$this->foreignKey}; + } + /** * Get the associated key of the relationship. * @@ -360,6 +371,17 @@ public function getQualifiedOwnerKeyName() return $this->related->qualifyColumn($this->ownerKey); } + /** + * Get the value of the model's associated key. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return mixed + */ + protected function getRelatedKeyFrom(Model $model) + { + return $model->{$this->ownerKey}; + } + /** * Get the name of the relationship. * diff --git a/src/Illuminate/Database/Eloquent/Relations/Concerns/ComparesWithModels.php b/src/Illuminate/Database/Eloquent/Relations/Concerns/ComparesWithModels.php new file mode 100644 index 000000000000..b58a451e1615 --- /dev/null +++ b/src/Illuminate/Database/Eloquent/Relations/Concerns/ComparesWithModels.php @@ -0,0 +1,68 @@ +compareKeys($this->getParentKey(), $this->getRelatedKeyFrom($model)) && + $this->related->getTable() === $model->getTable() && + $this->related->getConnectionName() === $model->getConnectionName(); + } + + /** + * Determine if the model is not the related instance of the relationship. + * + * @param \Illuminate\Database\Eloquent\Model|null $model + * @return bool + */ + public function isNot($model) + { + return ! $this->is($model); + } + + /** + * Get the value of the parent model's key. + * + * @return mixed + */ + abstract public function getParentKey(); + + /** + * Get the value of the model's related key. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return mixed + */ + abstract protected function getRelatedKeyFrom(Model $model); + + /** + * Compare the parent key with the related key. + * + * @param mixed $parentKey + * @param mixed $relatedKey + * @return bool + */ + protected function compareKeys($parentKey, $relatedKey) + { + if (empty($parentKey) || empty($relatedKey)) { + return false; + } + + if (is_int($parentKey) || is_int($relatedKey)) { + return (int) $parentKey === (int) $relatedKey; + } + + return $parentKey === $relatedKey; + } +} diff --git a/src/Illuminate/Database/Eloquent/Relations/HasOne.php b/src/Illuminate/Database/Eloquent/Relations/HasOne.php index 1d9e008fd231..6320e3aa0bf6 100755 --- a/src/Illuminate/Database/Eloquent/Relations/HasOne.php +++ b/src/Illuminate/Database/Eloquent/Relations/HasOne.php @@ -4,11 +4,12 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Concerns\ComparesWithModels; use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels; class HasOne extends HasOneOrMany { - use SupportsDefaultModels; + use ComparesWithModels, SupportsDefaultModels; /** * Get the results of the relationship. @@ -65,4 +66,15 @@ public function newRelatedInstanceFor(Model $parent) $this->getForeignKeyName(), $parent->{$this->localKey} ); } + + /** + * Get the value of the model's foreign key. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return mixed + */ + protected function getRelatedKeyFrom(Model $model) + { + return $model->getAttribute($this->getForeignKeyName()); + } } diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphOne.php b/src/Illuminate/Database/Eloquent/Relations/MorphOne.php index 5f8da14f1f46..704fa4b5fdc1 100755 --- a/src/Illuminate/Database/Eloquent/Relations/MorphOne.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphOne.php @@ -4,11 +4,12 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Concerns\ComparesWithModels; use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels; class MorphOne extends MorphOneOrMany { - use SupportsDefaultModels; + use ComparesWithModels, SupportsDefaultModels; /** * Get the results of the relationship. @@ -65,4 +66,15 @@ public function newRelatedInstanceFor(Model $parent) ->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey}) ->setAttribute($this->getMorphType(), $this->morphClass); } + + /** + * Get the value of the model's foreign key. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return mixed + */ + protected function getRelatedKeyFrom(Model $model) + { + return $model->getAttribute($this->getForeignKeyName()); + } } diff --git a/tests/Database/DatabaseEloquentBelongsToTest.php b/tests/Database/DatabaseEloquentBelongsToTest.php index 18faec7c18e9..54256d73c6c1 100755 --- a/tests/Database/DatabaseEloquentBelongsToTest.php +++ b/tests/Database/DatabaseEloquentBelongsToTest.php @@ -181,6 +181,169 @@ public function testDefaultEagerConstraintsWhenNotIncrementing() $relation->addEagerConstraints($models); } + public function testIsNotNull() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is(null)); + } + + public function testIsModel() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerParentKey() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return an integer + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('1'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerRelatedKey() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return a string + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('1'); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerKeys() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return an integer + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsNotModelWithNullParentKey() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return null + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(null); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithNullRelatedKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(null); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value.two'); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherTable() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('table.two'); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherConnection() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation.two'); + + $this->assertFalse($relation->is($model)); + } + protected function getRelation($parent = null, $keyType = 'int') { $this->builder = m::mock(Builder::class); diff --git a/tests/Database/DatabaseEloquentHasOneTest.php b/tests/Database/DatabaseEloquentHasOneTest.php index d854d0a85158..e0c26123d25f 100755 --- a/tests/Database/DatabaseEloquentHasOneTest.php +++ b/tests/Database/DatabaseEloquentHasOneTest.php @@ -196,6 +196,106 @@ public function testRelationCountQueryCanBeBuilt() $relation->getRelationExistenceCountQuery($builder, $builder); } + public function testIsNotNull() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->never(); + $this->related->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is(null)); + } + + public function testIsModel() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->once()->andReturn('table'); + $this->related->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithStringRelatedKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->once()->andReturn('table'); + $this->related->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('1'); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsNotModelWithNullRelatedKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->never(); + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(null); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherRelatedKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->never(); + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(2); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherTable() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->once()->andReturn('table'); + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table.two'); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherConnection() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getTable')->once()->andReturn('table'); + $this->related->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection.two'); + + $this->assertFalse($relation->is($model)); + } + protected function getRelation() { $this->builder = m::mock(Builder::class); diff --git a/tests/Database/DatabaseEloquentMorphTest.php b/tests/Database/DatabaseEloquentMorphTest.php index 226cf4f60bf5..cf7c8352a4de 100755 --- a/tests/Database/DatabaseEloquentMorphTest.php +++ b/tests/Database/DatabaseEloquentMorphTest.php @@ -253,6 +253,106 @@ public function testCreateFunctionOnNamespacedMorph() $this->assertEquals($created, $relation->create(['name' => 'taylor'])); } + public function testIsNotNull() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->never(); + $relation->getRelated()->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is(null)); + } + + public function testIsModel() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->once()->andReturn('table'); + $relation->getRelated()->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithStringRelatedKey() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->once()->andReturn('table'); + $relation->getRelated()->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn('1'); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsNotModelWithNullRelatedKey() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->never(); + $relation->getRelated()->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn(null); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherRelatedKey() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->never(); + $relation->getRelated()->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn(2); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherTable() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->once()->andReturn('table'); + $relation->getRelated()->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table.two'); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherConnection() + { + $relation = $this->getOneRelation(); + + $relation->getRelated()->shouldReceive('getTable')->once()->andReturn('table'); + $relation->getRelated()->shouldReceive('getConnectionName')->once()->andReturn('connection'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('morph_id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('table'); + $model->shouldReceive('getConnectionName')->once()->andReturn('connection.two'); + + $this->assertFalse($relation->is($model)); + } + protected function getOneRelation() { $builder = m::mock(Builder::class); diff --git a/tests/Database/DatabaseEloquentMorphToTest.php b/tests/Database/DatabaseEloquentMorphToTest.php index 5f9049b4a4a5..67c584e0fe4e 100644 --- a/tests/Database/DatabaseEloquentMorphToTest.php +++ b/tests/Database/DatabaseEloquentMorphToTest.php @@ -150,6 +150,169 @@ public function testDissociateMethodDeletesUnsetsKeyAndTypeOnModel() $relation->dissociate(); } + public function testIsNotNull() + { + $relation = $this->getRelation(); + + $relation->getRelated()->shouldReceive('getTable')->never(); + $relation->getRelated()->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is(null)); + } + + public function testIsModel() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerParentKey() + { + $parent = m::mock(Model::class); + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return an integer + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('1'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerRelatedKey() + { + $parent = m::mock(Model::class); + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return a string + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('1'); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsModelWithIntegerKeys() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return an integer + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(1); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(1); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $this->assertTrue($relation->is($model)); + } + + public function testIsNotModelWithNullParentKey() + { + $parent = m::mock(Model::class); + + // when addConstraints is called we need to return the foreign value + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); + // when getParentKey is called we want to return null + + $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn(null); + + $relation = $this->getRelation($parent); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithNullRelatedKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn(null); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherKey() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value.two'); + $model->shouldReceive('getTable')->never(); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherTable() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->never(); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('table.two'); + $model->shouldReceive('getConnectionName')->never(); + + $this->assertFalse($relation->is($model)); + } + + public function testIsNotModelWithAnotherConnection() + { + $relation = $this->getRelation(); + + $this->related->shouldReceive('getConnectionName')->once()->andReturn('relation'); + + $model = m::mock(Model::class); + $model->shouldReceive('getAttribute')->once()->with('id')->andReturn('foreign.value'); + $model->shouldReceive('getTable')->once()->andReturn('relation'); + $model->shouldReceive('getConnectionName')->once()->andReturn('relation.two'); + + $this->assertFalse($relation->is($model)); + } + protected function getRelationAssociate($parent) { $builder = m::mock(Builder::class); diff --git a/tests/Integration/Database/EloquentBelongsToTest.php b/tests/Integration/Database/EloquentBelongsToTest.php index 1cc52a79e51f..e04e39deba50 100644 --- a/tests/Integration/Database/EloquentBelongsToTest.php +++ b/tests/Integration/Database/EloquentBelongsToTest.php @@ -74,6 +74,64 @@ public function testAssociateWithIdUnsetsLoadedRelation() $this->assertEquals($child->id, $child->parent_id); $this->assertFalse($child->relationLoaded('parent')); } + + public function testParentIsNotNull() + { + $child = User::has('parent')->first(); + $parent = null; + + $this->assertFalse($child->parent()->is($parent)); + $this->assertTrue($child->parent()->isNot($parent)); + } + + public function testParentIsModel() + { + $child = User::has('parent')->first(); + $parent = User::doesntHave('parent')->first(); + + $this->assertTrue($child->parent()->is($parent)); + $this->assertFalse($child->parent()->isNot($parent)); + } + + public function testParentIsNotAnotherModel() + { + $child = User::has('parent')->first(); + $parent = new User(); + $parent->id = 3; + + $this->assertFalse($child->parent()->is($parent)); + $this->assertTrue($child->parent()->isNot($parent)); + } + + public function testNullParentIsNotModel() + { + $child = User::has('parent')->first(); + $child->parent()->dissociate(); + $parent = User::doesntHave('parent')->first(); + + $this->assertFalse($child->parent()->is($parent)); + $this->assertTrue($child->parent()->isNot($parent)); + } + + public function testParentIsNotModelWithAnotherTable() + { + $child = User::has('parent')->first(); + $parent = User::doesntHave('parent')->first(); + $parent->setTable('foo'); + + $this->assertFalse($child->parent()->is($parent)); + $this->assertTrue($child->parent()->isNot($parent)); + } + + public function testParentIsNotModelWithAnotherConnection() + { + $child = User::has('parent')->first(); + $parent = User::doesntHave('parent')->first(); + $parent->setConnection('foo'); + + $this->assertFalse($child->parent()->is($parent)); + $this->assertTrue($child->parent()->isNot($parent)); + } } class User extends Model diff --git a/tests/Integration/Database/EloquentHasOneIsTest.php b/tests/Integration/Database/EloquentHasOneIsTest.php new file mode 100644 index 000000000000..74f76e56ffe6 --- /dev/null +++ b/tests/Integration/Database/EloquentHasOneIsTest.php @@ -0,0 +1,103 @@ +increments('id'); + $table->timestamps(); + }); + + Schema::create('attachments', function (Blueprint $table) { + $table->increments('id'); + $table->unsignedInteger('post_id')->nullable(); + }); + + $post = Post::create(); + $post->attachment()->create(); + } + + public function testChildIsNotNull() + { + $parent = Post::first(); + $child = null; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsModel() + { + $parent = Post::first(); + $child = Attachment::first(); + + $this->assertTrue($parent->attachment()->is($child)); + $this->assertFalse($parent->attachment()->isNot($child)); + } + + public function testChildIsNotAnotherModel() + { + $parent = Post::first(); + $child = new Attachment(); + $child->id = 2; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testNullChildIsNotModel() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->post_id = null; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsNotModelWithAnotherTable() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->setTable('foo'); + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsNotModelWithAnotherConnection() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->setConnection('foo'); + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } +} + +class Attachment extends Model +{ + public $timestamps = false; +} + +class Post extends Model +{ + public function attachment() + { + return $this->hasOne(Attachment::class); + } +} diff --git a/tests/Integration/Database/EloquentMorphOneIsTest.php b/tests/Integration/Database/EloquentMorphOneIsTest.php new file mode 100644 index 000000000000..7d670264aac2 --- /dev/null +++ b/tests/Integration/Database/EloquentMorphOneIsTest.php @@ -0,0 +1,105 @@ +increments('id'); + $table->timestamps(); + }); + + Schema::create('attachments', function (Blueprint $table) { + $table->increments('id'); + $table->string('attachable_type')->nullable(); + $table->integer('attachable_id')->nullable(); + }); + + $post = Post::create(); + $post->attachment()->create(); + } + + public function testChildIsNotNull() + { + $parent = Post::first(); + $child = null; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsModel() + { + $parent = Post::first(); + $child = Attachment::first(); + + $this->assertTrue($parent->attachment()->is($child)); + $this->assertFalse($parent->attachment()->isNot($child)); + } + + public function testChildIsNotAnotherModel() + { + $parent = Post::first(); + $child = new Attachment(); + $child->id = 2; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testNullChildIsNotModel() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->attachable_type = null; + $child->attachable_id = null; + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsNotModelWithAnotherTable() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->setTable('foo'); + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } + + public function testChildIsNotModelWithAnotherConnection() + { + $parent = Post::first(); + $child = Attachment::first(); + $child->setConnection('foo'); + + $this->assertFalse($parent->attachment()->is($child)); + $this->assertTrue($parent->attachment()->isNot($child)); + } +} + +class Attachment extends Model +{ + public $timestamps = false; +} + +class Post extends Model +{ + public function attachment() + { + return $this->morphOne(Attachment::class, 'attachable'); + } +} diff --git a/tests/Integration/Database/EloquentMorphToIsTest.php b/tests/Integration/Database/EloquentMorphToIsTest.php new file mode 100644 index 000000000000..dbc33ed48c73 --- /dev/null +++ b/tests/Integration/Database/EloquentMorphToIsTest.php @@ -0,0 +1,106 @@ +increments('id'); + $table->timestamps(); + }); + + Schema::create('comments', function (Blueprint $table) { + $table->increments('id'); + $table->string('commentable_type'); + $table->integer('commentable_id'); + }); + + $post = Post::create(); + (new Comment)->commentable()->associate($post)->save(); + } + + public function testParentIsNotNull() + { + $child = Comment::first(); + $parent = null; + + $this->assertFalse($child->commentable()->is($parent)); + $this->assertTrue($child->commentable()->isNot($parent)); + } + + public function testParentIsModel() + { + $child = Comment::first(); + $parent = Post::first(); + + $this->assertTrue($child->commentable()->is($parent)); + $this->assertFalse($child->commentable()->isNot($parent)); + } + + public function testParentIsNotAnotherModel() + { + $child = Comment::first(); + $parent = new Post(); + $parent->id = 2; + + $this->assertFalse($child->commentable()->is($parent)); + $this->assertTrue($child->commentable()->isNot($parent)); + } + + public function testNullParentIsNotModel() + { + $child = Comment::first(); + $child->commentable()->dissociate(); + $parent = Post::first(); + + $this->assertFalse($child->commentable()->is($parent)); + $this->assertTrue($child->commentable()->isNot($parent)); + } + + public function testParentIsNotModelWithAnotherTable() + { + $child = Comment::first(); + $parent = Post::first(); + $parent->setTable('foo'); + + $this->assertFalse($child->commentable()->is($parent)); + $this->assertTrue($child->commentable()->isNot($parent)); + } + + public function testParentIsNotModelWithAnotherConnection() + { + $child = Comment::first(); + $parent = Post::first(); + $parent->setConnection('foo'); + + $this->assertFalse($child->commentable()->is($parent)); + $this->assertTrue($child->commentable()->isNot($parent)); + } +} + +class Comment extends Model +{ + public $timestamps = false; + + public function commentable() + { + return $this->morphTo(); + } +} + +class Post extends Model +{ + // +}