Coverage for Doctrine_Search

Back to coverage report

1 <?php
2 /*
3  *  $Id$
4  *
5  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16  *
17  * This software consists of voluntary contributions made by many individuals
18  * and is licensed under the LGPL. For more information, see
19  * <http://www.phpdoctrine.com>.
20  */
21
22 /**
23  * Doctrine_Search
24  *
25  * @package     Doctrine
26  * @subpackage  Search
27  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
28  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
29  * @version     $Revision$
30  * @link        www.phpdoctrine.com
31  * @since       1.0
32  */
33 class Doctrine_Search extends Doctrine_Plugin
34 {
35     protected $_options = array('generateFiles' => false,
36                                 'className'     => '%CLASS%Index',
37                                 'generatePath'  => false,
38                                 'batchUpdates'  => false,
39                                 'pluginTable'   => false);
40
41     
42     public function __construct(array $options)
43     {
44         $this->_options = array_merge($this->_options, $options);
45         
46         if ( ! isset($this->_options['analyzer'])) {
47             $this->_options['analyzer'] = new Doctrine_Search_Analyzer_Standard();
48         }
49     }
50
51     
52     public function analyze($text)
53     {
54         return $this->_options['analyzer']->analyze($text);
55     }
56
57     /**
58      * updateIndex
59      * updates the index
60      *
61      * @param Doctrine_Record $record
62      * @return integer
63      */
64     public function updateIndex(Doctrine_Record $record) 
65     {
66         $fields = $this->getOption('fields');
67         $class  = $this->getOption('className');
68         $name   = $record->getTable()->getComponentName();
69
70         if ($this->_options['batchUpdates'] === true) {
71
72             $conn = $record->getTable()->getConnection();
73             
74             $index = new $class(); 
75             foreach ($record->identifier() as $id => $value) {
76                 $index->$id = $value;
77             }
78             
79             $index->save();
80         } else {
81             foreach ($fields as $field) {
82                 $data  = $record->get($field);
83     
84                 $terms = $this->analyze($data);
85
86                 foreach ($terms as $pos => $term) {
87                     $index = new $class();
88     
89                     $index->keyword = $term;
90                     $index->position = $pos;
91                     $index->field = $field;
92                     $index->$name = $record;
93
94                     $index->save();
95                 }
96             }
97         }
98     }
99
100     public function processPending($limit = null, $offset = null)
101     {
102      $conn      = $this->_options['ownerTable']->getConnection();
103         $tableName = $this->_options['ownerTable']->getTableName();
104         $component = $this->_options['ownerTable']->getComponentName();
105         $id        = $this->_options['ownerTable']->getIdentifier();
106         $class     = $this->getOption('className');
107         $fields    = $this->getOption('fields');
108
109         try {
110
111             $conn->beginTransaction();
112     
113             $query = 'SELECT * FROM ' . $conn->quoteIdentifier($tableName)
114                    . ' WHERE ' . $conn->quoteIdentifier($id)
115                    . ' IN (SELECT ' . $conn->quoteIdentifier($id)
116                    . ' FROM ' . $conn->quoteIdentifier($this->_options['pluginTable']->getTableName())
117                    . ' WHERE keyword IS NULL)';
118     
119             $rows = $conn->fetchAll($query);
120     
121             foreach ($rows as $row) {
122                 foreach ($fields as $field) {
123                     $data  = $row[$field];
124         
125                     $terms = $this->analyze($data);
126         
127                     foreach ($terms as $pos => $term) {
128                         $index = new $class();
129         
130                         $index->keyword = $term;
131                         $index->position = $pos;
132                         $index->field = $field;
133                         
134                         foreach ((array) $this->_options['ownerTable']->getIdentifier() as $id) {
135                             $index->$id = $row[$id];
136                         }
137     
138                         $index->save();
139                     }
140                 }
141             }
142
143             $conn->commit();
144         } catch (Doctrine_Exception $e) {
145             $conn->rollback();
146         }
147     }
148     /**
149      * insertPending
150      *
151      * @return integer
152      */
153     public function insertPending($indexTableName, $id, $conn = null)
154     {
155         if ( ! ($conn instanceof Doctrine_Connection)) {
156             $conn = Doctrine_Manager::connection();
157         }
158
159         $conn->insert($indexTableName, array('foreign_id' => $id));
160     }
161     public function buildDefinition(Doctrine_Table $table)
162     {
163         $name = $table->getComponentName();
164
165         $className = $this->getOption('className');
166         
167         $this->_options['ownerTable'] = $table;
168
169         if (class_exists($className)) {
170             return false;
171         }
172
173         $columns = array('keyword'  => array('type'    => 'string',
174                                              'length'  => 200,
175                                              'primary' => true,
176                                              ),
177                          'field'    => array('type'    => 'string',
178                                              'length'  => 50,
179                                              'primary' => true),
180                          'position' => array('type'    => 'integer',
181                                              'length'  => 8,
182                                              'primary' => true,
183                                              ));
184
185         $id = $table->getIdentifier();
186
187         $options = array('className' => $className);
188
189         $fk = $this->generateForeignKeys($table);
190         $columns += $fk;
191
192         $relations = $this->generateRelation($table, $fk);
193
194         $this->generateClass($options, $columns, $relations);
195
196         $this->_options['pluginTable'] = $table->getConnection()->getTable($this->_options['className']);
197
198         return true;
199     }
200 }