Skip to content

Commit

Permalink
add HABTM association handle, write tests, see #18
Browse files Browse the repository at this point in the history
  • Loading branch information
imsamurai committed Oct 29, 2013
1 parent 67e251c commit 4ae1a29
Show file tree
Hide file tree
Showing 12 changed files with 474 additions and 0 deletions.
58 changes: 58 additions & 0 deletions Model/Datasource/HttpSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,64 @@ public function getQueryCache(array $request) {
return false;
}

/**
* Queries associations. Used to fetch results on recursive models.
*
* @param Model $model Primary Model object
* @param Model $linkModel Linked model that
* @param string $type Association type, one of the model association types ie. hasMany
* @param string $association
* @param array $assocData
* @param array $queryData
* @param boolean $external Whether or not the association query is on an external datasource.
* @param array $resultSet Existing results
* @param integer $recursive Number of levels of association
* @param array $stack
* @return mixed
* @throws CakeException when results cannot be created.
*/
public function queryAssociation(Model $model, &$linkModel, $type, $association, $assocData, &$queryData, $external, &$resultSet, $recursive, $stack) {
$assocQuery = $this->_scrubQueryData($assocData);
$query = $this->_scrubQueryData($queryData);

foreach ($resultSet as &$result) {
switch($type) {
case 'hasAndBelongsToMany': {
$JoinModel = ClassRegistry::init($assocData['with']);
$assocQuery['fields'] = array($assocData['associationForeignKey']);
$assocQuery['conditions'][$assocData['foreignKey']] = $result[$model->alias][$model->primaryKey];
$joinData = $JoinModel->find('all', array_filter($assocQuery));
$query['conditions'][$linkModel->primaryKey] = Hash::extract($joinData, "{n}.{$JoinModel->alias}.{$assocData['associationForeignKey']}");
$assocResults = $linkModel->find('all', $query);

$result[$association] = array();
foreach ($assocResults as $assocResult) {
$result[$association][] = $assocResult[$linkModel->alias];
}

break;
}

default: throw new NotImplementedException("Sorry, but type $type is not implemented yet, check out https://github.com/imsamurai/cakephp-httpsource-datasource/issues/18");
}
}
}

/**
* Private helper method to remove query metadata in given data array.
*
* @param array $data
* @return array
*/
protected function _scrubQueryData($data) {
static $base = null;
if ($base === null) {
$base = array_fill_keys(array('conditions', 'fields', 'joins', 'order', 'limit', 'offset', 'group'), array());
$base['callbacks'] = null;
}
return (array) $data + $base;
}

/**
* Format result to match Cake conventions
*
Expand Down
44 changes: 44 additions & 0 deletions Plugin/TestHttpSource/Config/TestHttpSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 5:54:32 PM
*
*/
$config['TestHttpSource']['config_version'] = 2;

$CF = HttpSourceConfigFactory::instance();
$Config = $CF->config();

$Config
->add(
$CF->endpoint()
->id(1)
->methodRead()
->table('default')
->path('/imsamurai/cakephp-httpsource-datasource/master/Test/Data/default.json')
->result($CF->result()->map(function($result) {
return array($result);
}))
)
->add(
$CF->endpoint()
->id(2)
->methodRead()
->table('documents')
->path('/imsamurai/cakephp-httpsource-datasource/master/Test/Data/documents:id.json')
->addCondition($CF->condition()->name('id')->map(function($v) {
return implode('.', $v);
}))
->result($CF->result()->map(function($result) {
return $result;
}))
)

;

$config['TestHttpSource']['config'] = $Config;


$config['TestHttpSource']['cache_name'] = false;
31 changes: 31 additions & 0 deletions Plugin/TestHttpSource/Model/Datasource/Http/TestHttpSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 5:44:49 PM
*
*/

App::uses('HttpSource', 'HttpSource.Model/Datasource');
App::uses('TestHttpSourceConnection', 'TestHttpSource.Model/Datasource');

