Commit 3e6e4034 authored by speedprogs_de's avatar speedprogs_de
Browse files

implemented extension search

git-svn-id: https://svn.typo3.org/TYPO3v4/Extensions/terfe/branches/ter_fe2@53034 735d13b6-9817-0410-8766-e36946ffe9aa
parent f0c2c981
......@@ -87,23 +87,38 @@
/**
* Index action, shows an overview
* Index action, displays extension list
*
* @param string $sorting Sort extensions by this key
* @param array $search Search params for extension list
* @return void
* @dontvalidate $search
*/
public function indexAction($sorting = 'updated') {
// Get all extensions
$this->view->assign('extensions', $this->getExtensions($sorting));
$this->view->assign('sorting', $sorting);
public function indexAction(array $search = array()) {
// Get extension list
if (!empty($this->settings['show']['extensionSearch'])) {
$this->view->assign('extensions', $this->getExtensions($search));
$this->view->assign('search', $search);
} else {
$this->view->assign('extensions', $this->extensionRepository->findAll());
}
// Get all categories
$categories = $this->categoryRepository->findAll();
$this->view->assign('categories', $categories);
if (!empty($this->settings['show']['categoryOverview'])) {
$categories = $this->categoryRepository->findAll();
$this->view->assign('categories', $categories);
}
// Get all tags
if (!empty($this->settings['show']['tagOverview'])) {
$tags = $this->tagRepository->findAll();
$this->view->assign('tags', $tags);
}
// Get authors
$authors = $this->authorRepository->findByLatestExtensionVersion();
$this->view->assign('authors', $authors);
if (!empty($this->settings['show']['authorOverview'])) {
$authors = $this->authorRepository->findByLatestExtensionVersion();
$this->view->assign('authors', $authors);
}
}
......@@ -300,28 +315,64 @@
/**
* Returns all extensions by
* Returns all / filtered extensions
*
* @param string $sorting Sort extensions by this key
* @param array $options Options for extension list
* @return Tx_Extbase_Persistence_ObjectStorage Objects
*/
protected function getExtensions(&$sorting) {
protected function getExtensions(array &$options) {
// Direction
$desc = Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING;
$asc = Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING;
$direction = $desc;
if (!empty($options['direction'])) {
$direction = ($options['direction'] === 'asc' ? $asc : $desc);
}
// Get last needle
$session = $this->objectManager->get('Tx_TerFe2_Persistence_Session');
$lastNeedle = $session->get('lastNeedle');
// Sorting
$sortings = array(
'updated' => 'lastVersion.uploadDate',
'downloads' => 'downloads',
'title' => 'lastVersion.title',
);
if (empty($sortings[$sorting])) {
$sorting = 'updated';
$sorting = $sortings['updated'];
if (!empty($options['sorting'])) {
// Set direction to ASC when sorting by title
if (!empty($sortings[$options['sorting']])) {
$sorting = $sortings[$options['sorting']];
if (empty($options['direction'])) {
$direction = $desc;
if ($options['sorting'] === 'title') {
$direction = $asc;
$options['direction'] = 'asc';
}
}
}
// Sort by downloads when searching
if (!empty($options['needle']) && (empty($lastNeedle) || $lastNeedle !== $options['needle'])) {
$sorting = $sortings['downloads'];
$options['sorting'] = 'downloads';
$direction = $desc;
}
}
// Direction
$desc = Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING;
$asc = Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING;
$direction = ($sorting === 'title' ? $asc : $desc);
// Set new needle
$session->set('lastNeedle', $options['needle']);
// Ordering
$ordering = array($sorting => $direction);
// Return sorted list of all extensions
if (empty($options['needle'])) {
return $this->extensionRepository->findAll(0, 0, $ordering);
}
return $this->extensionRepository->findAllBySortingAndDirection($sortings[$sorting], $direction);
// Return search result
return $this->extensionRepository->findBySearchWordsAndFilters($options['needle'], array(), $ordering);
}
}
......
......@@ -215,6 +215,12 @@
*/
protected $softwareRelations;
/**
* Software relations (for search index)
* @var string
*/
protected $softwareRelationList;
/**
* Parent extension object
* @var Tx_TerFe2_Domain_Model_Extension
......@@ -222,6 +228,12 @@
*/
protected $extension;
/**
* Key of the extension
* @var string
*/
protected $extensionKey;
/**
* Extension provider
* @var string
......@@ -995,6 +1007,7 @@
*/
public function addSoftwareRelation(Tx_TerFe2_Domain_Model_Relation $softwareRelation) {
$this->softwareRelations->attach($softwareRelation);
$this->buildSoftwareRelationList($this->softwareRelations);
}
......@@ -1006,6 +1019,43 @@
*/
public function removeSoftwareRelation(Tx_TerFe2_Domain_Model_Relation $softwareRelation) {
$this->softwareRelations->detach($softwareRelation);
$this->buildSoftwareRelationList($this->softwareRelations);
}
/**
* Build softwareRelationList
*
* @param Tx_Extbase_Persistence_ObjectStorage<Tx_TerFe2_Domain_Model_Relation> $softwareRelations Relations
* @return void
*/
public function buildSoftwareRelationList(Tx_Extbase_Persistence_ObjectStorage $softwareRelations) {
$relations = array();
foreach ($softwareRelations as $relation) {
$relations[] = $relation->getRelationKey();
}
$this->setSoftwareRelationList(implode(',', $relations));
}
/**
* Setter for softwareRelationList
*
* @param string $softwareRelationList Software relations
* @return void
*/
public function setSoftwareRelationList($softwareRelationList) {
$this->softwareRelationList = $softwareRelationList;
}
/**
* Getter for softwareRelationList
*
* @return string Software relations
*/
public function getSoftwareRelationList() {
return $this->softwareRelationList;
}
......@@ -1017,6 +1067,7 @@
*/
public function setExtension(Tx_TerFe2_Domain_Model_Extension $extension) {
$this->extension = $extension;
$this->setExtensionKey($extension->getExtKey());
}
......@@ -1030,6 +1081,27 @@
}
/**
* Setter for extensionKey
*
* @param string $extensionKey Key of the extension
* @return void
*/
public function setExtensionKey($extensionKey) {
$this->extensionKey = $extensionKey;
}
/**
* Getter for extensionKey
*
* @return string Key of the extension
*/
public function getExtensionKey() {
return $this->extensionKey;
}
/**
* Setter for extensionProvider
*
......
......@@ -36,7 +36,7 @@
* @param array $ordering Ordering <-> Direction
* @return Tx_Extbase_Persistence_QueryInterface
*/
public function createQuery($offset = 0, $count = 0, $ordering = array()) {
public function createQuery($offset = 0, $count = 0, array $ordering = array()) {
$query = parent::createQuery();
if (!empty($offset)) {
......@@ -78,14 +78,15 @@
/**
* Returns all objects ordered by given sorting and direction
* Returns all objects
*
* @param string $sorting Sort result by this key
* @param string $direction Sorting order
* @param string $offset Offset to start with
* @param string $count Count of result
* @param string $ordering Ordering <-> Direction
* @return Tx_Extbase_Persistence_ObjectStorage Objects
*/
public function findAllBySortingAndDirection($sorting, $direction) {
$query = $this->createQuery(0, 0, array($sorting => $direction));
public function findAll($offset = 0, $count = 0, array $ordering = array()) {
$query = $this->createQuery($offset, $count, $ordering);
return $query->execute();
}
......
......@@ -36,11 +36,13 @@
* @param string $ordering Ordering <-> Direction
* @return Tx_Extbase_Persistence_ObjectStorage Objects
*/
public function findAll($offset = 0, $count = 0, $ordering = array()) {
public function findAll($offset = 0, $count = 0, array $ordering = array()) {
if (empty($ordering)) {
$ordering = array('lastVersion.title' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING);
}
$query = $this->createQuery($offset, $count, $ordering);
// Filter empty title
$query->matching($query->logicalNot($query->equals('lastVersion.title', '')));
return $query->execute();
}
......@@ -129,6 +131,47 @@
}
/**
* Search extensions by search words and filters
*
* TODO:
* - Implement filters
* - Use real relevance ordering from uid order
*
* @param string $needle Search string
* @param array $filters Filter extension list
* @param array $ordering $ordering Ordering <-> Direction
* @return Tx_Extbase_Persistence_ObjectStorage Objects
*/
public function findBySearchWordsAndFilters($searchWords = NULL, array $filters = NULL, array $ordering = NULL) {
$statement = '
SELECT DISTINCT extension, MATCH (extension_key,title,description,upload_comment,software_relation_list) AGAINST (?) AS score
FROM tx_terfe2_domain_model_version
WHERE MATCH (extension_key,title,description,upload_comment,software_relation_list) AGAINST (?)
GROUP BY extension
ORDER BY score DESC
';
// Workaround while extbase doesn't support MATCH
$query = $this->createQuery();
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
$query->statement($statement, array($searchWords, $searchWords));
$rows = $query->execute();
unset($query);
// Workaround to enable paginate
$uids = array();
foreach ($rows as $row) {
$uids[] = (int) $row['extension'];
}
$query = $this->createQuery();
$query->setOrderings($ordering);
$query->matching($query->in('uid', $uids));
return $query->execute();
}
/**
* Returns count of extensions with given extKey and versionNumber
*
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_author'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_author']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_author'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_author']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'name,email,company,forge_link,username,versions',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_category'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_category']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_category'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_category']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'title,description',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_experience'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_experience']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_experience'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_experience']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'date_time,comment,rating',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_extension'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_extension']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_extension'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_extension']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'ext_key,forge_link,hudson_link,last_update,last_maintained,categories,tags,versions,last_version,frontend_user,downloads',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_media'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_media']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_media'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_media']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'title,type,language,source,description',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_relation'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_relation']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_relation'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_relation']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'relation_type,relation_key,minimum_version,maximum_version',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_tag'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_tag']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_tag'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_tag']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'title,extensions',
),
......
......@@ -3,8 +3,8 @@
die ('Access denied.');
}
$TCA['tx_terfe2_domain_model_version'] = array(
'ctrl' => $TCA['tx_terfe2_domain_model_version']['ctrl'],
$GLOBALS['TCA']['tx_terfe2_domain_model_version'] = array(
'ctrl' => $GLOBALS['TCA']['tx_terfe2_domain_model_version']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'title,description,version_number,version_string,upload_date,upload_comment,download_counter,frontend_download_counter,state,em_category,load_order,priority,shy,internal,do_not_load_in_fe,uploadfolder,clear_cache_on_load,module,create_dirs,modify_tables,lock_type,cgl_compliance,cgl_compliance_note,review_state,manual,media,experiences,software_relations,author,file_hash,extension_provider,has_zip_file,has_images',
),
......
......@@ -79,11 +79,26 @@ plugin.tx_terfe2 {
}
show {
# cat=TER Frontend/settings/5000; type=boolean; label=Show author extensions: Show all extensions of an author on detail view
# cat=TER Frontend/settings/5000; type=boolean; label=Show extension search: Show extension search above extension list
extensionSearch = 1
# cat=TER Frontend/settings/5010; type=boolean; label=Show author extensions: Show all extensions of an author on detail view
authorExtensions = 0
# cat=TER Frontend/settings/5010; type=boolean; label=Show category extensions: Show all extensions of a category on detail view
# cat=TER Frontend/settings/5020; type=boolean; label=Show author overview: Show all authors in index list
authorOverview = 0
# cat=TER Frontend/settings/5030; type=boolean; label=Show category extensions: Show all extensions of a category on detail view
categoryExtensions = 0
# cat=TER Frontend/settings/5040; type=boolean; label=Show category overview: Show all categories in index list
categoryOverview = 0
# cat=TER Frontend/settings/5050; type=boolean; label=Show tag extensions: Show all extensions of a tag on detail view
tagExtensions = 0
# cat=TER Frontend/settings/5060; type=boolean; label=Show tag overview: Show all tags in index list
tagOverview = 0
}
}
......
......@@ -38,8 +38,13 @@ plugin.tx_terfe2 {
}
show {
extensionSearch = {$plugin.tx_terfe2.settings.show.extensionSearch}
authorExtensions = {$plugin.tx_terfe2.settings.show.authorExtensions}
authorOverview = {$plugin.tx_terfe2.settings.show.authorOverview}
categoryExtensions = {$plugin.tx_terfe2.settings.show.categoryExtensions}
categoryOverview = {$plugin.tx_terfe2.settings.show.categoryOverview}
tagExtensions = {$plugin.tx_terfe2.settings.show.tagExtensions}
tagOverview = {$plugin.tx_terfe2.settings.show.tagOverview}
}
}
......
......@@ -77,12 +77,15 @@
<label index="tx_terfe2_task_createExtensions">Create extensions if not exist</label>
<label index="tx_terfe2_task_extensionFilePath">Relative path to extension files directory</label>
<label index="tx_terfe2_task_forceRecalculation">Force recalculation of extension downloads</label>
<label index="tx_terfe2_task_validityTime">Entries are valid for this time (seconds)</label>
<label index="tx_terfe2_task_updateextensionlisttask.name">Get new extensions</label>
<label index="tx_terfe2_task_updateextensionlisttask.description">Get new extensions in ter directory</label>
<label index="tx_terfe2_task_updatedownloadstask.name">Update download count</label>
<label index="tx_terfe2_task_updatedownloadstask.description">Update the number of downloads for the latest versions</label>
<label index="tx_terfe2_task_createextensionfilestask.name">Create extension related files</label>
<label index="tx_terfe2_task_createextensionfilestask.description">Create extension related files like zip file or images</label>
<label index="tx_terfe2_task_searchindextask.name">Update search index</label>
<label index="tx_terfe2_task_searchindextask.description">Update search index with new versions</label>
<label index="tx_terfe2_provider_mirrorprovider.name">Mirror Servers</label>
<label index="tx_terfe2_provider_fileprovider.name">Local Filesystem</label>
<label index="tx_terfe2_provider_soapprovider.name">SOAP Server</label>
......@@ -136,6 +139,8 @@
<label index="tab.tags">Tags</label>
<label index="tab.authors">Authors</label>
<label index="sorting">Sort by</label>
<label index="sorting.auto">Automatically</label>
<label index="sorting.updated">Last update</label>
<label index="sorting.downloads">Downloads</label>
<label index="sorting.title">Title</label>
......@@ -194,6 +199,8 @@
<label index="manual">Manual</label>
<label index="sort_extensions_by">Sort by</label>
<label index="submit_ordering_form">Sort</label>
<label index="search">Search</label>
<label index="extensions_found">%d extensions found</label>
<label index="back_to_list">Back to list</label>
<label index="back_to_extension_list">Back to Extension List</label>
......
......@@ -2,6 +2,10 @@
<f:if condition="{extensions}">
<f:then>
<div class="ter-ext-list-count">
<f:translate key="extensions_found" arguments="{0: '{f:count(subject : extensions)}'}" />
</div>
<f:widget.paginate objects="{extensions}" as="paginateExtensions" configuration="{itemsPerPage: settings.listCount, insertAbove: 0, insertBelow: 1}">
<f:for each="{paginateExtensions}" as="extension">
<div class="ter-ext-list-row cl">
......
{namespace terfe2=Tx_TerFe2_ViewHelpers}
<div id="ter-ext-list-sort">
<form method="get" action="{f:uri.action(controller:'Extension', action:'index', noCacheHash: 1)}">
<f:form.select name="tx_terfe2_pi1[sorting]" class="jsSubmit" options="{
NULL: '{f:translate(key:\'sort_extensions_by\')}',
updated: '{f:translate(key:\'sorting.updated\')}',
downloads: '{f:translate(key:\'sorting.downloads\')}',
title: '{f:translate(key:\'sorting.title\')}'
}" />
</form>
</div>
\ No newline at end of file
{namespace terfe2=Tx_TerFe2_ViewHelpers}
<div class="ter-ext-list-search">
<form method="get" action="{f:uri.action(controller:'Extension', action:'index', noCacheHash: 1)}">
<f:form.textfield name="tx_terfe2_pi1[search][needle]" id="ter-ext-list-search-needle" value="{search.needle}" />
<f:form.submit value="{f:translate(key: 'search')}" class="bu" />
<span class="ter-ext-list-search-sorting cl">
<label for="ter-ext-list-search-sorting"><f:translate key="sorting" />: </label>
<f:form.select name="tx_terfe2_pi1[search][sorting]" id="ter-ext-list-search-sorting" class="jsSubmit" value="{search.sorting}" options="{
updated: '{f:translate(key:\'sorting.updated\')}',
downloads: '{f:translate(key:\'sorting.downloads\')}',
title: '{f:translate(key:\'sorting.title\')}'
}" />
</span>
</form>
</div>
\ No newline at end of file
<f:layout name="Default" />
<f:section name="main">
<f:render partial="ExtensionListSortingForm" arguments="{sorting : sorting, direction : direction}" />
<f:if condition="{settings.show.extensionSearch}">
<f:render partial="ExtensionSearchForm" arguments="{search : search}" />
</f:if>
<f:render partial="ExtensionList" arguments="{extensions : extensions}" />
<!-- <f:render partial="CategoryList" arguments="{categories : categories}" /> -->
<!-- <f:render partial="TagList" arguments="{tags : tags}" /> -->
<!-- <f:render partial="AuthorList" arguments="{authors: authors}" /> -->
<f:if condition="{settings.show.categoryOverview}">
<f:render partial="CategoryList" arguments="{categories : categories}" />
</f:if>
<f:if condition="{settings.show.tagOverview}">
<f:render partial="TagList" arguments="{tags : tags}" />
</f:if>
<f:if condition="{settings.show.authorOverview}">
<f:render partial="AuthorList" arguments="{authors: authors}" />
</f:if>
</f:section>
\ No newline at end of file
{namespace terfe2=Tx_TerFe2_ViewHelpers}
<f:layout name="Default" />
<f:section name="main">
<!-- TODO -->
<h2><f:translate key="single_tag"/></h2>
<div class="ter-tag-info">
<table>
<tr>
<th><f:translate key="tx_terfe2_domain_model_tag.title" />:</td>
<td>{tag.title}</td>
</tr>
</table>
</div>
<f:if condition="{settings.show.tagExtensions}">
<h3><f:translate key="tag_extensions"/></h3>
<div class="ter-tag-extensions">
<f:render partial="ExtensionList" arguments="{extensions : tagExtensions}" />
</div>
</f:if>