Added prototype for ACP search
authorAlexander Ebert <ebert@woltlab.com>
Wed, 15 Aug 2012 17:48:58 +0000 (19:48 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 15 Aug 2012 17:48:58 +0000 (19:48 +0200)
16 files changed:
com.woltlab.wcf/acpSearchProvider.xml [new file with mode: 0644]
com.woltlab.wcf/package.xml
com.woltlab.wcf/packageInstallationPlugin.xml
wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProvider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderAction.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderEditor.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/builder/ACPSearchProviderCacheBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/ACPSearchHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/ACPSearchResult.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/ACPSearchResultList.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/IACPSearchResultProvider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/MenuItemACPSearchResultProvider.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/search/acp/OptionACPSearchResultProvider.class.php [new file with mode: 0644]
wcfsetup/setup/db/install.sql

diff --git a/com.woltlab.wcf/acpSearchProvider.xml b/com.woltlab.wcf/acpSearchProvider.xml
new file mode 100644 (file)
index 0000000..7b86ff0
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/acpSearchProvider.xsd">
+       <import>
+               <acpsearchprovider name="menuItem">
+                       <classname><![CDATA[wcf\system\search\acp\MenuItemACPSearchResultProvider]]></classname>
+                       <showorder>1</showorder>
+               </acpsearchprovider>
+               <acpsearchprovider name="option">
+                       <classname><![CDATA[wcf\system\search\acp\OptionACPSearchResultProvider]]></classname>
+                       <showorder>2</showorder>
+               </acpsearchprovider>
+       </import>
+</data>
index 9ada6fc3deef79b4909055847025500dbd9da36a..909be5e2aa96e1f09bcd4588347e9438902ab583 100644 (file)
@@ -28,5 +28,6 @@
                <instruction type="clipboardAction">clipboardAction.xml</instruction>
                <instruction type="objectTypeDefinition">objectTypeDefinition.xml</instruction>
                <instruction type="objectType">objectType.xml</instruction>
+               <instruction type="acpSearchProvider">acpSearchProvider.xml</instruction>
        </instructions>
 </package>
index ab7d051a167fdc6a4364235d28e2f34fa130867b..353698136355e7fa826475beddd653ba85296144 100644 (file)
@@ -21,5 +21,6 @@
                <pip name="userOption">wcf\system\package\plugin\UserOptionPackageInstallationPlugin</pip>
                <pip name="packageIcon">wcf\system\package\plugin\PackageIconPackageInstallationPlugin</pip>
                <pip name="sitemap">wcf\system\package\plugin\SitemapPackageInstallationPlugin</pip>
+               <pip name="acpSearchProvider">wcf\system\package\plugin\ACPSearchProviderPackageInstallationPlugin</pip>
        </import>
 </data>
diff --git a/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProvider.class.php b/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProvider.class.php
new file mode 100644 (file)
index 0000000..86354db
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+namespace wcf\data\acp\search\provider;
+use wcf\data\DatabaseObject;
+
+/**
+ * Represents an ACP search provider.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.search.provider
+ * @category   Community Framework
+ */
+class ACPSearchProvider extends DatabaseObject {
+       /**
+        * @see wcf\data\DatabaseObject::$databaseTableName
+        */
+       protected static $databaseTableName = 'acp_search_provider';
+       
+       /**
+        * @see wcf\data\DatabaseObject::$databaseTableIndexName
+        */
+       protected static $databaseTableIndexName = 'providerID';
+}
diff --git a/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderAction.class.php b/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderAction.class.php
new file mode 100644 (file)
index 0000000..a4ff2fa
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+namespace wcf\data\acp\search\provider;
+use wcf\data\AbstractDatabaseObjectAction;
+
+/**
+ * Executes ACP search provider-related actions.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.search.provider
+ * @category   Community Framework
+ */
+class ACPSearchProviderAction extends AbstractDatabaseObjectAction { }
diff --git a/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderEditor.class.php b/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderEditor.class.php
new file mode 100644 (file)
index 0000000..0c23811
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+namespace wcf\data\acp\search\provider;
+use wcf\data\DatabaseObjectEditor;
+
+/**
+ * Provides functions to edit acp search providers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.search.provider
+ * @category   Community Framework
+ */
+class ACPSearchProviderEditor extends DatabaseObjectEditor {
+       /**
+        * @see wcf\data\DatabaseObjectDecorator::$baseClass
+        */
+       protected static $baseClass = 'wcf\data\acp\search\provider\ACPSearchProvider';
+}
diff --git a/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderList.class.php b/wcfsetup/install/files/lib/data/acp/search/provider/ACPSearchProviderList.class.php
new file mode 100644 (file)
index 0000000..bb9fdae
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+namespace wcf\data\acp\search\provider;
+use wcf\data\DatabaseObjectList;
+
+/**
+ * Represents a list of ACP search providers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage data.acp.search.provider
+ * @category   Community Framework
+ */
+class ACPSearchProviderList extends DatabaseObjectList { }
diff --git a/wcfsetup/install/files/lib/system/cache/builder/ACPSearchProviderCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/ACPSearchProviderCacheBuilder.class.php
new file mode 100644 (file)
index 0000000..a2d1802
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+namespace wcf\system\cache\builder;
+use wcf\data\acp\search\provider\ACPSearchProviderList;
+use wcf\system\package\PackageDependencyHandler;
+
+/**
+ * Caches the ACP search providers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category   Community Framework
+ */
+class ACPSearchProviderCacheBuilder implements ICacheBuilder {
+       /**
+        * @see wcf\system\cache\ICacheBuilder::getData()
+        */
+       public function getData(array $cacheResource) {
+               list($cache, $packageID) = explode('-', $cacheResource['cache']);
+               
+               $providerList = new ACPSearchProviderList();
+               $providerList->getConditionBuilder()->add("acp_search_provider.packageID IN (?)", array(PackageDependencyHandler::getInstance()->getDependencies()));
+               $providerList->sqlLimit = 0;
+               $providerList->sqlOrderBy = "acp_search_provider.showOrder ASC";
+               $providerList->readObjects();
+               
+               return $providerList->getObjects();
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/ACPSearchProviderPackageInstallationPlugin.class.php
new file mode 100644 (file)
index 0000000..abafea3
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+namespace wcf\system\package\plugin;
+use wcf\system\cache\CacheHandler;
+use wcf\system\WCF;
+
+/**
+ * This PIP installs, updates or deletes ACP search providers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.package.plugin
+ * @category   Community Framework
+ */
+class ACPSearchProviderPackageInstallationPlugin extends AbstractXMLPackageInstallationPlugin {
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::$className
+        */
+       public $className = 'wcf\data\acp\search\provider\ACPSearchProviderEditor';
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractPackageInstallationPlugin::$tableName
+        */
+       public $tableName = 'acp_search_provider';
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::$tagName
+        */     
+       public $tagName = 'acpsearchprovider';
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::handleDelete()
+        */
+       protected function handleDelete(array $items) {
+               $sql = "DELETE FROM     wcf".WCF_N."_".$this->tableName."
+                       WHERE           providerName = ?
+                                       AND packageID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               foreach ($items as $item) {
+                       $statement->execute(array(
+                               $item['attributes']['name'],
+                               $this->installation->getPackageID()
+                       ));
+               }
+       }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::prepareImport()
+        */
+       protected function prepareImport(array $data) {
+               // get show order
+               $showOrder = (isset($data['elements']['showorder'])) ? $data['elements']['showorder'] : null;
+               $showOrder = $this->getShowOrder($showOrder);
+               
+               return array(
+                       'className' => $data['elements']['classname'],
+                       'providerName' => $data['attributes']['name'],
+                       'showOrder' => $showOrder
+               );
+       }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::findExistingItem()
+        */
+       protected function findExistingItem(array $data) {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_".$this->tableName."
+                       WHERE   providerName = ?
+                               AND packageID = ?";
+               $parameters = array(
+                       $data['providerName'],
+                       $this->installation->getPackageID()
+               );
+               
+               return array(
+                       'sql' => $sql,
+                       'parameters' => $parameters
+               );
+       }
+       
+       /**
+        * @see wcf\system\package\plugin\AbstractXMLPackageInstallationPlugin::cleanup()
+        */     
+       protected function cleanup() {
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.acpSearchProvider-*.php');
+       }
+       
+       /**
+        * @see wcf\system\package\plugin\IPackageInstallationPlugin::uninstall()
+        */
+       public function uninstall() {
+               parent::uninstall();
+               
+               // clear cache immediately
+               CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.acpSearchProvider-*.php');
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/ACPSearchHandler.class.php b/wcfsetup/install/files/lib/system/search/acp/ACPSearchHandler.class.php
new file mode 100644 (file)
index 0000000..0fad920
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+namespace wcf\system\search\acp;
+use wcf\system\application\ApplicationHandler;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+use wcf\util\ClassUtil;
+
+/**
+ * Handles ACP Search.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+class ACPSearchHandler extends SingletonFactory {
+       /**
+        * list of acp search provider
+        * @var array<wcf\data\acp\search\provider\ACPSearchProvider>
+        */
+       protected $cache = null;
+       
+       /**
+        * @see wcf\system\SingletonFactory::init()
+        */
+       protected function init() {
+               $application = ApplicationHandler::getInstance()->getPrimaryApplication();
+               $cacheName = 'acpSearchProvider-'.$application->packageID;
+               
+               CacheHandler::getInstance()->addResource(
+                       $cacheName,
+                       WCF_DIR.'cache/cache.'.$cacheName.'.php',
+                       'wcf\system\cache\builder\ACPSearchProviderCacheBuilder'
+               );
+               
+               $this->cache = CacheHandler::getInstance()->get($cacheName);
+       }
+       
+       /**
+        * Returns a list of search result collections for given query.
+        * 
+        * @param       string          $query
+        * @param       integer         $limit
+        * @return      array<wcf\system\search\acp\ACPSearchResultList>
+        */
+       public function search($query, $limit = 10) {
+               $data = array();
+               $maxResultsPerProvider = ceil($limit / 2);
+               $totalResultCount = 0;
+               
+               foreach ($this->cache as $acpSearchProvider) {
+                       $className = $acpSearchProvider->className;
+                       if (!ClassUtil::isInstanceOf($className, 'wcf\system\search\acp\IACPSearchProvider')) {
+                               throw new SystemException("Class '".$className."' does not implement the interface 'wcf\system\search\acp\IACPSearchProvider'");
+                       }
+                       
+                       $provider = new $className();
+                       $results = $provider->search($query, $maxResultsPerProvider);
+                       
+                       if (!empty($results)) {
+                               $resultList = new ACPSearchResultList();
+                               foreach ($results as $result) {
+                                       $resultList->addResult($result);
+                               }
+                               
+                               $data[] = $resultList;
+                               $totalResultCount += count($resultList);
+                       }
+               }
+               
+               // reduce results per collection until we match the limit
+               while ($totalResultCount > $limit) {
+                       // calculate highest value
+                       $max = 0;
+                       foreach ($data as $resultList) {
+                               $max = max($max, count($resultList));
+                       }
+                       
+                       // remove one result per result list with hits the $max value
+                       foreach ($data as $index => $resultList) {
+                               // break if we hit the $limit during reduction
+                               if ($totalResultCount == $limit) {
+                                       break;
+                               }
+                               
+                               $count = count($resultList);
+                               if ($count == $max) {
+                                       $resultList->reduceResults(1);
+                                       $totalResultCount--;
+                                       
+                                       // the last element of this result was removed
+                                       if ($count == 1) {
+                                               unset($data[$index]);
+                                       }
+                               }
+                       }
+               }
+               
+               return $data;
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/ACPSearchResult.class.php b/wcfsetup/install/files/lib/system/search/acp/ACPSearchResult.class.php
new file mode 100644 (file)
index 0000000..1ed809f
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+namespace wcf\system\search\acp;
+
+/**
+ * Represents an ACP search result.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+class ACPSearchResult {
+       /**
+        * item link
+        * @var string
+        */
+       protected $link = '';
+       
+       /**
+        * item title
+        * @var string
+        */
+       protected $title = '';
+       
+       /**
+        * Creates a new ACP search result.
+        * 
+        * @param       string          $title
+        * @param       string          $link
+        */
+       public function __construct($title, $link) {
+               $this->title = $title;
+               $this->link = $link;
+       }
+       
+       /**
+        * Returns the item link.
+        * 
+        * @return      string
+        */
+       public function getLink() {
+               return $this->link;
+       }
+       
+       /**
+        * Returns the item title.
+        * 
+        * @return      string
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+       
+       /**
+        * @see wcf\system\search\acp\ACPSearchResult::getTitle()
+        */
+       public function __toString() {
+               return $this->getTitle();
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/ACPSearchResultList.class.php b/wcfsetup/install/files/lib/system/search/acp/ACPSearchResultList.class.php
new file mode 100644 (file)
index 0000000..915199d
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+namespace wcf\system\search\acp;
+
+/**
+ * Represents a list of ACP search results.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+class ACPSearchResultList implements \Countable, \Iterator {
+       /**
+        * current iterator index
+        * @var integer
+        */
+       protected $index = 0;
+       
+       /**
+        * result list
+        * @var array<wcf\system\search\acp\ACPSearchResult>
+        */
+       protected $results = array();
+       
+       /**
+        * Adds a result to the collection.
+        * 
+        * @param       wcf\system\search\acp\ACPSearchResult   $result
+        */
+       public function addResult(ACPSearchResult $result) {
+               $this->results[] = $result;
+       }
+       
+       /**
+        * Reduces the result collection by given count. If the count is higher
+        * than the actual amount of results, the results will be cleared.
+        * 
+        * @param       integer         $count
+        */
+       public function reduceResults($count) {
+               // more results than available should be whiped, just set it to 0
+               if ($count >= count($this->results)) {
+                       $this->results = array();
+               }
+               else {
+                       while ($count > 0) {
+                               array_pop($this->results);
+                               $count--;
+                       }
+               }
+               
+               // rewind index to prevent bad offsets
+               $this->rewind();
+       }
+       
+       /**
+        * Sorts results by title.
+        */
+       public function sort() {
+               usort($this->results, function($a, $b) {
+                       return strcmp($a->getTitle(), $b->getTitle());
+               });
+       }
+       
+       /**
+        * @see \Countable::count()
+        */
+       public function count() {
+               return count($this->objects);
+       }
+       
+       /**
+        * @see \Iterator::current()
+        */
+       public function current() {
+               return $this->results[$this->index];
+       }
+       
+       /**
+        * @see \Iterator::key()
+        */
+       public function key() {
+               return $this->index;
+       }
+       
+       /**
+        * @see \Iterator::next()
+        */
+       public function next() {
+               ++$this->index;
+       }
+       
+       /**
+        * @see \Iterator::rewind()
+        */
+       public function rewind() {
+               $this->index = 0;
+       }
+       
+       /**
+        * @see \Iterator::valid()
+        */
+       public function valid() {
+               return isset($this->results[$this->index]);
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/IACPSearchResultProvider.class.php b/wcfsetup/install/files/lib/system/search/acp/IACPSearchResultProvider.class.php
new file mode 100644 (file)
index 0000000..8fc375b
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+namespace wcf\system\search\acp;
+
+/**
+ * Default implementation for ACP search providers.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+interface IACPSearchResultProvider {
+       /**
+        * Returns a list of seach results for given query.
+        * 
+        * @param       string          $query
+        * @param       integer         $limit
+        * @return      array<wcf\system\search\acp\ACPSearchResult>
+        */
+       public function search($query, $limit = 5);
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/MenuItemACPSearchResultProvider.class.php b/wcfsetup/install/files/lib/system/search/acp/MenuItemACPSearchResultProvider.class.php
new file mode 100644 (file)
index 0000000..3d2b1f9
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+namespace wcf\system\search\acp;
+use wcf\system\application\ApplicationHandler;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\request\LinkHandler;
+use wcf\system\WCF;
+
+/**
+ * ACP search provider for menu items.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+class MenuItemACPSearchResultProvider implements IACPSearchResultProvider {
+       /**
+        * @see wcf\system\search\acp\IACPSearchResultProvider::search()
+        */
+       public function search($query, $limit = 5) {
+               $results = array();
+               
+               // search by language item
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("languageID = ?", array(WCF::getLanguage()->languageID));
+               $conditions->add("languageItem LIKE ?", array('wcf.acp.option.'.$query.'%'));
+               $conditions->add("packageID IN (?)", array(PackageDependencyHandler::getInstance()->getDependencies()));
+               
+               // get available abbrevations
+               $packageIDs = array(ApplicationHandler::getInstance()->getActiveApplication()->packageID);
+               foreach (ApplicationHandler::getInstance()->getDependentApplications() as $application) {
+                       $packageIDs[] = $application->packageID;
+               }
+               
+               $searchConditions = array();
+               $searchString = '';
+               foreach ($packageIDs as $packageID) {
+                       if (!empty($searchString)) {
+                               $searchString .= " OR ";
+                       }
+                       
+                       $searchString .= "languageItem LIKE ?";
+                       $searchConditions[] = ApplicationHandler::getInstance()->getAbbrevation($packageID) . '.acp.menu.link.'.$query.'%';
+               }
+               $conditions->add($searchString, $searchConditions);
+               
+               $sql = "SELECT          languageItem, languageItemValue
+                       FROM            wcf".WCF_N."_language_item
+                       ".$conditions."
+                       ORDER BY        languageItemValue ASC";
+               $statement = WCF::getDB()->prepareStatement($sql, ($limit * 2)); // use double limit here since categories are matched too
+               $statement->execute($conditions->getParameters());
+               $languageItems = array();
+               while ($row = $statement->fetchArray()) {
+                       $languageItems[$row['languageItem']] = $row['languageItemValue'];
+               }
+               
+               if (empty($languageItems)) {
+                       return array();
+               }
+               
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("menuItem IN (?)", array(array_keys($languageItems)));
+               $conditions->add("menuItemLink <> ''");
+               
+               $sql = "SELECT  menuItem, menuItemLink
+                       FROM    wcf".WCF_N."_acp_menu_item
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql, $limit);
+               $statement->execute($conditions->getParameters());
+               
+               while ($row = $statement->fetchArray()) {
+                       $results[] = new ACPSearchResult($languageItems[$row['menuItem']], $row['menuItemLink']);
+               }
+               
+               return $results;
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/search/acp/OptionACPSearchResultProvider.class.php b/wcfsetup/install/files/lib/system/search/acp/OptionACPSearchResultProvider.class.php
new file mode 100644 (file)
index 0000000..f56aa02
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+namespace wcf\system\search\acp;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\package\PackageDependencyHandler;
+use wcf\system\request\LinkHandler;
+use wcf\system\WCF;
+
+/**
+ * ACP search provider for options.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.search.acp
+ * @category   Community Framework
+ */
+class OptionACPSearchResultProvider implements IACPSearchResultProvider {
+       /**
+        * @see wcf\system\search\acp\IACPSearchResultProvider::search()
+        */
+       public function search($query, $limit = 5) {
+               $results = array();
+               
+               // search by language item
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("languageID = ?", array(WCF::getLanguage()->languageID));
+               $conditions->add("languageItem LIKE ?", array('wcf.acp.option.'.$query.'%'));
+               $conditions->add("packageID IN (?)", array(PackageDependencyHandler::getInstance()->getDependencies()));
+               
+               $sql = "SELECT          languageItem, languageItemValue
+                       FROM            wcf".WCF_N."_language_item
+                       ".$conditions."
+                       ORDER BY        languageItemValue ASC";
+               $statement = WCF::getDB()->prepareStatement($sql, $limit);
+               $statement->execute($conditions->getParameters());
+               $languageItems = array();
+               $optionNames = array();
+               while ($row = $statement->fetchArray()) {
+                       $optionName = str_replace('wcf.acp.option.', '', $row['languageItem']);
+                       
+                       $languageItems[$optionName] = $row['languageItemValue'];
+                       $optionNames[] = $optionName;
+               }
+               
+               if (empty($optionNames)) {
+                       return array();
+               }
+               
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add("option.optionName IN (?)", array($optionNames));
+               
+               $sql = "SELECT          option.optionName, option.categoryName, option_category.categoryID
+                       FROM            wcf".WCF_N."_option option
+                       LEFT JOIN       wcf".WCF_N."_option_category option_category
+                       ON              (option_category.categoryName = option.categoryName)
+                       ".$conditions;
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute($conditions->getParameters());
+               
+               while ($row = $statement->fetchArray()) {
+                       $link = LinkHandler::getInstance()->getLink('Option', array('id' => $row['categoryID']), '#'.$row['categoryName']);
+                       $results[] = new ACPSearchResult($languageItems[$row['optionName']], $link);
+               }
+               
+               return $results;
+       }
+}
index c6efbd941ea2799bb48f5b6809322492bd127d35..909c293bb92a03e339648490519202ce69a75225 100644 (file)
@@ -12,6 +12,16 @@ CREATE TABLE wcf1_acp_menu_item (
        UNIQUE KEY menuItem (menuItem, packageID)
 );
 
+DROP TABLE IF EXISTS wcf1_acp_search_provider;
+CREATE TABLE wcf1_acp_search_provider (
+       providerID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+       packageID INT(10) NOT NULL,
+       providerName VARCHAR(255) NOT NULL DEFAULT '',
+       className VARCHAR(255) NOT NULL DEFAULT '',
+       showOrder INT(10) NOT NULL DEFAULT 0,
+       UNIQUE KEY providerName (providerName, packageID)
+);
+
 DROP TABLE IF EXISTS wcf1_acp_session;
 CREATE TABLE wcf1_acp_session (
        sessionID CHAR(40) NOT NULL PRIMARY KEY,
@@ -767,6 +777,8 @@ CREATE TABLE wcf1_user_to_language (
 /**** foreign keys ****/
 ALTER TABLE wcf1_acp_menu_item ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
 
+ALTER TABLE wcf1_acp_search_provider ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
+
 ALTER TABLE wcf1_acp_session ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
 ALTER TABLE wcf1_acp_session ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;