Author: caziel Date: 2010-01-31 17:53:53 +0100 (Sun, 31 Jan 2010) New Revision: 27357
Added: plugins/rsLucenePlugin/trunk/LICENSE plugins/rsLucenePlugin/trunk/README plugins/rsLucenePlugin/trunk/config/ plugins/rsLucenePlugin/trunk/config/propel.ini plugins/rsLucenePlugin/trunk/config/schema.yml plugins/rsLucenePlugin/trunk/config/search.yml plugins/rsLucenePlugin/trunk/lib/ plugins/rsLucenePlugin/trunk/lib/behavior/ plugins/rsLucenePlugin/trunk/lib/behavior/RsBehaviorSearchable.php plugins/rsLucenePlugin/trunk/lib/rsLucene.class.php plugins/rsLucenePlugin/trunk/lib/task/ plugins/rsLucenePlugin/trunk/lib/task/sfLuceneDumpTask.class.php plugins/rsLucenePlugin/trunk/lib/task/sfLuceneGenerateTask.class.php plugins/rsLucenePlugin/trunk/lib/task/sfLuceneInfoTask.class.php plugins/rsLucenePlugin/trunk/lib/task/sfLuceneOptimizeTask.class.php plugins/rsLucenePlugin/trunk/modules/ plugins/rsLucenePlugin/trunk/modules/rsLucene/ plugins/rsLucenePlugin/trunk/modules/rsLucene/actions/ plugins/rsLucenePlugin/trunk/modules/rsLucene/actions/actions.class.php plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/ plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_search.php plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_searchResult.php plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/searchSuccess.php Log: =initial commit for rsLucenePlugin Added: plugins/rsLucenePlugin/trunk/LICENSE =================================================================== --- plugins/rsLucenePlugin/trunk/LICENSE (rev 0) +++ plugins/rsLucenePlugin/trunk/LICENSE 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,7 @@ +Copyright (c) 2010 Robert Schönthal + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Added: plugins/rsLucenePlugin/trunk/README =================================================================== --- plugins/rsLucenePlugin/trunk/README (rev 0) +++ plugins/rsLucenePlugin/trunk/README 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,123 @@ +rsLucenePlugin +======== + +*adds Zend-Search-Lucene capabilities to Propel Models by adding a behavior* + +Its completly configurable through a yaml file + +Its mostly inspired by the "old" sfLucenePlugin which wont worked for my newer symfony projects. +and the lucene integration mentioned in the jobeet tutorials +The sfLucenePlugin is very configurable and handy, the jobeet integration is clean and working, +if tried to combine both advantages. + +*Its still alpha or beta, but its working perfectly for me.* + +*Its working with symfony 1.4 and PHP5.3* + + +Installation +------------ + +for SVN externals try this: + + http://svn.symfony-project.com/plugins/rsLucenePlugin/trunk + +for Pear Packages try this: + + ./symfony plugin:install rsLucenePlugin -s alpha + + +Configuration +------------- + +add the Zend Framework to your symfony project, since we wont load Zend all the time, +implement this function in your ProjectConfiguration (it should return the path to the Zend Autoloader): + + public function getZendPath(){ + return 'PATH/TO/Zend/Loader/Autoloader.php'; + } + +add the behavior to your propel.ini by adding these line: + + propel.behavior.searchable.class = plugins.rsLucenePlugin.lib.behavior.rsBehaviorSearchable + +add the behavior to your models: + + propel: + MODEL: + _propel_behaviors: + # every model gets indexed + searchable: ~ + ANOTHER_MODEL: + _propel_behaviors: + searchable: + #only models which ACCESSOR_METHOD returns true gets indexed + check_active: ACCESSOR_METHOD + +now configure your search configuration: + + index: + meta: + name: THE_INDEX_NAME + models: + MODEL: + fields: + pk: id + AN_ATTRIBUTE: + boost: 1.5 + method: ACCESSOR_METHOD + ANOTHER_ATTRIBUTE: ~ + route: ~ + category: THE_CATEGORY + ANOTHER_MODEL: + fields: + pk: id + AN_ATTRIBUTE: + boost: 1.5 + method: ACCESSOR_METHOD + ANOTHER_ATTRIBUTE: ~ + route: ~ + category: THE_CATEGORY + +**the route attribute is mandatory, your model should define a function which returns the url for it!** + +Thats all, now let rebuild your model: + + ./symfony propel:build-all + +Now everytime a model is saved the appropiate lucene documents is updated. + +Tasks +----- + ./symfony lucene:generate # generates the index + ./symfony lucene:optimize # optimized the index + ./symfony lucene:info # shows information about the index + ./symfony lucene:dump # deletes the index + + +Frontend +-------- +For plug'n'play search add the plugin module to your application settings.yml: + + all: + .settings: + enabled_modules: [ ..., rsLucene] + +Add the route: + + search: + url: /search + param: { module: rsLucene, action: search } + + +Tests +----- +* none till now + +Todo +---- + +* move route registering to plugin configuration +* implement multi indexes +* implement unit tests +* implement much more lucene features Added: plugins/rsLucenePlugin/trunk/config/propel.ini =================================================================== --- plugins/rsLucenePlugin/trunk/config/propel.ini (rev 0) +++ plugins/rsLucenePlugin/trunk/config/propel.ini 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,2 @@ +;propel.builder.addBehaviors = true +;propel.behavior.searchable.class = plugins.rsLucenePlugin.lib.behavior.rsBehaviorSearchable Added: plugins/rsLucenePlugin/trunk/config/schema.yml =================================================================== --- plugins/rsLucenePlugin/trunk/config/schema.yml (rev 0) +++ plugins/rsLucenePlugin/trunk/config/schema.yml 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,12 @@ +#propel: +# MODEL: +# _propel_behaviors: +# # every model gets indexed +# searchable: ~ +# +# ANOTHER_MODEL: +# _propel_behaviors: +# searchable: +# #only models which ACCESSOR_METHOD returns true gets indexed +# check_active: ACCESSOR_METHOD +# Added: plugins/rsLucenePlugin/trunk/config/search.yml =================================================================== --- plugins/rsLucenePlugin/trunk/config/search.yml (rev 0) +++ plugins/rsLucenePlugin/trunk/config/search.yml 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,14 @@ +#index: +# meta: +# name: THE_INDEX_NAME +# +# models: +# A_MODEL_NAME: +# fields: +# pk: id +# AN_ATTRIBUTE: +# boost: 1.5 +# method: ACCESSOR_METHOD +# ANOTHER_ATTRIBUTE: ~ +# route: ~ +# category: THE_CATEGORY Added: plugins/rsLucenePlugin/trunk/lib/behavior/RsBehaviorSearchable.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/behavior/RsBehaviorSearchable.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/behavior/RsBehaviorSearchable.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,84 @@ +<?php + +/** + * propel behavior for making models indexable und searchable + * + * @package rsLucenePlugin + * @subpackage lib.behavior + * @author robert schoenthal + */ +class rsBehaviorSearchable extends SfPropelBehaviorBase +{ + protected $parameters = array( + 'check_active' => false + ); + + public function postSave() + { + if ($this->isDisabled()) + { + return; + } + + if($this->getParameter('check_active') === false){ + return <<<EOF +rsLucene::updateDocument(\$this); +EOF; + }else{ + if ($column = $this->getParameter('check_active')) + { + return <<<EOF +if (\$this->{$column}) +{ + rsLucene::updateDocument(\$this); +} +else +{ + rsLucene::deleteDocument(\$this); +} +EOF; + + } + + } + } + + public function postInsert() + { + if ($this->isDisabled()) + { + return; + } + + if($this->getParameter('check_active') === false){ + return <<<EOF +rsLucene::updateDocument(\$this); +EOF; + }else{ + if ($column = $this->getParameter('check_active')) + { + return <<<EOF +if (\$this->{$column}) +{ +rsLucene::updateDocument(\$this); +} +EOF; + + } + + } + } + + public function postDelete() + { + if ($this->isDisabled()) + { + return; + } + + return <<<EOF + rsLucene::deleteDocument(\$this); +EOF; + + } +} Added: plugins/rsLucenePlugin/trunk/lib/rsLucene.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/rsLucene.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/rsLucene.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,289 @@ +<?php + +/** + * symfony friendly zend lucene wrapper + * + * @package rsLucenePlugin + * @subpackage lib + * @author robert schoenthal + */ +class rsLucene { + + static protected $zendLoaded = false; + + /** + * the index name + * @var string + */ + static $indexName; + + /** + * models to index + * @var array + */ + static $classes; + + /** + * the search config + * @var array + */ + static $config; + + /** + * the current instance + * @var rsLucene + */ + static $instance; + + /** + * debug switch + * @var boolean + */ + static $debug; + + /** + * fetches the index for current env + * @return string + */ + private static function getLuceneIndexFile() { + return sfConfig::get('sf_data_dir').'/'.self::$indexName.'.index'; + } + + public static function debug() { + self::$debug = true; + } + + /** + * prepares the search engine + */ + private static function prepareZendSearch() { + + Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); + + $stopWords = array(); + $stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords($stopWords); + Zend_Search_Lucene_Analysis_Analyzer::getDefault()->addFilter($stopWordsFilter); + + $shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords(3); + Zend_Search_Lucene_Analysis_Analyzer::getDefault()->addFilter($shortWordsFilter); + + Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions(0777); + } + + private static function getConfig() { + + $cfg = sfYaml::load(sfConfig::get('sf_config_dir').'/'.'search.yml'); + self::$config = $cfg["index"]; + + self::$indexName = self::$config["meta"]["name"]; + self::$classes = self::$config["models"]; + + self::loadZend(); + } + + private static function loadZend() { + if(!self::$zendLoaded) { + self::registerZend(); + } + } + + private static function registerZend() { + if(!class_exists('Zend_Loader_Autoloader')){ + require_once ProjectConfiguration::getActive()->getZendPath(); + } + + Zend_Loader_Autoloader::getInstance(); + self::$zendLoaded = true; + } + + /** + * returns the search instance + * @return rsLucene + */ + public static function getInstance() { + if(!self::$instance) { + self::$instance = self; + self::getConfig(); + self::prepareZendSearch(); + } + return self::$instance; + } + + /** + * optimizes a lucene index + */ + public static function optimizeIndex() { + + $index = self::getIndex(); + $index->optimize(); + } + + /** + * returns index information + * @return array + */ + public static function getInfos() { + $infos = array(); + $index = self::getIndex(); + $infos["documents"] = $index->numDocs(); + return $infos; + } + + /** + * generates a lucene index + */ + public static function generateIndex() { + $index = self::getIndex(); + + foreach(self::$classes as $class=>$config) { + $peer = isset($config["peer"]) ? $config["peer"] : $class."Peer"; + + $models = call_user_func($peer."::doSelect",new Criteria()); + + foreach($models as $model) { + self::updateDocument($model,$config["fields"]); + } + } + } + + /** + * dumps a lucene index + */ + public static function dumpIndex() { + + self::getConfig(); + + if (file_exists($index = self::getLuceneIndexFile())) { + sfToolkit::clearDirectory($index); + rmdir($index); + } + } + + /** + * returns the index + * @return Zend_Search_Lucene + */ + public static function getIndex() { + + self::getConfig(); + self::prepareZendSearch(); + + if (file_exists($index = self::getLuceneIndexFile())) { + $lucene_index = Zend_Search_Lucene::open($index); + }else { + $lucene_index = Zend_Search_Lucene::create($index); + chmod($index, 0777); + } + + + return $lucene_index; + } + + /** + * prepares a query string for search + * @param string $query + * @return Zend_Search_Lucene_Search_Query + */ + private static function prepareQuery($query,$model) { + + if($model) { + $query = "+".$query." +category:".$model; + }else { + $query = "+".$query; + } + + $query = Zend_Search_Lucene_Search_QueryParser::parse($query); //search object + + return $query; + + } + + /** + * searches the index for a given query + * @param Zend_Search_Lucene_Search_Query $query + * @return array Zend_Search_Lucene_Search_QueryHit + */ + public static function search($query,$model=null) { + self::getConfig(); + + $query = self::prepareQuery($query,$model); + if(!$query) { + return false; + } + else { + return self::getIndex()->find($query); + } + } + + /** + * updates a document + * @param sfBaseObject + */ + public static function updateDocument($object,$config=null) { + $index = self::getIndex(); + + if(!$config) { + $config = self::$config["models"][get_class($object)]["fields"]; + } + + // remove existing entries + foreach ($index->find(get_class($object).'_pk:'.$object->getId()) as $hit) { + $index->delete($hit->id); + } + + $doc = new Zend_Search_Lucene_Document(); + + $doc->addField(Zend_Search_Lucene_Field::Keyword(get_class($object).'_pk', $object->getId())); + + foreach($config as $key=>$field) { + if($key == "pk") { + $doc->addField(Zend_Search_Lucene_Field::unIndexed('pk', $object->getId() , 'utf-8')); + }elseif($key == "category") { + $doc->addField(Zend_Search_Lucene_Field::Text('category', $field , 'utf-8')); + }else { + if(!$field) { + $method = "get".$key; + } + elseif(is_array($field)) { + $method = $field["method"] ? $field["method"] : "get".$key; + } + else { + $method = "get".$field; + } + + $value = $object->$method(); + + $value = strip_tags($value); + $objField = Zend_Search_Lucene_Field::Text($key, $value, 'utf-8'); + if(is_array($field)) { + foreach($field as $pkey => $param) { + $objField->$pkey = $param; + } + } + $doc->addField($objField); + } + } + + if(self::$debug) { + echo "add Document: ".get_class($object)." id:".$object->getId()."\n"; + } + + $index->addDocument($doc); + + $index->commit(); + } + + /** + * deletes a document + * @param sfBaseObject $object + */ + public static function deleteDocument($object) { + $index = self::getIndex(); + + foreach ($index->find(get_class($object).'_pk:'.$object->getId()) as $hit) { + $index->delete($hit->id); + } + } + +} + Added: plugins/rsLucenePlugin/trunk/lib/task/sfLuceneDumpTask.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/task/sfLuceneDumpTask.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/task/sfLuceneDumpTask.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,36 @@ +<?php + +/** + * symfony task for deleting a lucene index + * + * @package rsLucenePlugin + * @subpackage lib.task + * @author robert schoenthal + */ +class rsLuceneDumpTask extends sfBaseTask +{ + protected function configure() + { + $this->addOptions(array( + new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel'), + )); + + $this->namespace = 'lucene'; + $this->name = 'dump'; + $this->briefDescription = 'dumps a lucene index'; + $this->aliases = array("lucene-dump"); + $this->detailedDescription = <<<EOF +The [rsLuceneDump|INFO] task dumps a lucene index. +Call it with: + + [php symfony lucene:dump|INFO] +EOF; + } + + protected function execute($arguments = array(), $options = array()) + { + rsLucene::dumpIndex(); + $this->logSection("Info", "dumped index: ".rsLucene::$indexName); + } + +} \ No newline at end of file Added: plugins/rsLucenePlugin/trunk/lib/task/sfLuceneGenerateTask.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/task/sfLuceneGenerateTask.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/task/sfLuceneGenerateTask.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,56 @@ +<?php + +/** + * symfony task for generating a lucene index + * + * @package rsLucenePlugin + * @subpackage lib.task + * @author robert schoenthal + */ +class rsLuceneGenerateTask extends sfBaseTask +{ + protected function configure() + { + $this->addOptions(array( + new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel'), + )); + + $this->namespace = 'lucene'; + $this->name = 'generate'; + $this->briefDescription = 'generates a lucene index'; + $this->aliases = array("lucene-generate"); + $this->detailedDescription = <<<EOF +The [rsLuceneGenerate|INFO] task generates a lucene index. +Call it with: + + [php symfony lucene:generate|INFO] +EOF; + } + + protected function execute($arguments = array(), $options = array()) + { + $this->logSection("Task", "start lucene index generating"); + + // initialize the database connection + $databaseManager = new sfDatabaseManager($this->configuration); + $connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection(); + + $stime = time(); + rsLucene::debug(); + + rsLucene::dumpIndex(); + rsLucene::generateIndex(); + rsLucene::optimizeIndex(); + $etime = time(); + + $time = $etime - $stime; + + foreach(rsLucene::getInfos() as $key=>$info){ + $this->logSection($key,$info); + } + $this->logSection("time",$time." s"); + + $this->logSection("index",rsLucene::$indexName); + } + +} Added: plugins/rsLucenePlugin/trunk/lib/task/sfLuceneInfoTask.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/task/sfLuceneInfoTask.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/task/sfLuceneInfoTask.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,36 @@ +<?php + +/** + * symfony task for shows information of a lucene index + * + * @package rsLucenePlugin + * @subpackage lib.task + * @author robert schoenthal + */ +class sfLuceneInfoTask extends sfBaseTask +{ + protected function configure() + { + $this->addOptions(array( + new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel'), + )); + + $this->namespace = 'lucene'; + $this->name = 'info'; + $this->briefDescription = 'show informations about a lucene index'; + $this->aliases = array("lucene-info"); + $this->detailedDescription = <<<EOF +The [rsLuceneInfo|INFO] task show informations about a lucene index. +Call it with: + + [php symfony lucene:info|INFO] +EOF; + } + + protected function execute($arguments = array(), $options = array()) + { + foreach(rsLucene::getInfos() as $key=>$info){ + echo $key." : ".$info."\n"; + } + } +} Added: plugins/rsLucenePlugin/trunk/lib/task/sfLuceneOptimizeTask.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/lib/task/sfLuceneOptimizeTask.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/lib/task/sfLuceneOptimizeTask.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,39 @@ +<?php + +/** + * symfony task for optimizing a lucene index + * + * @package rsLucenePlugin + * @subpackage lib.task + * @author robert schoenthal + */ +class rsLuceneOptimizeTask extends sfBaseTask +{ + protected function configure() + { + + $this->addOptions(array( + new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel'), + )); + + $this->namespace = 'lucene'; + $this->name = 'optimize'; + $this->briefDescription = 'optimizes a lucene index'; + $this->aliases = array("lucene-optimize"); + $this->detailedDescription = <<<EOF +The [rsLuceneOptimize|INFO] task optimizes a lucene index. +Call it with: + + [php symfony lucene:optimize|INFO] +EOF; + } + + protected function execute($arguments = array(), $options = array()) + { + $this->logSection("Info", "optimzing index: ".sfKaozLucene::$indexName); + rsLucene::optimizeIndex(); + + $this->logSection("Task", "lucene index optimizing complete"); + } + +} Added: plugins/rsLucenePlugin/trunk/modules/rsLucene/actions/actions.class.php =================================================================== --- plugins/rsLucenePlugin/trunk/modules/rsLucene/actions/actions.class.php (rev 0) +++ plugins/rsLucenePlugin/trunk/modules/rsLucene/actions/actions.class.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,21 @@ +<?php + +/** + * search actions. + * + * @package rsLucenePlugin + * @subpackage actions + * @author robert schoenthal + */ +class homeActions extends sfActions { + + public function executeSearch(sfWebRequest $request) + { + try{ + $this->hits = rsLucene::search($request->getParameter('query'),$request->getParameter("category")); + } + catch(Exception $e){ + + } + } +} Added: plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_search.php =================================================================== --- plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_search.php (rev 0) +++ plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_search.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,16 @@ +<?php + $category = $sf_request->getParameter("category"); +?> + +<div id="search"> + <form method="get" action="<?php echo url_for('@search')?>"> + <?php if(isset($categories)):?> + <select name="category"> + <option value="" <?php if(!$category):?>selected="selected"<?php endif;?>>Everything</option> + </select> + <?php endif;?> + + <input type="text" name="query" value="<?php echo $sf_request->getParameter('query')?>"/> + <input type="submit" name="submit" value="Search"/> + </form> +</div> \ No newline at end of file Added: plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_searchResult.php =================================================================== --- plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_searchResult.php (rev 0) +++ plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/_searchResult.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,15 @@ +<?php + $hit = $doc->getDocument(); +?> + +<div class="search-result"> + <h3> + <span class="search_cat">[<?php echo $hit->category;?>]</span> + <?php echo link_to($doc->getDocument()->title,$hit->route);?> + <span class="search_rank">(<?php echo floor($doc->score*100)?> %)</span> + </h3> + <?php if($doc->getDocument()->category == "Bilder"):?> + <?php echo image_tag($doc->getDocument()->thumnail)?> + <?php endif?> + <p><?php echo truncate_text(html_entity_decode($hit->description), "400");?> +</div> Added: plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/searchSuccess.php =================================================================== --- plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/searchSuccess.php (rev 0) +++ plugins/rsLucenePlugin/trunk/modules/rsLucene/templates/searchSuccess.php 2010-01-31 16:53:53 UTC (rev 27357) @@ -0,0 +1,13 @@ +<?php include_partial("search",array('categories'=>true));?> + +<?php if(!isset($hits) || count($hits) == 0):?> + <h2><?php echo "no results"?></h2> +<?php else : ?> + <?php use_helper("Text")?> + <h2><?php echo count($hits)." "."Hit".(count($hits)>1 ? 's':'')?></h2> + + <?php foreach($hits as $doc):?> + <?php include_partial("searchResult",array("doc"=>$doc));?> + <?php endforeach;?> + +<?php endif;?> \ No newline at end of file -- You received this message because you are subscribed to the Google Groups "symfony SVN" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/symfony-svn?hl=en.