class TestHttpSource extends HttpSource {

/**
* The description of this data source
*
* @var string
*/
public $description = 'Test DataSource';

/**
* {@inheritdoc}
*
* @param array $config
* @param HttpSourceConnection $Connection
*/
public function __construct($config = array(), HttpSourceConnection $Connection = null) {
parent::__construct($config, new TestHttpSourceConnection($config));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 5:45:06 PM
*
*/
App::uses('HttpSourceConnection', 'HttpSource.Model/Datasource');

class TestHttpSourceConnection extends HttpSourceConnection {

/**
* Constructor
*
* @param array $config
* @param HttpSocket $Transport
*/
public function __construct(array $config = array(), HttpSocket $Transport = null) {
parent::__construct($config, $Transport);

$this->setDecoder(array('text/plain'), function(HttpSocketResponse $Response) {
return json_decode((string) $Response, true);
}, false);
}

}
38 changes: 38 additions & 0 deletions Plugin/TestHttpSource/Model/TestHttpSourceModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 6:02:17 PM
* Format: http://book.cakephp.org/2.0/en/models.html
*/

App::uses('HttpSourceModel', 'HttpSource.Model');

/**
* TestHttpSourceModel Model
*/
class TestHttpSourceModel extends HttpSourceModel {

/**
* {@inheritdoc}
*
* @var string
*/
public $name = 'TestHttpSourceModel';

/**
* {@inheritdoc}
*
* @var string
*/
public $useTable = 'default';

/**
* {@inheritdoc}
*
* @var string
*/
public $useDbConfig = 'http';

}
23 changes: 23 additions & 0 deletions Test/Case/AllHttpSourceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: 29.10.2013
* Time: 21:50:00
*/
class AllHttpSourceTest extends PHPUnit_Framework_TestSuite {

/**
* Suite define the tests for this suite
*
* @return void
*/
public static function suite() {
$suite = new CakeTestSuite('All Http Source Tests');

$path = App::pluginPath('HttpSource') . 'Test' . DS . 'Case' . DS;
$suite->addTestDirectoryRecursive($path);
return $suite;
}

}
34 changes: 34 additions & 0 deletions Test/Case/Model/BasicsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 6:06:31 PM
* Format: http://book.cakephp.org/2.0/en/development/testing.html
*/
App::uses('HttpSourceTest', 'HttpSource.Test');

/**
* BasicsTest
*/
class BasicsTest extends HttpSourceTest {

public function testRead() {
$this->HttpModel->setSource('default');
$result = $this->HttpModel->field('name');

$this->assertSame('imsamurai', $result);
}

public function testRead2() {
$this->HttpModel->setSource('documents');
$result = $this->HttpModel->find('all', array(
'conditions' => array(
'id' => array(1,2)
)
));

$this->assertCount(2, $result);
}

}
49 changes: 49 additions & 0 deletions Test/Case/Model/ToDboAssociationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 5:28:22 PM
* Format: http://book.cakephp.org/2.0/en/development/testing.html
*/

App::uses('HttpSourceTest', 'HttpSource.Test');

/**
* HttpSourceToDboAssociationTest
*/
class ToDboAssociationTest extends HttpSourceTest {

/**
* User model
*
* @var User
*/
public $User = null;
/**
* {@inheritdoc}
*/
public function setUp(){
parent::setUp();
$this->User = new User();
}

/**
* {@inheritdoc}
*
* @var array
*/
public $fixtures = array(
'plugin.HttpSource.User',
'plugin.HttpSource.UsersDocument'
);

public function testHABTM() {
$this->User->Documents->useDbConfig = 'testHttpSource';
$results = $this->User->find('all', array('recursive' => 3));
debug($results);
foreach ($results as $result) {
$this->assertNotEmpty($result['Documents']);
}
}
}
31 changes: 31 additions & 0 deletions Test/Data/models.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* Author: imsamurai <[email protected]>
* Date: Oct 29, 2013
* Time: 9:18:11 PM
* Format: http://book.cakephp.org/2.0/en/views.html
*
*/
App::uses('HttpSourceModel', 'HttpSource.Model');

class Document extends HttpSourceModel {

public $name = 'Document';
public $useTable = 'documents';

}

class User extends AppModel {

public $name = 'User';
public $useTable = 'users';
public $useDbConfig = 'test';
public $hasAndBelongsToMany = array(
'Documents' => array(
'joinTable' => 'users_documents',
'dependent' => false
)
);

}
32 changes: 32 additions & 0 deletions Test/Fixture/UserFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* User Fixture
*/
class UserFixture extends CakeTestFixture {

public $useDbConfig = 'test';
public $table = 'users';

/**
* Fields
*
* @var array
*/
public $fields = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'length' => 20, 'key' => 'primary'),
'name' => array('type' => 'string', 'null' => false, 'length' => 100),
'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'MyISAM')
);

/**
* Records
*
* @var array
*/
public $records = array(
array('id' => 1, 'name' => 'dan'),
array('id' => 2, 'name' => 'robert')
);

}
Loading

0 comments on commit 4ae1a29

Please sign in to comment.