diff --git a/extensions/data/source/Couchbase.php b/extensions/data/source/Couchbase.php index b7f6f2a..ff7693c 100644 --- a/extensions/data/source/Couchbase.php +++ b/extensions/data/source/Couchbase.php @@ -10,6 +10,8 @@ use Couchbase as Couch; use lithium\core\NetworkException; +use lithium\core\Environment; +use lithium\util\Inflector; /** * A data source adapter which allows you to connect to the Couchbase database engine. @@ -64,6 +66,13 @@ class Couchbase extends \lithium\data\Source { */ protected $_autoConfig = array('schema', 'classes' => 'merge'); + /** + * List of views indexed by design document + * + * @var array + */ + protected $_views = array(); + /** * */ @@ -109,6 +118,17 @@ public static function enabled($feature = null) { * their respective properties in `Model`. */ public function configureClass($class) { + $pieces = explode('\\', $class); + $model = array_pop($pieces); + $source = Inflector::tableize($model); + $prefix = (Environment::get() == 'production') ? '' : 'dev_'; + $this->_views[$source] = json_decode($this->getDesignDoc("{$prefix}{$source}"), true); + $this->_views[$source] = $this->_views[$source]['views']; + if ($this->_views[$source]) { + foreach ($this->_views[$source] as $k => $v) { + $class::finder($k, array('conditions' => array('view' => $k))); + } + } return array('schema' => array(), 'meta' => array('key' => 'id', 'locked' => false)); } @@ -231,16 +251,40 @@ public function read($query, array $options = array()) { )))); $key = $model::key(); - if (empty($conditions[$key])) { - return null; + $viewName = ''; + $prefix = (Environment::get() == 'production') ? '' : 'dev_'; + + if (!$conditions) { + $viewName = 'all'; } + + if (!empty($conditions['view'])) { + $viewName = $conditions['view']; + } + + $viewOptions = array('stale' => false); + if (isset($conditions['key'])) { + $viewOptions['key'] = $conditions['key']; + } + + if ($viewName) { + $view = $self->connection->view($prefix . $source, $viewName, $viewOptions); + $records = array(); + if (!empty($view['rows'])) { + foreach ($view['rows'] as $r) { + $records[$r['id']] = $r['value']; + } + } + return $self->item($model, $records, array('class' => 'set', 'exists' => true)); + } + $conditions += array('callback' => null, 'cas' => null); $key = "{$source}:{$conditions[$key]}"; $data = $self->connection->get($key, $conditions['callback'], $conditions['cas']); if ($result = json_decode($data, true)) { $config = compact('query') + array('exists' => true); - return $this->item($model, array('data' => $result), $config); + return $self->item($model, array('data' => $result), $config); } return false; }); diff --git a/tests/integration/data/CrudExtendedTest.php b/tests/integration/data/CrudExtendedTest.php index 7c3c0b4..d10ea4f 100644 --- a/tests/integration/data/CrudExtendedTest.php +++ b/tests/integration/data/CrudExtendedTest.php @@ -52,6 +52,25 @@ public function skip() { * Creating the test database */ public function setUp() { + $views = array( + 'views' => + array( + 'all' => + array( + 'map' => + "function (doc, meta) { if(doc._source == 'companies') { emit(meta.id, + doc) }}", + ), + 'by_active' => + array( + 'map' => + "function (doc, meta) { if(doc._source == 'companies') { emit(doc.active, doc + ) }}", + ), + ), + ); + $result = $this->db->setDesignDoc('dev_companies', json_encode($views)); + $this->assertTrue($result); //$this->db->connection->put($this->_database); } @@ -108,4 +127,40 @@ public function testCreateIdCustomKey() { $this->assertEqual('something', $custom->my_key); $this->assertTrue($custom->delete()); } + + public function testFindAll() { + $company = Companies::create($this->data[0]); + $this->assertTrue($company->save()); + $companies = Companies::find('all'); + $data = $companies->data(); + $this->assertEqual(1, count($data)); + $record = array_shift($data); + $this->assertEqual('Marine Store', $record['name']); + $this->assertEqual('1', $record['active']); + $this->assertEqual('companies', $record['_source']); + $this->assertTrue($company->delete()); + } + + public function testFindByView() { + $company1 = Companies::create($this->data[0]); + $company1->save(); + $company2 = Companies::create($this->data[1]); + $company2->save(); + + $company = Companies::find($company1->id); + $data = $company->data(); + $this->assertEqual('Marine Store', $data['name']); + + $companies = Companies::find('by_active'); + $this->assertEqual(2, count($companies->data())); + + $companies = Companies::find('all', array('conditions' => array('view' => 'by_active'))); + $this->assertEqual(2, count($companies->data())); + + $companies = Companies::find('by_active', array('conditions' => array('key' => false))); + $this->assertEqual(1, count($companies->data())); + + $company1->delete(); + $company2->delete(); + } } \ No newline at end of file