From d434174a968736dea273206e245073c808175166 Mon Sep 17 00:00:00 2001 From: zYne Date: Wed, 11 Jul 2007 14:39:15 +0000 Subject: [PATCH] added Search component, new record event listeners and some tests --- lib/Doctrine.php | 1 + lib/Doctrine/AuditLog.php | 4 +- lib/Doctrine/Configurable.php | 61 ++++- lib/Doctrine/Connection/UnitOfWork.php | 26 ++- lib/Doctrine/Import.php | 4 +- lib/Doctrine/Import/Builder.php | 86 +++++-- lib/Doctrine/Manager.php | 1 + lib/Doctrine/Query.php | 2 +- lib/Doctrine/Record.php | 4 +- lib/Doctrine/Record/Abstract.php | 6 +- lib/Doctrine/Record/Listener/Chain.php | 6 +- lib/Doctrine/Relation.php | 28 ++- lib/Doctrine/Search.php | 11 +- lib/Doctrine/Search/Analyzer/Standard.php | 259 +++++++++++++++++++++- lib/Doctrine/Search/Listener.php | 28 ++- lib/Doctrine/Search/Template.php | 4 +- tests/Import/BuilderTestCase.php | 44 ++++ tests/Query/HavingTestCase.php | 1 - tests/SearchTestCase.php | 117 ++++++++++ tests/run.php | 6 +- 20 files changed, 632 insertions(+), 67 deletions(-) create mode 100644 tests/Import/BuilderTestCase.php create mode 100644 tests/SearchTestCase.php diff --git a/lib/Doctrine.php b/lib/Doctrine.php index 32facca6f..5a2b323ce 100644 --- a/lib/Doctrine.php +++ b/lib/Doctrine.php @@ -193,6 +193,7 @@ final class Doctrine const ATTR_CACHE = 150; const ATTR_CACHE_LIFESPAN = 151; const ATTR_LOAD_REFERENCES = 153; + const ATTR_RECORD_LISTENER = 154; /** * LIMIT CONSTANTS diff --git a/lib/Doctrine/AuditLog.php b/lib/Doctrine/AuditLog.php index f6bab72b2..a6c286aae 100644 --- a/lib/Doctrine/AuditLog.php +++ b/lib/Doctrine/AuditLog.php @@ -33,8 +33,8 @@ class Doctrine_AuditLog { protected $_options = array( 'className' => '%CLASS%Version', - 'deleteTrigger' => '%TABLE%_ddt', - 'updateTrigger' => '%TABLE%_dut', + 'deleteTrigger' => '%TABLE%_ddtr', + 'updateTrigger' => '%TABLE%_dutr', 'versionTable' => '%TABLE%_dvt', 'versionColumn' => 'version', ); diff --git a/lib/Doctrine/Configurable.php b/lib/Doctrine/Configurable.php index 5228dba22..8c93e0fc3 100644 --- a/lib/Doctrine/Configurable.php +++ b/lib/Doctrine/Configurable.php @@ -97,12 +97,7 @@ abstract class Doctrine_Configurable extends Doctrine_Object } break; case Doctrine::ATTR_CREATE_TABLES: - $attribute = Doctrine::ATTR_EXPORT; - if ($value) { - $value = Doctrine::EXPORT_TABLES; - } else { - $value = Doctrine::EXPORT_NONE; - } + throw new Doctrine_Exception("ATTR_CREATE_TABLES has been deprecated. See exporting in the first chapter of the manual."); break; case Doctrine::ATTR_ACCESSORS: throw new Doctrine_Exception("Get / Set filtering is deprecated (slowed down Doctrine too much)."); @@ -141,6 +136,7 @@ abstract class Doctrine_Configurable extends Doctrine_Object case Doctrine::ATTR_EXPORT: case Doctrine::ATTR_DECIMAL_PLACES: case Doctrine::ATTR_LOAD_REFERENCES: + case Doctrine::ATTR_RECORD_LISTENER: break; case Doctrine::ATTR_SEQCOL_NAME: @@ -187,13 +183,60 @@ abstract class Doctrine_Configurable extends Doctrine_Object { return $this->setListener($listener); } + /** + * addRecordListener + * + * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener + * @return mixed this object + */ + public function addRecordListener($listener, $name = null) + { + if ( ! isset($this->attributes[Doctrine::ATTR_RECORD_LISTENER]) || + ! ($this->attributes[Doctrine::ATTR_LISTENER] instanceof Doctrine_Record_Listener_Chain)) { + + $this->attributes[Doctrine::ATTR_RECORD_LISTENER] = new Doctrine_Record_Listener_Chain(); + } + $this->attributes[Doctrine::ATTR_RECORD_LISTENER]->add($listener, $name); + + return $this; + } + /** + * getListener + * + * @return Doctrine_EventListener_Interface|Doctrine_Overloadable + */ + public function getRecordListener() + { + if ( ! isset($this->attributes[Doctrine::ATTR_RECORD_LISTENER])) { + if (isset($this->parent)) { + return $this->parent->getRecordListener(); + } + return null; + } + return $this->attributes[Doctrine::ATTR_RECORD_LISTENER]; + } + /** + * setListener + * + * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener + * @return Doctrine_Configurable this object + */ + public function setRecordListener($listener) + { + if ( ! ($listener instanceof Doctrine_Record_Listener_Interface) + && ! ($listener instanceof Doctrine_Overloadable) + ) { + throw new Doctrine_Exception("Couldn't set eventlistener. Record listeners should implement either Doctrine_Record_Listener_Interface or Doctrine_Overloadable"); + } + $this->attributes[Doctrine::ATTR_RECORD_LISTENER] = $listener; + + return $this; + } /** * addListener * * @param Doctrine_EventListener_Interface|Doctrine_Overloadable $listener - * @return Doctrine_Connection_Informix|Doctrine_Connection_Mssql|Doctrine_Connection_Oracle| - * Doctrine_Connection_Db2|Doctrine_Connection_Firebird|Doctrine_Connection_Common| - * Doctrine_Manager|Doctrine_Connection|Doctrine_Table + * @return mixed this object */ public function addListener($listener, $name = null) { diff --git a/lib/Doctrine/Connection/UnitOfWork.php b/lib/Doctrine/Connection/UnitOfWork.php index bdbd6a9ae..1b8982ba9 100644 --- a/lib/Doctrine/Connection/UnitOfWork.php +++ b/lib/Doctrine/Connection/UnitOfWork.php @@ -181,10 +181,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module */ public function save(Doctrine_Record $record) { - $event = new Doctrine_Event($this, Doctrine_Event::RECORD_SAVE); + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE); $record->preSave($event); + $record->getTable()->getRecordListener()->preSave($event); + if ( ! $event->skipOperation) { switch ($record->state()) { case Doctrine_Record::STATE_TDIRTY: @@ -201,6 +203,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module } } + $record->getTable()->getRecordListener()->postSave($event); + $record->postSave($event); } /** @@ -218,10 +222,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module } $this->conn->beginTransaction(); - $event = new Doctrine_Event($this, Doctrine_Event::RECORD_DELETE); + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE); $record->preDelete($event); + $record->getTable()->getRecordListener()->preDelete($event); + $record->state(Doctrine_Record::STATE_LOCKED); $this->deleteComposites($record); @@ -233,6 +239,9 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module $record->state(Doctrine_Record::STATE_TCLEAN); } + + $record->getTable()->getRecordListener()->postDelete($event); + $record->postDelete($event); $this->conn->commit(); @@ -382,10 +391,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module */ public function update(Doctrine_Record $record) { - $event = new Doctrine_Event($this, Doctrine_Event::RECORD_UPDATE); + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE); $record->preUpdate($event); + $record->getTable()->getRecordListener()->preUpdate($event); + if ( ! $event->skipOperation) { $array = $record->getPrepared(); @@ -430,6 +441,9 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module $record->assignIdentifier(true); } + + $record->getTable()->getRecordListener()->postUpdate($event); + $record->postUpdate($event); return true; @@ -443,10 +457,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module public function insert(Doctrine_Record $record) { // listen the onPreInsert event - $event = new Doctrine_Event($this, Doctrine_Event::RECORD_INSERT); + $event = new Doctrine_Event($record, Doctrine_Event::RECORD_INSERT); $record->preInsert($event); + $record->getTable()->getRecordListener()->preInsert($event); + if ( ! $event->skipOperation) { $array = $record->getPrepared(); @@ -488,6 +504,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module } $record->getTable()->addRecord($record); + $record->getTable()->getRecordListener()->postInsert($event); + $record->postInsert($event); return true; diff --git a/lib/Doctrine/Import.php b/lib/Doctrine/Import.php index 9cd0874c3..b6771088b 100644 --- a/lib/Doctrine/Import.php +++ b/lib/Doctrine/Import.php @@ -190,7 +190,9 @@ class Doctrine_Import extends Doctrine_Connection_Module $classes = array(); foreach ($this->listTables() as $table) { - $builder->buildRecord($table, $this->listTableColumns($table)); + $builder->buildRecord(array('tableName' => $table, + 'className' => Doctrine::classify($table)), + $this->listTableColumns($table)); $classes[] = Doctrine::classify($table); } diff --git a/lib/Doctrine/Import/Builder.php b/lib/Doctrine/Import/Builder.php index 3f8da7c6d..8848dd999 100644 --- a/lib/Doctrine/Import/Builder.php +++ b/lib/Doctrine/Import/Builder.php @@ -87,10 +87,8 @@ class Doctrine_Import_Builder } self::$tpl =<< END; } @@ -114,9 +111,9 @@ END; * @param string $table * @param array $tableColumns */ - public function buildDefinition($table, $tableColumns) + public function buildColumnDefinition(array $tableColumns) { - $columns = array(0 => str_repeat(' ', 8) . '$this->setTableName(\''. $table .'\');'); + $columns = array(); $i = 1; foreach ($tableColumns as $name => $column) { @@ -158,7 +155,7 @@ END; } $columns[$i] .= ');'; - if ($i < (count($table) - 1)) { + if ($i < (count($tableColumns) - 1)) { $columns[$i] .= PHP_EOL; } $i++; @@ -166,13 +163,69 @@ END; return implode("\n", $columns); } - - public function buildRecord($table, $tableColumns, $className='', $fileName='') + public function buildRelationDefinition(array $relations) { - if (empty($className)) { - $className = Doctrine::classify($table); + $ret = array(); + $i = 0; + foreach ($relations as $name => $relation) { + $alias = (isset($relation['alias']) && $relation['alias'] !== $name) ? ' as ' . $relation['alias'] : ''; + + if ( ! isset($relation['type'])) { + $relation['type'] = Doctrine_Relation::ONE; + } + + if ($relation['type'] === Doctrine_Relation::ONE || + $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) { + $ret[$i] = ' $this->hasOne(\'' . $name . $alias . '\''; + } else { + $ret[$i] = ' $this->hasMany(\'' . $name . $alias . '\''; + } + $a = array(); + + if (isset($relation['deferred']) && $relation['deferred']) { + $a[] = '\'default\' => ' . var_export($relation['deferred'], true); + } + if (isset($relation['local']) && $relation['local']) { + $a[] = '\'local\' => ' . var_export($relation['local'], true); + } + if (isset($relation['foreign']) && $relation['foreign']) { + $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true); + } + if (isset($relation['onDelete']) && $relation['onDelete']) { + $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true); + } + if (isset($relation['onUpdate']) && $relation['onUpdate']) { + $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true); + } + if ( ! empty($a)) { + $ret[$i] .= ', ' . 'array('; + $length = strlen($ret[$i]); + $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')'; + } + $ret[$i] .= ');'; + $i++; } - + return implode("\n", $ret); + } + + + public function buildDefinition(array $options, array $columns, array $relations = array()) + { + if ( ! isset($options['className'])) { + throw new Doctrine_Import_Builder_Exception('Missing class name.'); + } + + //$opt = array(0 => str_repeat(' ', 8) . '$this->setTableName(\''. $table .'\');'); + + $content = sprintf(self::$tpl, $options['className'], + $this->buildColumnDefinition($columns), + $this->buildRelationDefinition($relations)); + + return $content; + } + + public function buildRecord($table, $columns, $relations) + { if (empty($fileName)) { if (empty($this->path)) { $errMsg = 'No build target directory set.'; @@ -187,13 +240,10 @@ END; $fileName = $this->path . DIRECTORY_SEPARATOR . $className . $this->suffix; } - - $created = date('l dS \of F Y h:i:s A'); - - $content = sprintf(self::$tpl, $created, $className, - $this->buildDefinition($table, $tableColumns)); - $bytes = file_put_contents($fileName, $content); + $content = $this->buildDefinition($options, $columns, $relations); + + $bytes = file_put_contents($fileName, ' null, Doctrine::ATTR_LOAD_REFERENCES => true, Doctrine::ATTR_LISTENER => new Doctrine_EventListener(), + Doctrine::ATTR_RECORD_LISTENER => new Doctrine_Record_Listener(), Doctrine::ATTR_LOCKMODE => 1, Doctrine::ATTR_VLD => false, Doctrine::ATTR_AUTO_LENGTH_VLD => true, diff --git a/lib/Doctrine/Query.php b/lib/Doctrine/Query.php index 48c42d606..b7c38ad40 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -1238,7 +1238,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable } } else { - + $queryPart = $join . $foreignSql . ' ON ' . $this->_conn->quoteIdentifier($localAlias . '.' . $relation->getLocal()) diff --git a/lib/Doctrine/Record.php b/lib/Doctrine/Record.php index 0de37e02d..b3003d453 100644 --- a/lib/Doctrine/Record.php +++ b/lib/Doctrine/Record.php @@ -1379,9 +1379,9 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count * * @param string $template */ - public function loadTemplate($template) + public function loadTemplate($template, $options = array()) { - $tpl = new $template(); + $tpl = new $template($options); $tpl->setTable($this->_table); $tpl->setUp(); $tpl->setTableDefinition(); diff --git a/lib/Doctrine/Record/Abstract.php b/lib/Doctrine/Record/Abstract.php index 03e19cc50..3638dbbf6 100644 --- a/lib/Doctrine/Record/Abstract.php +++ b/lib/Doctrine/Record/Abstract.php @@ -40,7 +40,7 @@ abstract class Doctrine_Record_Abstract extends Doctrine_Access */ public function addListener($listener, $name = null) { - $this->_table->addListener($listener, $name = null); + $this->_table->addRecordListener($listener, $name = null); return $this; } @@ -51,7 +51,7 @@ abstract class Doctrine_Record_Abstract extends Doctrine_Access */ public function getListener() { - return $this->_table->getListener(); + return $this->_table->getRecordListener(); } /** * setListener @@ -61,7 +61,7 @@ abstract class Doctrine_Record_Abstract extends Doctrine_Access */ public function setListener($listener) { - $this->_table->setListener($listener); + $this->_table->setRecordListener($listener); return $this; } diff --git a/lib/Doctrine/Record/Listener/Chain.php b/lib/Doctrine/Record/Listener/Chain.php index a5e3fdcc3..e6910d365 100644 --- a/lib/Doctrine/Record/Listener/Chain.php +++ b/lib/Doctrine/Record/Listener/Chain.php @@ -33,7 +33,7 @@ Doctrine::autoload('Doctrine_Access'); * @since 1.0 * @version $Revision$ */ -class Doctrine_Record_Listener_Chain extends Doctrine_Access implements Doctrine_EventListener_Interface +class Doctrine_Record_Listener_Chain extends Doctrine_Access implements Doctrine_Record_Listener_Interface { /** * @var array $listeners an array containing all listeners @@ -49,10 +49,10 @@ class Doctrine_Record_Listener_Chain extends Doctrine_Access implements Doctrine */ public function add($listener, $name = null) { - if ( ! ($listener instanceof Doctrine_EventListener_Interface) && + if ( ! ($listener instanceof Doctrine_Record_Listener_Interface) && ! ($listener instanceof Doctrine_Overloadable)) { - throw new Doctrine_EventListener_Exception("Couldn't add eventlistener. EventListeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable"); + throw new Doctrine_EventListener_Exception("Couldn't add eventlistener. Record listeners should implement either Doctrine_EventListener_Interface or Doctrine_Overloadable"); } if ($name === null) { $this->_listeners[] = $listener; diff --git a/lib/Doctrine/Relation.php b/lib/Doctrine/Relation.php index b24832ad0..6c582f8ec 100644 --- a/lib/Doctrine/Relation.php +++ b/lib/Doctrine/Relation.php @@ -30,7 +30,7 @@ * @version $Revision$ * @author Konsta Vesterinen */ -abstract class Doctrine_Relation +abstract class Doctrine_Relation implements ArrayAccess { /** * RELATION CONSTANTS @@ -157,6 +157,32 @@ abstract class Doctrine_Relation { return $this->definition['equal']; } + + public function offsetExists($offset) + { + return isset($this->definition[$offset]); + } + + public function offsetGet($offset) + { + if (isset($this->definition[$offset])) { + return $this->definition[$offset]; + } + + return null; + } + + public function offsetSet($offset, $value) + { + if (isset($this->definition[$offset])) { + $this->definition[$offset] = $value; + } + } + + public function offsetUnset($offset) + { + $this->definition[$offset] = false; + } /** * toArray * diff --git a/lib/Doctrine/Search.php b/lib/Doctrine/Search.php index 23779f5cc..55dfb5e58 100644 --- a/lib/Doctrine/Search.php +++ b/lib/Doctrine/Search.php @@ -37,17 +37,26 @@ class Doctrine_Search public function __construct(array $options) { $this->_options = array_merge($this->_options, $options); + + if ( ! isset($this->_options['analyzer'])) { + $this->_options['analyzer'] = new Doctrine_Search_Analyzer_Standard(); + } } public function getOption($option) { if (isset($this->_options[$option])) { - return $this->_option[$option]; + return $this->_options[$option]; } return null; } + public function analyze($text) + { + return $this->_options['analyzer']->analyze($text); + } + public function setOption($option, $value) { $this->_options[$option] = $value; diff --git a/lib/Doctrine/Search/Analyzer/Standard.php b/lib/Doctrine/Search/Analyzer/Standard.php index efbb345fd..67db87537 100644 --- a/lib/Doctrine/Search/Analyzer/Standard.php +++ b/lib/Doctrine/Search/Analyzer/Standard.php @@ -32,14 +32,261 @@ */ class Doctrine_Search_Analyzer_Standard implements Doctrine_Search_Analyzer_Interface { + protected static $_stopwords = array( + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + 'a', + 'about', + 'after', + 'all', + 'almost', + 'along', + 'also', + 'amp', + 'an', + 'and', + 'another', + 'any', + 'are', + 'area', + 'around', + 'as', + 'at', + 'available', + 'back', + 'be', + 'because', + 'been', + 'being', + 'best', + 'better', + 'big', + 'bit', + 'both', + 'but', + 'by', + 'c', + 'came', + 'can', + 'capable', + 'control', + 'could', + 'course', + 'd', + 'dan', + 'day', + 'decided', + 'did', + 'didn', + 'different', + 'div', + 'do', + 'doesn', + 'don', + 'down', + 'drive', + 'e', + 'each', + 'easily', + 'easy', + 'edition', + 'end', + 'enough', + 'even', + 'every', + 'example', + 'few', + 'find', + 'first', + 'for', + 'found', + 'from', + 'get', + 'go', + 'going', + 'good', + 'got', + 'gt', + 'had', + 'hard', + 'has', + 'have', + 'he', + 'her', + 'here', + 'how', + 'i', + 'if', + 'in', + 'into', + 'is', + 'isn', + 'it', + 'just', + 'know', + 'last', + 'left', + 'li', + 'like', + 'little', + 'll', + 'long', + 'look', + 'lot', + 'lt', + 'm', + 'made', + 'make', + 'many', + 'mb', + 'me', + 'menu', + 'might', + 'mm', + 'more', + 'most', + 'much', + 'my', + 'name', + 'nbsp', + 'need', + 'new', + 'no', + 'not', + 'now', + 'number', + 'of', + 'off', + 'old', + 'on', + 'one', + 'only', + 'or', + 'original', + 'other', + 'our', + 'out', + 'over', + 'part', + 'place', + 'point', + 'pretty', + 'probably', + 'problem', + 'put', + 'quite', + 'quot', + 'r', + 're', + 'really', + 'results', + 'right', + 's', + 'same', + 'saw', + 'see', + 'set', + 'several', + 'she', + 'sherree', + 'should', + 'since', + 'size', + 'small', + 'so', + 'some', + 'something', + 'special', + 'still', + 'stuff', + 'such', + 'sure', + 'system', + 't', + 'take', + 'than', + 'that', + 'the', + 'their', + 'them', + 'then', + 'there', + 'these', + 'they', + 'thing', + 'things', + 'think', + 'this', + 'those', + 'though', + 'through', + 'time', + 'to', + 'today', + 'together', + 'too', + 'took', + 'two', + 'up', + 'us', + 'use', + 'used', + 'using', + 've', + 'very', + 'want', + 'was', + 'way', + 'we', + 'well', + 'went', + 'were', + 'what', + 'when', + 'where', + 'which', + 'while', + 'white', + 'who', + 'will', + 'with', + 'would', + 'you', + 'your', + ); + public function analyze($text) { - $text = explode(' ', $text); - - foreach ($text as $i => $term) { - $text[$i] = strtolower(trim($term)); - } + $text = preg_replace('/[.()&#!,]/', ' ', $text); + $text = str_replace(' ', ' ', $text); - return $text; + $terms = explode(' ', $text); + + $ret = array(); + if ( ! empty($terms)) { + foreach ($terms as $i => $term) { + if (empty($term)) { + continue; + } + $lower = strtolower(trim($term)); + + if (in_array($lower, self::$_stopwords)) { + continue; + } + + $pos = strpos($text, $term); + $ret[$pos] = $lower; + } + } + return $ret; } } diff --git a/lib/Doctrine/Search/Listener.php b/lib/Doctrine/Search/Listener.php index e475b965c..01d194f65 100644 --- a/lib/Doctrine/Search/Listener.php +++ b/lib/Doctrine/Search/Listener.php @@ -47,21 +47,27 @@ class Doctrine_Search_Listener extends Doctrine_Record_Listener { } - - public function preInsert(Doctrine_Event $event) - { - - } - public function postInsert(Doctrine_Event $event) { $fields = $this->_search->getOption('fields'); - + $class = $this->_search->getOption('className'); + $record = $event->getInvoker(); + $name = $record->getTable()->getComponentName(); + foreach ($fields as $field) { - $terms = $this->_search->analyze($field); - - foreach ($terms as $term) { - + $data = $record->get($field); + + $terms = $this->_search->analyze($data); + + foreach ($terms as $pos => $term) { + $index = new $class(); + + $index->keyword = $term; + $index->position = $pos; + $index->field = $field; + $index->$name = $record; + + $index->save(); } } } diff --git a/lib/Doctrine/Search/Template.php b/lib/Doctrine/Search/Template.php index 38421ffbe..10749ef7d 100644 --- a/lib/Doctrine/Search/Template.php +++ b/lib/Doctrine/Search/Template.php @@ -48,10 +48,10 @@ class Doctrine_Search_Template extends Doctrine_Template $this->_search->setOption('className', $name); foreach ((array) $id as $column) { - $foreign[] = strtolower($name . '_' . $column); + $foreign[] = strtolower($this->_table->getComponentName() . '_' . $column); } - $foreign = (count($foreign) > 1) ? array_keys($foreign) : key($foreign); + $foreign = (count($foreign) > 1) ? $foreign : current($foreign); $this->hasMany($name, array('local' => $id, 'foreign' => $foreign)); diff --git a/tests/Import/BuilderTestCase.php b/tests/Import/BuilderTestCase.php new file mode 100644 index 000000000..39383d2e5 --- /dev/null +++ b/tests/Import/BuilderTestCase.php @@ -0,0 +1,44 @@ +. + */ + +/** + * Doctrine_Import_Builder_TestCase + * + * @package Doctrine + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision$ + */ +class Doctrine_Import_Builder_TestCase extends Doctrine_UnitTestCase +{ + public function testBuildingOfRecord() + { + $table = $this->conn->getTable('Phonenumber'); + + $builder = new Doctrine_Import_Builder(); + + $rel = $builder->buildRelationDefinition($table->getRelations()); + + } +} diff --git a/tests/Query/HavingTestCase.php b/tests/Query/HavingTestCase.php index 0aa7ea6f1..a7809a54a 100644 --- a/tests/Query/HavingTestCase.php +++ b/tests/Query/HavingTestCase.php @@ -54,7 +54,6 @@ class Doctrine_Query_Having_TestCase extends Doctrine_UnitTestCase $q = new Doctrine_Query(); $q->parseQuery("SELECT CONCAT(u.name, u.loginname) name FROM User u LEFT JOIN u.Phonenumber p HAVING name = 'xx'"); - } } diff --git a/tests/SearchTestCase.php b/tests/SearchTestCase.php new file mode 100644 index 000000000..33e569f57 --- /dev/null +++ b/tests/SearchTestCase.php @@ -0,0 +1,117 @@ +. + */ + +/** + * Doctrine_Search_TestCase + * + * @package Doctrine + * @author Konsta Vesterinen + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision$ + */ +class Doctrine_Search_TestCase extends Doctrine_UnitTestCase +{ + public function prepareTables() + { + $this->tables = array('SearchTest', 'SearchTestIndex'); + + parent::prepareTables(); + } + public function prepareData() + { } + public function testBuildingOfSearchRecordDefinition() + { + $e = new SearchTest(); + + $this->assertTrue($e->SearchTestIndex instanceof Doctrine_Collection); + + $rel = $e->getTable()->getRelation('SearchTestIndex'); + + $this->assertIdentical($rel->getLocal(), 'id'); + $this->assertIdentical($rel->getForeign(), 'searchtest_id'); + } + public function testSavingEntriesUpdatesIndex() + { + $e = new SearchTest(); + + $e->title = 'Once there was an ORM framework'; + $e->content = 'There are many ORM frameworks, but nevertheless we decided to create one.'; + + $e->save(); + } + public function testQuerying() + { + $q = new Doctrine_Query(); + + $q->select('t.title') + ->from('SearchTest t') + ->innerJoin('t.SearchTestIndex i') + ->where('i.keyword = ?'); + + $array = $q->execute(array('orm'), Doctrine_Hydrate::HYDRATE_ARRAY); + + $this->assertEqual($array[0]['title'], 'Once there was an ORM framework'); + } + public function testQueryingReturnsEmptyArrayForStopKeyword() + { + $q = new Doctrine_Query(); + + $q->select('t.title') + ->from('SearchTest t') + ->innerJoin('t.SearchTestIndex i') + ->where('i.keyword = ?'); + + $array = $q->execute(array('was'), Doctrine_Hydrate::HYDRATE_ARRAY); + + $this->assertEqual(count($array), 0); + } + public function testQueryingReturnsEmptyArrayForUnknownKeyword() + { + $q = new Doctrine_Query(); + + $q->select('t.title') + ->from('SearchTest t') + ->innerJoin('t.SearchTestIndex i') + ->where('i.keyword = ?'); + + $array = $q->execute(array('someunknownword'), Doctrine_Hydrate::HYDRATE_ARRAY); + + $this->assertEqual(count($array), 0); + } +} +class SearchTest extends Doctrine_Record +{ + public function setTableDefinition() + { + $this->hasColumn('title', 'string', 100); + $this->hasColumn('content', 'string'); + } + public function setUp() + { + $options = array('generateFiles' => false, + 'fields' => array('title', 'content')); + + $this->loadTemplate('Doctrine_Search_Template', $options); + } +} diff --git a/tests/run.php b/tests/run.php index 2728d14b0..0a4c4d5cc 100644 --- a/tests/run.php +++ b/tests/run.php @@ -70,7 +70,7 @@ $test = new GroupTest('Doctrine Framework Unit Tests'); $test->addTestCase(new Doctrine_Ticket330_TestCase()); */ - +/** */ // Connection drivers (not yet fully tested) $test->addTestCase(new Doctrine_Connection_Pgsql_TestCase()); $test->addTestCase(new Doctrine_Connection_Oracle_TestCase()); @@ -322,9 +322,11 @@ $test->addTestCase(new Doctrine_Cache_Sqlite_TestCase()); $test->addTestCase(new Doctrine_Record_SaveBlankRecord_TestCase()); - $test->addTestCase(new Doctrine_Template_TestCase()); +$test->addTestCase(new Doctrine_Import_Builder_TestCase()); + +$test->addTestCase(new Doctrine_Search_TestCase()); //$test->addTestCase(new Doctrine_IntegrityAction_TestCase()); //$test->addTestCase(new Doctrine_AuditLog_TestCase());