Skip to content

Commit

Permalink
Implementing smart loading of entity class for table
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Oct 14, 2013
1 parent 3103225 commit 0751ba3
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 12 deletions.
29 changes: 29 additions & 0 deletions Cake/ORM/Error/MissingEntityException.php
@@ -0,0 +1,29 @@
<?php
/**
* MissingModelException class

This comment has been minimized.

Copy link
@markstory

markstory Oct 15, 2013

Member

This text is wrong, and could be removed really.

*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2013, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2013, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @since CakePHP(tm) v 3.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace Cake\ORM\Error;

use Cake\Error\Exception;

/**
* Exception raised when an Entity could not be found.
*
*/
class MissingEntityException extends Exception {

protected $_messageTemplate = 'Entity class %s could not be found.';

}
9 changes: 4 additions & 5 deletions Cake/ORM/Error/MissingTableClassException.php
Expand Up @@ -10,8 +10,7 @@
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/2.0/en/development/testing.html
* @copyright Copyright 2005-2013, Cake Software Foundation, Inc. (http://cakefoundation.org)

This comment has been minimized.

Copy link
@dereuromark

dereuromark Oct 14, 2013

Member

Shoudn't all those be Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) to avoid the yearly merging issue?

* @since CakePHP(tm) v 3.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
Expand All @@ -20,11 +19,11 @@
use Cake\Error\Exception;

/**
* Exception raised when a Model could not be found.
* Exception raised when an Entity could not be found.
*
*/
class MissingTableClassException extends Exception {
class MissingEntityException extends Exception {

protected $_messageTemplate = 'Table class %s could not be found.';
protected $_messageTemplate = 'Entity class %s could not be found.';

}
28 changes: 25 additions & 3 deletions Cake/ORM/Table.php
Expand Up @@ -125,8 +125,7 @@ class Table {
*
* @var string
*/
protected $_entityClass = '\Cake\ORM\Entity';

protected $_entityClass;

/**
* Initializes a new instance
Expand Down Expand Up @@ -388,12 +387,35 @@ public function displayField($key = null) {
* a new one
*
* @param string $name the name of the class to use
* @throws \Cake\ORM\Error\MissingEntityException when the entity class cannot be found
* @return string
*/
public function entityClass($name = null) {
if ($name === null && !$this->_entityClass) {
$default = '\Cake\ORM\Entity';
$self = get_called_class();
$parts = explode('\\', $self);

if ($self === __CLASS__ || count($parts) < 3) {
return $this->_entityClass = $default;
}

$alias = substr(array_pop($parts), 0, -5);
$name = implode('\\', array_slice($parts, 0, -1)) . '\Entity\\' . $alias;
if (!class_exists($name)) {
return $this->_entityClass = $default;
}
}

if ($name !== null) {
$this->_entityClass = $name;
$class = App::classname($name, 'Model\Entity');
$this->_entityClass = $class;
}

if (!$this->_entityClass) {
throw new Error\MissingEntityException([$name]);
}

return $this->_entityClass;
}

Expand Down
13 changes: 13 additions & 0 deletions Cake/Test/TestApp/Model/Entity/Article.php
@@ -0,0 +1,13 @@
<?php

namespace TestApp\Model\Entity;

use Cake\ORM\Entity;

/**
* Tests entity class used for asserting correct loading
*
*/
class Article extends Entity {

}
21 changes: 21 additions & 0 deletions Cake/Test/TestApp/Model/Repository/ArticleTable.php
@@ -0,0 +1,21 @@
<?php
/**
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
* Copyright 2005-2013, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice
*
* @since CakePHP(tm) v 3.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
namespace TestApp\Model\Repository;

use Cake\ORM\Table;

/**
* Article class
*
*/
class ArticleTable extends Table {
}
8 changes: 4 additions & 4 deletions Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -1261,7 +1261,7 @@ public function testHydrateCustomObject() {
$class = $this->getMockClass('\Cake\ORM\Entity', ['fakeMethod']);
$table = Table::build('article', [
'table' => 'articles',
'entityClass' => $class
'entityClass' => '\\' . $class
]);
$query = new Query($this->connection, $table);
$results = $query->select()->hydrate(true)->execute()->toArray();
Expand Down Expand Up @@ -1292,11 +1292,11 @@ public function testHydrateWithHasManyCustomEntity() {
$articleEntity = $this->getMockClass('\Cake\ORM\Entity', ['foo']);
$table = Table::build('author', [
'connection' => $this->connection,
'entityClass' => $authorEntity
'entityClass' => '\\' . $authorEntity
]);
Table::build('article', [
'connection' => $this->connection,
'entityClass' => $articleEntity
'entityClass' => '\\' . $articleEntity
]);
$table->hasMany('article', [
'property' => 'articles',
Expand Down Expand Up @@ -1337,7 +1337,7 @@ public function testHydrateBelongsToCustomEntity() {
$table = Table::build('article', ['table' => 'articles']);
Table::build('author', [
'connection' => $this->connection,
'entityClass' => $authorEntity
'entityClass' => '\\' . $authorEntity
]);
$table->belongsTo('author');

Expand Down
70 changes: 70 additions & 0 deletions Cake/Test/TestCase/ORM/TableTest.php
Expand Up @@ -783,4 +783,74 @@ public function testFindListHydrated() {
$this->assertSame($expected, $query->toArray());
}

public function testEntityClassDefault() {
$table = new Table();
$this->assertEquals('\Cake\ORM\Entity', $table->entityClass());
}

/**
* Tests that using a simple string for entityClass will try to
* load the class from the App namespace
*
* @return void
*/
public function testRepositoryClassInAPP() {
$class = $this->getMockClass('\Cake\ORM\Entity');
class_alias($class, 'App\Model\Entity\TestUser');
$table = new Table();
$this->assertEquals('App\Model\Entity\TestUser', $table->entityClass('TestUser'));
}

/**
* Tests that using a simple string for entityClass will try to
* load the class from the Plugin namespace when using plugin notation
*
* @return void
*/
public function testRepositoryClassInPlugin() {
$class = $this->getMockClass('\Cake\ORM\Entity');
class_alias($class, 'MyPlugin\Model\Entity\SuperUser');
$table = new Table();
$this->assertEquals(
'MyPlugin\Model\Entity\SuperUser',
$table->entityClass('MyPlugin.SuperUser')
);
}

/**
* Tests that using a simple string for entityClass will throw an exception
* when the class does not exist in the namespace
*
* @expectedException Cake\ORM\Error\MissingEntityException
* @expectedExceptionMessage Entity class FooUser could not be found.
* @return void
*/
public function testRepositoryClassNonExisting() {
$table = new Table;
$this->assertFalse($table->entityClass('FooUser'));
}

/**
* Tests getting the entityClass based on conventions for the entity
* namespace
*
* @return void
*/
public function testRepositoryClassConventionForAPP() {
$table = new \TestApp\Model\Repository\ArticleTable;
$this->assertEquals('TestApp\Model\Entity\Article', $table->entityClass());
}

/**
* Tests setting a entity class object using the setter method
*
* @return void
*/
public function testSetEntityClass() {
$table = new Table;
$class = '\\' . $this->getMockClass('\Cake\ORM\Entity');
$table->entityClass($class);
$this->assertEquals($class, $table->entityClass());
}

}

0 comments on commit 0751ba3

Please sign in to comment.