source: cpc/trunk/project/lib/model/solr/SolrListener.php @ 1312

Last change on this file since 1312 was 1312, checked in by teymour, 11 years ago

Indexation possible, reste un pb de gestion de fichier à regler

File size: 7.3 KB
Line 
1<?php
2
3
4class SolrConnector extends sfLogger
5{
6  private $solr = NULL;
7  private $_options = NULL;
8
9  public static function getFileCommands() {
10    return sfConfig::get('sf_log_dir').'/solr/commands.log';
11  }
12
13  protected function doLog($message, $priority)
14  {
15    error_log(sprintf('%s (%s)', $message, sfLogger::getPriorityName($priority)));
16  }
17
18  public function __construct( $listener_options = NULL)
19  {
20    $host = sfConfig::get('app_solr_host', 'localhost');
21    $port = sfConfig::get('app_solr_port', '8983');
22    $url = sfConfig::get('app_solr_url', '/solr');
23    $this->solr = new Apache_Solr_Service($host, $port, $url);
24   
25    if(!$this->solr->ping()) {
26      throw new Exception('Search is not available right now.');
27//      $this->doLog('SolrConnector: Arg, Search is not available right now', sfLogger::ERR);
28    }
29   
30    $this->_options = $listener_options;
31
32    return $this->solr;
33  }
34 
35
36  public function updateFromCommands() {
37    echo "UpdateFromCommands\n";
38    echo file_exists(self::getFileCommands())."\n";
39    if (!file_exists(self::getFileCommands().'.lock') && file_exists(self::getFileCommands())) {
40      echo "rename \n";
41      rename(self::getFileCommands(), self::getFileCommands().'.lock');
42    }
43    if (!file_exists(self::getFileCommands().'.lock')) {
44      echo "No lock\n";
45      return ;
46    }
47    foreach(file(self::getFileCommands().'.lock') as $line) {
48      if (preg_match('/\] (UPDATE|REMOVE): (.+)/', $line, $matches)) {
49        echo $matches[1]." ".$matches[2]."\n";
50        $obj = json_decode($matches[2]);
51        if ($matches[1] == 'UPDATE') {
52          $this->updateLuceneRecord($obj);
53        }else{
54          $this->solr->deleteById($obj->id);
55        }
56      }
57    }
58    unlink(self::getFileCommands().'.lock');
59  }
60
61
62  public function deleteLuceneRecord($id)
63  {
64    if($this->solr->deleteById($id) )
65      return $this->solr->commit();
66    return false;
67  }
68
69  public function updateLuceneRecord($obj)
70  {
71     $document = new Apache_Solr_Document(); 
72     $document->addField('id', $obj->id); 
73     $document->addField('object_id', $obj->object_id); 
74     $document->addField('object_name', $obj->object_name); 
75     if (isset($obj->wordcount))
76       $document->addField('wordcount', $obj->wordcount); 
77     if (isset($obj->title))
78       $document->addField('title', $obj->title->content, $obj->title->weight); 
79     if (isset($obj->description))
80       $document->addField('description', $obj->description->content, $obj->description->weight); 
81     if (isset($obj->date))
82       $document->addField('date', $obj->date->content, $obj->date->weight); 
83     $this->solr->addDocument($document);
84     $this->solr->commit();
85  }
86
87  public function deleteAll() {
88    $this->solr->deleteByQuery('*:*');
89    $this->solr->commit();
90  }
91
92  public function search($queryString, $params = array(), $offset = 0, $maxHits = 0) {
93    if($maxHits == 0)
94        $maxHits = sfConfig::get('app_solr_max_hits', 256);
95    $response = $this->solr->search($queryString, $offset, $maxHits, $params);
96    return unserialize($response->getRawResponse());
97  }
98 
99}
100
101class SolrListener extends Doctrine_Record_Listener
102{
103  /**
104     * Array of timestampable options
105     *
106     * @var string
107     */
108    protected $_options = array();
109
110    protected static $fileCommand = null;
111    protected static $fileDispatcher = null;
112
113    protected static function getFileCommand() {
114      if (!self::$fileDispatcher) {
115        self::$fileDispatcher = new sfEventDispatcher();
116      }
117      if (!self::$fileCommand) {
118        self::$fileCommand = new sfFileLogger(self::$fileDispatcher, array('file' => SolrConnector::getFileCommands()));
119      }
120      return self::$fileCommand;
121    }
122
123    private $command = null;
124
125    /**
126     * __construct
127     *
128     * @param string $options
129     * @return void
130     */
131    public function __construct($options)
132    {
133      $this->_options = $options;
134    }
135
136    protected $solr = NULL;
137    protected function getSolrConnector() {
138      if (!$this->solr)
139        $this->solr = new SolrConnector($this->_options);
140      return $this->solr;
141    }
142
143    private function sendCommand($status, $json) {
144      self::getFileCommand()->log($status.': '.json_encode($json));
145    }
146   
147  private function get_and_strip($obj, $field) {
148    $f = $obj->get($field);
149    if ($f) {
150      if (get_class($f) && ! $f->id)
151        return ;
152      return strip_tags($f);
153    }
154    return ;
155  }
156
157  private function getObjFieldsValue($obj, $fields)
158  {
159    if (!is_array($fields)) {
160      return $this->get_and_strip($obj, $fields);
161    }
162    $s = '';
163    foreach($fields as $f) {
164      $s .= $this->get_and_strip($obj, $f).' ';
165    }
166    return $s;
167  }
168 
169  private function getLuceneObjId($obj) 
170  {
171    return get_class($obj).'/'.$obj->getId();
172  }
173 
174    // Réindexation après une création / modification
175    public function postSave(Doctrine_Event $event)
176    {
177      $obj = $event->getInvoker();
178      //      $this->getSolrConnector()->updateLuceneRecord($obj);
179
180      if ($t = $this->_options['index_if'] && $t && $obj->get($t))
181        return ;
182     
183      $json = array();
184      $json['id'] = $this->getLuceneObjId($obj);
185      $json['object_id'] =  $obj->getId();
186      $json['object_name'] = get_class($obj);
187     
188
189    if ($t = $this->_options['description']) {
190      $content = $this->getObjFieldsValue($obj, $t);
191      $wordcount = str_word_count($content);
192    }
193
194    if (isset($this->_options['extra_weight'])) 
195      $extra_weight = $this->_options['extra_weight'];
196    else
197      $extra_weight = 1;
198
199    if (isset($this->_options['devaluate_if_wordcount_under']) && ($wclimit = $this->_options['devaluate_if_wordcount_under'])) {
200       if ($wclimit > $wordcount)
201         $extra_weight *= ($wordcount*0.5) / $wclimit + 0.5 ;
202    }
203   
204    // On donne un poids plus important au titre
205    if (isset($this->_options['title']) && $t = $this->_options['title']) {
206      $json['title']['content'] = $this->getObjFieldsValue($obj, $t);
207      $json['title']['weight'] =  1.2 * $extra_weight;
208    }
209   
210    // La description
211    if (isset($content)) {
212      $json['description']['content'] = $content;
213      $json['description']['weight'] = $extra_weight;
214      $json['wordcount'] = $wordcount;
215    }
216     
217    // par default la date est la created_at
218    if ( !($t = $this->_options['date'])) {
219      $t = 'created_at';
220    }
221    $d = preg_replace('/\+.*/', 'Z', date('c', strtotime($this->getObjFieldsValue($obj, $t))));
222    $json['date']['content'] = $d;
223    $json['date']['weight'] = $extra_weight;
224   
225
226    $json['tags']['content'] = array();
227    try {
228      foreach($obj->getTags() as $tag) if ($tag)  {
229        $json['tags']['content'][] =  preg_replace('/:/', '=', $tag);
230      }
231    }catch (Exception $e) {}
232   
233    if ($t = $this->_options['moretags']) {
234      if (!is_array($t)) {
235        $s = $this->get_and_strip($obj, $t);
236        if ($s)
237          $json['tags']['content'][] = $t.'='.$s;
238      }else{
239        foreach ($t as $i) {
240          $s = $this->get_and_strip($obj, $i);
241          if (strlen($s)) {
242            $s = strip_tags($s);
243            $json['tags']['content'][] = $i.'='.$s;
244          }
245        }
246      }
247    }
248   
249    $json['tags']['weight'] = $extra_weight;
250
251   
252    $this->sendCommand('UPDATE', $json);
253    }
254   
255    // Désindexation après une suppression
256    public function postDelete(Doctrine_Event $event)
257    {
258      $obj = $event->getInvoker();
259      //      $this->getSolrConnector()->deleteLuceneRecord($obj);
260      $json = new stdClass();
261      $json->id = $this->getLuceneObjId($obj);
262      $this->sendCommand('DELETE', $json);
263    }
264   
265}
Note: See TracBrowser for help on using the repository browser.