Permalink
Browse files

[sfLuceneable15BehaviorPlugin]

first commit
  • Loading branch information...
0 parents commit fa57760738b75c84bbd4065d958a718621817315 @nibsirahsieu committed Jan 2, 2011
@@ -0,0 +1,7 @@
+#all:
+# sf_luceneable15_behavior:
+# stopwords: false #possible value:
+ #false disabled stopwords (default)
+ #string separated by ','. ex: "a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "no", "not", "of", "on", "or", "s", "such", "t", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"
+# shortwords: 3
+# data_dir: %SF_DATA_DIR%/lucene
@@ -0,0 +1,8 @@
+<?php
+class sfLuceneable15BehaviorPluginConfiguration extends sfPluginConfiguration
+{
+ public function initialize()
+ {
+
+ }
+}
@@ -0,0 +1,77 @@
+<?php
+class LuceneableBehavior extends Behavior
+{
+ protected function getLuceneFieldMethod($method)
+ {
+ $availableMethods = array('keyword' => 'Keyword', 'unidexed' => 'UnIndexed', 'binary' => 'Binary', 'text' => 'Text', 'unstored' => 'UnStored');
+ $method = strtolower($method);
+ if (isset($availableMethods[$method])) return $availableMethods[$method];
+ throw new Exception(sprintf('Unknown Lucene Field method %s', $method));
+ }
+
+ /**
+ * Get the getter of the column of the behavior
+ * @param string $col the column name
+ * @return string The related getter, e.g. 'getSlug'
+ */
+ protected function getColumnGetter($col)
+ {
+ return 'get' . $this->getTable()->getColumn($col)->getPhpName();
+ }
+
+ public function postSave($builder)
+ {
+ return "if (\$affectedRows > 0) \$this->updateLuceneIndex();";
+ }
+
+ public function postDelete($builder)
+ {
+ return "\$this->deleteLuceneIndex();";
+ }
+
+ public function objectMethods($builder)
+ {
+ $script = '';
+ $script .= $this->addUpdateLuceneIndex();
+ $script .= $this->addDeleteLuceneIndex();
+
+ return $script;
+ }
+
+ public function addUpdateLuceneIndex()
+ {
+ $data = array();
+ $columns = $this->getParameters();
+ if (empty($columns))
+ {
+ $table = $this->getTable();
+ foreach ($table->getColumns() as $col) {
+ //skip primary key
+ if (!$col->isPrimaryKey())
+ {
+ $method = 'get'.$col->getPhpName().'()';
+ $clo = strtolower($col->getName());
+ $data[] = array('UnStored', $clo, $method);
+ }
+ }
+ }
+ else
+ {
+ foreach ($columns as $col => $type)
+ {
+ $method = $this->getColumnGetter($col).'()';
+ $clo = strtolower($col);
+ $fieldMethod = $this->getLuceneFieldMethod($type);
+ $data[] = array($fieldMethod, $clo, $method);
+ }
+ }
+ return $this->renderTemplate('updateLuceneIndex', array(
+ 'data' => $data,
+ ));
+ }
+
+ public function addDeleteLuceneIndex()
+ {
+ return $this->renderTemplate('deleteLuceneIndex');
+ }
+}
@@ -0,0 +1,16 @@
+
+/**
+ * delete lucene index for this class
+ * @param zend lucene index $index
+ * @return boolean
+ */
+public function deleteLuceneIndex($index = null)
+{
+ if (null === $index) $index = sfLuceneableToolkit::getLuceneIndex(get_class($this));
+ foreach ($index->find('pk:'.$this->getPrimaryKey()) as $hit)
+ {
+ $index->delete($hit->id);
+ }
+
+ return true;
+}
@@ -0,0 +1,24 @@
+
+/**
+ * update lucene index for this class
+ * @param zend lucene index $index
+ * @return boolean
+ */
+public function updateLuceneIndex($index = null)
+{
+ if (null === $index) $index = sfLuceneableToolkit::getLuceneIndex(get_class($this));
+
+ // remove existing entries
+ $this->deleteLuceneIndex($index);
+
+ $doc = new Zend_Search_Lucene_Document();
+ $doc->addField(Zend_Search_Lucene_Field::Keyword('pk', $this->getPrimaryKey()));
+<?php foreach ($data as $v): ?>
+ $doc->addField(Zend_Search_Lucene_Field::<?php echo $v[0] ?>('<?php echo $v[1] ?>', $this-><?php echo $v[2] ?>, 'utf-8'));
+<?php endforeach; ?>
+
+ $index->addDocument($doc);
+ $index->commit();
+
+ return true;
+}
@@ -0,0 +1,53 @@
+<?php
+class sfPropelLuceneGenerator extends sfGenerator
+{
+ protected
+ $dbMap = null;
+
+ public function initialize(sfGeneratorManager $generatorManager)
+ {
+ parent::initialize($generatorManager);
+
+ $this->setGeneratorClass('sfPropelLucene');
+ }
+
+ public function generate($params = array())
+ {
+ $this->params = $params;
+
+ if (!isset($this->params['connection']))
+ {
+ throw new sfParseException('You must specify a "connection" parameter.');
+ }
+
+ $this->dbMap = Propel::getDatabaseMap($this->params['connection']);
+
+ $this->loadBuilders();
+
+ $luceneableModels = array();
+ foreach ($this->dbMap->getTables() as $tableName => $table)
+ {
+ $behaviors = $table->getBehaviors();
+ if (isset($behaviors['luceneable']))
+ {
+ $luceneableModels[] = $table->getClassname();
+ }
+ }
+ return $luceneableModels;
+ }
+
+ protected function loadBuilders()
+ {
+ $this->dbMap = Propel::getDatabaseMap($this->params['connection']);
+ $classes = sfFinder::type('file')->name('*TableMap.php')->in($this->generatorManager->getConfiguration()->getModelDirs());
+ foreach ($classes as $class)
+ {
+ $omClass = basename($class, 'TableMap.php');
+ if (class_exists($omClass) && is_subclass_of($omClass, 'BaseObject'))
+ {
+ $tableMapClass = basename($class, '.php');
+ $this->dbMap->addTableFromMapClass($tableMapClass);
+ }
+ }
+ }
+}
@@ -0,0 +1,87 @@
+<?php
+class sfLuceneableToolkit
+{
+ public static $_index = array();
+ static protected $zendLoaded = false;
+
+ private static function prepareZendSearchLucene()
+ {
+ Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive());
+
+ $stopWords = sfConfig::get('app_sf_luceneable15_behavior_stopWords', false);
+ $stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords(false === $stopWords ? array() : explode(',', $stopWords));
+ Zend_Search_Lucene_Analysis_Analyzer::getDefault()->addFilter($stopWordsFilter);
+
+ $shortWords = sfConfig::get('app_sf_luceneable15_behavior_shortWords', 3);
+ $shortWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_ShortWords($shortWords);
+ Zend_Search_Lucene_Analysis_Analyzer::getDefault()->addFilter($shortWordsFilter);
+
+ Zend_Search_Lucene_Storage_Directory_Filesystem::setDefaultFilePermissions(0777);
+ }
+
+ static public function registerZend()
+ {
+ if (self::$zendLoaded)
+ {
+ return;
+ }
+ set_include_path(dirname(__FILE__).'/../vendor'.PATH_SEPARATOR.get_include_path());
+ require_once dirname(__FILE__).'/../vendor/Zend/Loader/Autoloader.php';
+ Zend_Loader_Autoloader::getInstance();
+ self::$zendLoaded = true;
+ }
+
+ static public function getLuceneIndex($class)
+ {
+ if (isset(self::$_index[$class]))
+ {
+ return self::$_index[$class];
+ }
+
+ self::registerZend();
+
+ if (file_exists($index = self::getLuceneIndexFile($class)))
+ {
+ $luceneIndex = Zend_Search_Lucene::open($index);
+ }
+ else
+ {
+ $luceneIndex = Zend_Search_Lucene::create($index);
+ chmod($index, 0777);
+ }
+ self::$_index[$class] = $luceneIndex;
+ return $luceneIndex;
+ }
+
+ static public function getLuceneIndexFile($class)
+ {
+ $data_dir = sfConfig::get('app_sf_luceneable15_behavior_data_dir', sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'lucene');
+ return $data_dir.DIRECTORY_SEPARATOR.$class.'.index';
+ }
+
+ public static function optimizeIndex($class, $index = null)
+ {
+ if (null === $index) $index = self::getLuceneIndex($class);
+ $index->optimize();
+ }
+
+ public static function removeIndex($class, $index = null)
+ {
+ if (null === $index) $index = self::getLuceneIndex($class);
+ if (file_exists($index))
+ {
+ sfToolkit::clearDirectory($index);
+ rmdir($index);
+ }
+ }
+
+ public static function createIndex($class, $index = null)
+ {
+ if (null === $index) $index = self::getLuceneIndex($class);
+ $objects = PropelQuery::from($class)->find();
+ foreach ($objects as $object)
+ {
+ $object->updateLuceneIndex($index);
+ }
+ }
+}
@@ -0,0 +1,43 @@
+<?php
+class sfPropelLuceneSearch
+{
+ protected $_queryString = "";
+ protected $_models = array();
+
+ public function __construct($sSearch = null)
+ {
+ $this->_queryString = $sSearch;
+ }
+
+ public static function create($sSearch = null)
+ {
+ return new self($sSearch);
+ }
+
+ public function in($models)
+ {
+ if (is_array($models))
+ {
+ $this->models = $models;
+ }
+ else
+ {
+ $this->_models = func_get_args();
+ }
+ return $this;
+ }
+
+ public function find($limit = 10)
+ {
+ foreach ($this->models as $model)
+ {
+ $hits = sfLuceneableToolkit::getLuceneIndex($model)->find($this->_queryString);
+ $pks = array();
+ foreach ($hits as $hit)
+ {
+ $pks[] = $hit->pk;
+ }
+ return PropelQuery::from($model)->limit($limit)->findPks($pks);
+ }
+ }
+}
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * symfony task for creating lucene indexes
+ *
+ * @package sfLuceneable15BehaviorPlugin
+ * @subpackage lib.task
+ * @author nibsirahsieu
+ */
+class sfPropelLuceneCreateIndexTask extends sfPropelBaseTask
+{
+ protected function configure()
+ {
+ $this->addOptions(array(
+ new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel'),
+ new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
+ new sfCommandOption('generator-class', null, sfCommandOption::PARAMETER_REQUIRED, 'The generator class', 'sfPropelLuceneGenerator'),
+ ));
+
+ $this->namespace = 'propel';
+ $this->name = 'lucene-create-index';
+ $this->briefDescription = 'Creates lucene index for the current model';
+
+ $this->detailedDescription = <<<EOF
+The [propel:lucene-create-index|INFO] task creates lucene index from the schema:
+
+ [./symfony lucene-create-index|INFO]
+
+The task read the schema information in [config/*schema.xml|COMMENT] and/or
+[config/*schema.yml|COMMENT] from the project and all installed plugins.
+
+The task use the [propel|COMMENT] connection as defined in [config/databases.yml|COMMENT].
+You can use another connection by using the [--connection|COMMENT] option:
+
+ [./symfony propel:lucene-create-index --connection="name"|INFO]
+
+EOF;
+ }
+
+ /**
+ * @see sfTask
+ */
+ protected function execute($arguments = array(), $options = array())
+ {
+ $this->logSection('propel', 'generating lucene indexes...');
+
+ $generatorManager = new sfGeneratorManager($this->configuration);
+ $luceneableModels = $generatorManager->generate($options['generator-class'], array(
+ 'connection' => $options['connection']
+ ));
+
+ $databaseManager = new sfDatabaseManager($this->configuration);
+
+ foreach ($luceneableModels as $luceneableModel)
+ {
+ $this->logSection('propel', sprintf('Recreating lucene index for %s model', $luceneableModel));
+ $index = sfLuceneableToolkit::getLuceneIndex($luceneableModel);
+ sfLuceneableToolkit::removeIndex($luceneableModel);
+ sfLuceneableToolkit::createIndex($luceneableModel);
+ $this->logSection('propel', sprintf('Optimizing lucene index for %s model', $luceneableModel));
+ sfLuceneableToolkit::optimizeIndex($luceneableModel);
+ }
+
+ $this->logSection('propel', 'done...');
+ }
+
+}
Oops, something went wrong.

0 comments on commit fa57760

Please sign in to comment.