Watch
GitHub Core
Show your support for Zikula! Sign up at Github account and watch the Core project!
GitHub Modules
- rgasch responded to »Zikula: Not Ready for Prime Time?« 10:25 AM
- Paustian responded to »Multiple Errors Migrating Dizkus 3,1 to Dizkus 3.2« 05:19 AM
- trichers created topic »Mobile Theme html5 and link with tel:« 02:15 AM
- espaan responded to »Interesting jQuery Javascript projects...« 17. Jun
- incasas responded to »Migrating Postcalendar 6.2 to Postcalendar 8.0« 17. Jun
- krator responded to »Error converting RATINGS and WEBLINKS« 16. Jun
- bartl responded to »Titles and Slogans and Descs, oh my!« 15. Jun
Login
Wiki » ModuleProgrammingPart4
Additions
Now, when the user submits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "FAQ_searchapi_search".
Deletions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "FAQ_searchapi_search".
Additions
To be able to find your items via the normal search function provided by Zikula, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This is done for the following reasons:
Deletions
To be able to find your items via the normal search function provided by Zikula 0.8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastic change from the Zikula .76 API, where the plugins had to create the output HTML by themselves, and it is done for the following reasons:
Additions
Passing of module specific variables
It is possible to pass variables specific for your module by adding inputs to your form like<input name="modvar[yourmodulename][yourparametername]" value="yourparametervalue" type="hidden">
You will receive the variable in the args array passed to your yourmodule_pnsearchapi_searchfunction. You will thus be able to use the parameters passed to modify your search implementation.
Additions
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastic change from the Zikula .76 API, where the plugins had to create the output HTML by themselves, and it is done for the following reasons:
2. Paging, browsing, and sorting can all be done through SQL. This performs a lot better than doing so in PHP (for "large" result sets - wherever that threshold is).
.
Deletions
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastical change from the Zikula .76 API, where the plugins had to create the output HTML by themselves, and it is done for the following reasons:
Deletions
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastical change from the Zikula .76 API, where the plugins had to create the output HTML by themselves, and it is done for the following reasons:
2. Paging, browsing, and sorting can all be done through SQL. This performs a lot better than doing so in PHP (for "large" result sets - where ever that treshold is).
.
_EDITED
2008-02-08 22:22:49
by Paustian
[ ]
Additions
To be able to find your items via the normal search function provided by Zikula 0.8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
Additions
To be able to find your items via the normal search function provided by Zikula 0.8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
3. All the search HTML is concatenated and presented to the user as the complete search form.
.
Deletions
To be able to find your items via the normal search function provided by Zikula .8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
Deletions
To be able to find your items via the normal search function provided by Zikula .8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
3. All the search HTML is concatenated and presented to the user a the complete search form.
.
_EDITED
2007-12-19 10:57:48
by espaan
[ forgot next step text ]
Additions
Next step: Module Programming Part 5
Deletions
Module Programming Part 5
_EDITED
2007-12-19 10:56:23
by espaan
[ Added next step programming part 5 ]
Additions
Module Programming Part 5
Deletions
_EDITED
2007-05-25 21:27:58
by
[ ]
Additions
Deletions
Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.
_EDITED
2007-05-24 22:12:50
by
[ ]
Additions
This post processing is done with the "xxx_yyy_check" API function (where xxx=module name and yyy=search function name). This function is called by the search API and passed the database data for the found item:
The ampersands are *very* important here! We need to modify the $args variable
function faq_searchapi_search_check(&$args)
It is also possible to do late access checking at this time - but it should be avoided since the displayed count of found items will be too big if you filter out some items. If you need to use late access checking then return true/false signalling access allowed/denied.
_EDITED
2007-05-24 21:58:56
by
[ ]
Additions
function faq_searchapi_info()
You need to implement the "options" function that returns the input form's HTML code. Here's an example from the FAQ module:
function faq_searchapi_options($args)
<label for="active_faqs"><!--[pnml name="_FAQ_CATEGORIES]--></label>
</div>
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "FAQ_searchapi_search".
Deletions
function Admin_Messages_searchapi_info()
You need to implement the "options" function that returns the input form's HTML code. Here's an example from the Admin_Messages module:
function Admin_Messages_searchapi_options($args)
Additions
Next step: Module Programming Part 5
Deletions
Module Programming Part 5
Additions
Module Programming Part 5
Deletions
Additions
3. The search plugins are only activated on the first page. Subsequent browsing through the results is done much more efficiently by browsing through the result table.
Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.Implementation details
One problem is that the search module won't be informed when a session is deleted. This means the result table will grow and grow, keeping up with an ever increasing amount of unused results stored for unused sessions. To avoid this the system adds a timestamp to each found item. Items older than some hours are automatically deleted.Deletions
Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.
Additions
Adding URLs and last minute access checking
You may wonder why there was no "link-to-item" URL in the above code examples. This is because URLs must be generated via the pnModUrl() function - and we only want to call that function for the items actually displayed to the end user. So the item URL is added in a post processing step for each item displayed to the user.This post processing is done with the "xxx_yyy_check" API function (where xxx=module name and yyy=search function name). This function is called by the search API and passed the database data for the found item:
The ampersands are *very* important here! We need to modify the $args variable
function faq_searchapi_search_check(&$args)
Fetch database row and the "extra" value in this row
$datarow = &$args['datarow'];
$faqId = $datarow['extra'];
Write URL into the data
$datarow['url'] = pnModUrl('FAQ', 'user', 'display', array('faqid' => $faqId));
User has access to this item - so return true
$datarow = &$args['datarow'];
$faqId = $datarow['extra'];
Write URL into the data
$datarow['url'] = pnModUrl('FAQ', 'user', 'display', array('faqid' => $faqId));
User has access to this item - so return true
Additions
1. title - the name of the module (must match the name used in the search options template exactly).
The example here is from the FAQ module:function faq_searchapi_info()
return array('title' => 'FAQ',
'functions' => array('FAQ' => 'search'));
function faq_searchapi_options($args)
if (SecurityUtil::checkPermission∞( 'FAQ::', '::', ACCESS_READ)) {
return ;
<input type="checkbox" id="active_faqs" name="active[FAQ]" value="1" checked="checked" />
$pnRender = new pnRender('FAQ');
return $pnRender->fetch('faq_search_options.htm');
return $pnRender->fetch('faq_search_options.htm');
<label for="active_faqs"><!--[pnml name="_FAQ_CATEGORIES]--></label>
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "FAQ_searchapi_search".
Deletions
1. title - the name of the module (must match the module directoy name exactly since it is used to locate the module later on).
The example here is from the Admin_Messages module:function Admin_Messages_searchapi_info()
return array('title' =>'Admin_Messages',
'functions' => array('Admin_Messages' => 'search'));
function Admin_Messages_searchapi_options($args)
if (SecurityUtil::checkPermission('Admin_Messages:search∞:', '::', ACCESS_READ))
{
{
Make sure we have language defines available in the templates
pnModLangLoad('Admin_Messages', 'admin');
Create output render object
$pnRender = new pnRender('Admin_Messages');
Assign various module variables for the template
$pnRender->assign(pnModGetVar('Admin_Messages'));
$pnRender->assign('active', (isset($args['active']) && isset($args['active']['Admin_Messages']))
_EDITED
2007-05-24 21:55:24
by
[ ]
Additions
Try also to take a look at the template from the User module which is a bit simpler.
A very important step here is to "decorate" all data in the result table with the current user's session ID. This is done so multiple users can do searching simultaneously without seeing each others results.
function faq_searchapi_search($args)
FROM $faqtable
pnModLangLoad('Admin_Messages', 'admin');
Create output render object
$pnRender = new pnRender('Admin_Messages');
Assign various module variables for the template
$pnRender->assign(pnModGetVar('Admin_Messages'));
$pnRender->assign('active', (isset($args['active']) && isset($args['active']['Admin_Messages']))
| (!isset($args['active']))); $pnRender->assign('activeonly', (isset($args['modvar']) && isset($args['modvar']['Admin_Messages']) && isset($args['modvar']['Admin_Messages']['activeonly'])) | !isset($args['modvar'])); return $pnRender->fetch('admin_messages_search_options.htm'); else return ; <input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" <!--[if $active]-->checked="checked"<!--[/if]--> /> <label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGES_SEARCH]--></label> <!--[if $allowsearchinactive]-->
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" <!--[if $activeonly]-->checked="checked"<!--[/if]--> />
<!--[/if]--><label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGES_ACTIVEONLY]--></label> </div>%% Try also to take a look at the template from the User module which is a bit simpler. Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "Admin_Messages_searchapi_search". |
Additions
1. title - the name of the module (must match the module directoy name exactly since it is used to locate the module later on).
You need to implement the "options" function that returns the input form's HTML code. Here's an example from the Admin_Messages module:
'functions' => array('Admin_Messages' => 'search'));
Make sure we have language defines available in the templates
A very important step here is to "decorate" all data in the result table with the current user's session ID. This is done so multiple users can do searching simultaneously without seeing each others results.
3. extra - any data needed to create a link to the item (typically the item ID).
5. module - exact name of the module that owns the item.
6. session - the session ID of the current user.
Here is how it is done in the FAQ API:5. module - exact name of the module that owns the item.
6. session - the session ID of the current user.
function faq_searchapi_search($args)
$faqtable = $pntable['faqanswer'];
$faqcolumn = $pntable['faqanswer_column'];
$searchTable = $pntable['search_result'];
$searchColumn = $pntable['search_result_column'];
$where = search_construct_where($args,
$sessionId = session_id();
$faqcolumn = $pntable['faqanswer_column'];
$searchTable = $pntable['search_result'];
$searchColumn = $pntable['search_result_column'];
$where = search_construct_where($args,
array($faqcolumn['question'],
$faqcolumn['answer']),
- ;
$faqcolumn[question] as title,
$faqcolumn[answer] as text,
$faqcolumn[faqid] as id,
$faqcolumn[cr_date] as date
$faqcolumn[answer] as text,
$faqcolumn[faqid] as id,
$faqcolumn[cr_date] as date
$searchColumn[extra],
$searchColumn[session])
$searchColumn[session])
$item = $result->GetRowAssoc?(2);
if (SecurityUtil::checkPermission('FAQ∞::', "$item[id]::", ACCESS_READ)) {
if (SecurityUtil::checkPermission('FAQ∞::', "$item[id]::", ACCESS_READ)) {
. '\ . DataUtil::formatForStore($item['title∞']) . '\', '
. '\ . DataUtil::formatForStore($item['text∞']) . '\', '
. '\ . DataUtil::formatForStore($item['id∞']) . '\', '
. '\ . DataUtil::formatForStore($item['date∞']) . '\', '
. '\ . 'FAQ' . '\', '
. '\ . DataUtil::formatForStore($sessionId∞) . '\')'; ...........
Deletions
A very important step here is to "decorate" all data in the result table with the current user's user-ID. This is done so multiple users can do searching simultaneously without seeing each others results.
function Admin_Messages_searchapi_search($args)
. '\ . DataUtil::formatForStore($item['text∞']) . '\', '
. '\ . DataUtil::formatForStore($item['id∞']) . '\', '
. '\ . DataUtil::formatForStore($item['date∞']) . '\', '
. '\ . 'FAQ' . '\', '
. '\ . DataUtil::formatForStore($sessionId∞) . '\')'; ...........
Deletions
1. title - the name of the module (must match exactly since it is used to locate the module later on).
You need to implement the following function:
Make sure translation of "_ADMINMESSAGES" is available
pnModLangLoad('Admin_Messages', 'admin');
pnModLangLoad('Admin_Messages', 'admin');
'functions' => array(_ADMINMESSAGES => 'search'));
A very important step here is to "decorate" all data in the result table with the current user's user-ID. This is done so multiple users can do searching simultaneously without seeing each others results.
3. module - exact name of the module that owns the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
Here is how it is done in the Admin_Messages API:5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
function Admin_Messages_searchapi_search($args)
Security check
if (SecurityUtil::checkPermission('Admin_Messages::', '::', ACCESS_READ)) {
get the db and table info
$messagestable = $pntable['message'];
$messagescolumn = $pntable['message_column'];
$searchTable = &$pntable['search_result'];
$searchColumn = &$pntable['search_result_column'];
form the where clause
$where = ;
if (!pnModGetVar('Admin_Messages', 'allowsearchinactive')
_EDITED
2007-05-16 23:20:51
by
[ ]
Additions
Please refer to the code in your working copy of Zikula - the above code might easily be deprecated when you read this.
_EDITED
2007-05-16 23:16:08
by
[ ]
Additions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "Admin_Messages_searchapi_search".
Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.
Deletions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" functions, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - for instance "Admin_Messages_searchapi_search".
_EDITED
2007-05-16 23:11:25
by
[ ]
Additions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" functions, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - for instance "Admin_Messages_searchapi_search".
A typical search function performs these steps:
We need to insert the following values in the result table:
function Admin_Messages_searchapi_search($args)
if (SecurityUtil::checkPermission('Admin_Messages::', '::', ACCESS_READ)) {
return true;
$messagestable = $pntable['message'];
$messagescolumn = $pntable['message_column'];
$searchTable = &$pntable['search_result'];
$searchColumn = &$pntable['search_result_column'];
form the where clause
$where = ;
if (!pnModGetVar('Admin_Messages', 'allowsearchinactive')
| (isset($args['activeonly']) && (bool)$args['activeonly'])){
$where .= " $messagescolumn[active] = 1 AND ";
$where .= search_construct_where($args, array($messagescolumn['title'], $messagescolumn['content']), $messagescolumn['language']); $userId = (int)pnUserGetVar('uid');
pn_title as title,
FROM $messagestablepn_content as text, pn_date as date, pn_date as date
$searchColumn[updated], $searchColumn[uid])
$message = $result->GetRowAssoc?(2); if (SecurityUtil::checkPermission('Admin_Messages∞::', "$message[title]::$message[mid]", ACCESS_READ)) {
. '\ . DataUtil::formatForStore($message['title∞']) . '\', ' . '\ . DataUtil::formatForStore($message['text∞']) . '\', ' . '\ . 'Admin_Messages' . '\', ' . '\ . DataUtil::formatForStore($message['date∞']) . '\', ' . '\ . DataUtil::formatForStore($message['date∞']) . '\', ' . $userId . ')'; ........... |
Additions
Please refer to the code in your working copy of Zikula - the above code might easily be deprecated when you read this.
Additions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" function, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - corresponding to (for instance) "Admin_Messages_searchapi_search".
1. Access check - does the current user have access to searching through this kind of documents?
5. Check each found item for item based access. If the user has access to it then it is inserted in the Search module's result table.
A very important step here is to "decorate" all data in the result table with the current user's user-ID. This is done so multiple users can do searching simultaneously without seeing each others results.5. Check each found item for item based access. If the user has access to it then it is inserted in the Search module's result table.
1. title - the title of the found item.
2. text - any relevant text representing the item.
3. module - exact name of the module that owns the item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
If it is possible to do searching without access control, or with an access control that can be expressed in SQL, then we can short-circuit the "select-from-database-into-PHP-and-insert-into-database-again" step.2. text - any relevant text representing the item.
3. module - exact name of the module that owns the item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
Process the result set and insert into search result table
Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.
Deletions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" functions, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - for instance "Admin_Messages_searchapi_search".
1. An access check - does the current user have access to searching through this kind of documents?
5. Each found item is checked for item based access. If the user has access to it then it is inserted in the Search module's result table.
A very important step here is to "decorate" all data in the result table with the current user's user-ID. This is done so multiple users can do searching simultaneously without seeing each others results.5. Each found item is checked for item based access. If the user has access to it then it is inserted in the Search module's result table.
1. title - the title of the found item.
2. text - any relevant text representing the found item.
3. module - exact name of the module that owns the found item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
If it is possible to do searching without access control, or with an access control that can be expressed in SQL, then we can short-circuit the "select-from-database-into-PHP-and-insert-into-database-again" step. Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.
2. text - any relevant text representing the found item.
3. module - exact name of the module that owns the found item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
Process the result set into an array of records
Additions
Now, when the user subsmits the search query, the Search module starts scanning for search plugins. For each found plugin it locates the "info" functions, fetches the "functions" list, and iterates through each document type's search function. Typically there will only be one type with a search function named "search" - for instance "Admin_Messages_searchapi_search".
A typical search function performs these steps:
1. An access check - does the current user have access to searching through this kind of documents?
2. Loading database information.
3. Create an SQL "select" statement based on the search query.
4. Execute the "select" statement and iterate through the found items.
5. Each found item is checked for item based access. If the user has access to it then it is inserted in the Search module's result table.
A very important step here is to "decorate" all data in the result table with the current user's user-ID. This is done so multiple users can do searching simultaneously without seeing each others results.2. Loading database information.
3. Create an SQL "select" statement based on the search query.
4. Execute the "select" statement and iterate through the found items.
5. Each found item is checked for item based access. If the user has access to it then it is inserted in the Search module's result table.
We need to insert the following values in the result table:
1. title - the title of the found item.
2. text - any relevant text representing the found item.
3. module - exact name of the module that owns the found item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
Here is how it is done in the Admin_Messages API:2. text - any relevant text representing the found item.
3. module - exact name of the module that owns the found item.
4. created - date of creation of the item.
5. updated - date of last update made to the item (often just the created date).
6. uid - the user-ID of the current user.
function Admin_Messages_searchapi_search($args)
Security check
if (SecurityUtil::checkPermission('Admin_Messages::', '::', ACCESS_READ)) {
get the db and table info
pnModDBInfoLoad('Search');
$pntable = pnDBGetTables();
$messagestable = $pntable['message'];
$messagescolumn = $pntable['message_column'];
$searchTable = &$pntable['search_result'];
$searchColumn = &$pntable['search_result_column'];
form the where clause
$where = ;
if (!pnModGetVar('Admin_Messages', 'allowsearchinactive')
Deletions
... more to come ...
_EDITED
2007-05-16 22:57:09
by
[ ]
Additions
Your pnsearchapi.php file must include a "info" function that passes various required information about the module back to the Search module.
Deletions
Your pnsearchapi.php file must include a "info" function that passed various required information about the module back to the Search module.
Now we have all variables of one module in a html form array named like the module:
This Example is taken from the admin messages module. It's important that the text in brackets (here: Admin_Messages) is exactly the module's name (case sensitive) and that it's equal to the title field from above.
_EDITED
2007-05-16 22:53:06
by
[ cleaning up ]
Additions
Deletions
Interacting with the search module
_EDITED
2007-05-16 22:49:27
by
[ ]
Additions
Interacting with the search module
Creating the search form
You need to implement the following function:
if (SecurityUtil::checkPermission('Admin_Messages::', '::', ACCESS_READ)) {
return true;
pnModDBInfoLoad('Search');
$pntable = pnDBGetTables();
$messagestable = $pntable['message'];
$messagescolumn = $pntable['message_column'];
$searchTable = &$pntable['search_result'];
$searchColumn = &$pntable['search_result_column'];
form the where clause
$where = ;
if (!pnModGetVar('Admin_Messages', 'allowsearchinactive')
| (isset($args['activeonly']) && (bool)$args['activeonly'])){
$where .= " $messagescolumn[active] = 1 AND ";
$where .= search_construct_where($args, array($messagescolumn['title'], $messagescolumn['content']), $messagescolumn['language']); $userId = (int)pnUserGetVar('uid'); $sql = " SELECT
pn_title as title,
pn_content as text, pn_date as date, pn_date as date WHERE $where";
($searchColumn[title],
VALUES ";
$searchColumn[text],
$searchColumn[module], $searchColumn[created], $searchColumn[updated], $searchColumn[uid])
Process the result set into an array of records
for (; !$result->EOF; $result->MoveNext?()) {
$message = $result->GetRowAssoc?(2);
return true;if (SecurityUtil::checkPermission('Admin_Messages∞::', "$message[title]::$message[mid]", ACCESS_READ)) {
$sql = $insertSql . '('
}
. '\ . DataUtil::formatForStore($message['title∞']) . '\', '
. '\ . DataUtil::formatForStore($message['text∞']) . '\', ' . '\ . 'Admin_Messages' . '\', ' . '\ . DataUtil::formatForStore($message['date∞']) . '\', ' . '\ . DataUtil::formatForStore($message['date∞']) . '\', ' . $userId . ')'; Speeding up searchingIf it is possible to do searching without access control, or with an access control that can be expressed in SQL, then we can short-circuit the "select-from-database-into-PHP-and-insert-into-database-again" step. Instead of going through PHP we just do a "INSERT INTO result-table SELECT ..." where the select statement is more or less the same as the normal search statement.. |
Deletions
... more to come ...
Additions
Your pnsearchapi.php file must include a "info" function that passes various required information about the module back to the Search module.
1. title - the name of the module (must match exactly since it is used to locate the module later on).
2. functions - an array of document types and their search function. The Search module will iterate over each document type in the array and call the corresponding search functions when doing the search.
The corresponding pnRender template is:
2. functions - an array of document types and their search function. The Search module will iterate over each document type in the array and call the corresponding search functions when doing the search.
Create output render object
Assign various module variables for the template
Assign various module variables for the template
Deletions
Your pnsearchapi.php file must include a "info" function that passed various required information about the module back to the Search module.
1. title - the name of the module (must match exactly it is used to locate the module later on).
2. functions - an array of document types and their search function. The Search module will iterate over each element in the array and call the corresponding search functions when doing the search.
The searchform has changed from .7x to .8.2. functions - an array of document types and their search function. The Search module will iterate over each element in the array and call the corresponding search functions when doing the search.
Create and setup output render object
Now we have all variables of one module in a html form array named like the module:
This Example is taken from the admin messages module. It's important that the text in brackets (here: Admin_Messages) is exactly the module's name (case sensitive) and that it's equal to the title field from above.
Additions
1. The user enters a search query - some keywords like "Zikula administration" - and fills out other search elements.
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastical change from the Zikula .76 API, where the plugins had to create the output HTML by themselves, and it is done for the following reasons:Interacting with the search module
Deletions
1. The user enters a search query - some keywords like "Zikula administration" - fills out other search elements.
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items, based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastical change from the Zikula .76 API, where the plugins had to create the output HTML by them self, and it is done for the following reasons: Interacting with the search module
Additions
Module Programming Part 4 - Searching
But let's first take a look at how searching actually work. Here is what happens when a search form is created:
1. The Search module scans all modules for an implementation of the Search interface.
2. Each found module's search "plugin" is then asked to generate the HTML needed for any special search settings (like selecting a subset of the available topics or restricting search to a certain forum).
3. All the search HTML is concatenated and presented to the user a the complete search form.
Now the actual searching starts:2. Each found module's search "plugin" is then asked to generate the HTML needed for any special search settings (like selecting a subset of the available topics or restricting search to a certain forum).
3. All the search HTML is concatenated and presented to the user a the complete search form.
1. The user enters a search query - some keywords like "Zikula administration" - fills out other search elements.
3. Each search plugin is passed the search query and other data from the search form and is asked to make a search of it in all the module's items.
So the most important thing for your search plugin to do is 1) To create a search form, 2) to find items, based on the search query, and 3) insert information about the found items in the Search module's result table. This last step is a rather drastical change from the Zikula .76 API, where the plugins had to create the output HTML by them self, and it is done for the following reasons:3. Each search plugin is passed the search query and other data from the search form and is asked to make a search of it in all the module's items.
Interacting with the search module
Your pnsearchapi.php file must include a "info" function that passed various required information about the module back to the Search module.
The returned info data is an array with the following keys:
1. title - the name of the module (must match exactly it is used to locate the module later on).
2. functions - an array of document types and their search function. The Search module will iterate over each element in the array and call the corresponding search functions when doing the search.
The example here is from the Admin_Messages module:
function Admin_Messages_searchapi_info()
Make sure translation of "_ADMINMESSAGES" is available
pnModLangLoad('Admin_Messages', 'admin');
return array('title' =>'Admin_Messages',
'functions' => array(_ADMINMESSAGES => 'search'));
Creating the search form The returned info data is an array with the following keys:
1. title - the name of the module (must match exactly it is used to locate the module later on).
2. functions - an array of document types and their search function. The Search module will iterate over each element in the array and call the corresponding search functions when doing the search.
The example here is from the Admin_Messages module:2. functions - an array of document types and their search function. The Search module will iterate over each element in the array and call the corresponding search functions when doing the search.
function Admin_Messages_searchapi_info()
Make sure translation of "_ADMINMESSAGES" is available
pnModLangLoad('Admin_Messages', 'admin');
return array('title' =>'Admin_Messages',
pnModLangLoad('Admin_Messages', 'admin');
return array('title' =>'Admin_Messages',
'functions' => array(_ADMINMESSAGES => 'search'));
You need to implement the following function:
function Admin_Messages_searchapi_options($args)
if (SecurityUtil::checkPermission('Admin_Messages:search∞:', '::', ACCESS_READ))
{
pnModLangLoad('Admin_Messages', 'admin');
Create and setup output render object
$pnRender = new pnRender('Admin_Messages');
$pnRender->assign(pnModGetVar('Admin_Messages'));
$pnRender->assign('active', (isset($args['active']) && isset($args['active']['Admin_Messages']))
(!isset($args['active'])));
$pnRender->assign('activeonly', (isset($args['modvar']) && isset($args['modvar']['Admin_Messages']) && isset($args['modvar']['Admin_Messages']['activeonly'])) !isset($args['modvar']));
return $pnRender->fetch('admin_messages_search_options.htm');
else return ;
The searchform has changed from .7x to .8.
This Example is taken from the admin messages module. It's important that the text in brackets (here: Admin_Messages) is exactly the module's name (case sensitive) and that it's equal to the title field from above.
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" <!--[if $active]-->checked="checked"<!--[/if]--> />
<label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGES_SEARCH]--></label>
<!--[if $allowsearchinactive]-->
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" <!--[if $activeonly]-->checked="checked"<!--[/if]--> />
<label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGES_ACTIVEONLY]--></label>
<!--[/if]-->
</div>%%
Performing the search
... more to come ...
Deletions
But let's first take a look at how searching actually work. Here is what happens:
1. The user enters a search query - some keywords like "Zikula administration".
3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
So the most important thing for your search plugin to do, is to find items, based on the search query and insert information about the found items in the Search module's result table. This is a rather drastical change from the Zikula .76 API and is done for the following reasons:
You need to implement the following functions:
function helloworld_searchapi_info()
$search_module = array('title' =>'helloworld', 'type' => 'API');
return $search_module;
function helloworld_searchapi_options()
if (!pnModAvailable('helloworld')
!pnSecAuthAction(0, 'helloworld::', '::', ACCESS_READ)) {
return;
pnModLangLoad('helloworld', 'user');
$pnRender = &new pnRender('helloworld');
return $pnRender->fetch('helloworld_search_form.htm');
The searchform has changed from .7x to .8
This Example is taken from the admin messages module. It's important that the test in brackets (here: Admin_Messages) is exactly the modulename (case sensitive) and that it's equal to the title field from above.
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" checked="checked" />
<label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGESSEARCH]--></label>
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" checked="checked" />
<label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGESACTIVEONLY]--></label>
</div>
function helloworld_searchapi_search($args)
....
%%
_EDITED
2007-05-16 22:29:29
by
[ backup ]
Additions
To be able to find your items via the normal search function provided by Zikula .8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
But let's first take a look at how searching actually work. Here is what happens:
1. The user enters a search query - some keywords like "Zikula administration".
2. The Search module scans all modules for an implementation of the Search interface.
3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
4. All items found by the plugin must be inserted in the Search module's result database table.
5. When all modules are finished searching then the search module presents all the found items from it's result table and lets the user browse through them.
So the most important thing for your search plugin to do, is to find items, based on the search query and insert information about the found items in the Search module's result table. This is a rather drastical change from the Zikula .76 API and is done for the following reasons:
1. All search results are presented in the same way independently of the module they originate from.
2. Paging, browsing, and sorting can all be done through SQL. This performs a lot better than doing so in PHP (for "large" result sets - where ever that treshold is).
.
Deletions
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
Oldest known version of this page was edited on 2007-05-16 22:17:19
by
[ Temporary submit - must move to Firefox ]
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
You need to implement the following functions:
/**
This function returns an array with the title, which needs to be exactly the module name
*/
function helloworld_searchapi_info()
{
$search_module = array('title' =>'helloworld', 'type' => 'API');
return $search_module;
}
/**
You also need to present search options to the user, at least an option to disable the search
*/
function helloworld_searchapi_options()
{
if (!pnModAvailable('helloworld') || !pnSecAuthAction(0, 'helloworld::', '::', ACCESS_READ)) {
return;
}
pnModLangLoad('helloworld', 'user');
$pnRender = &new pnRender('helloworld');
return $pnRender->fetch('helloworld_search_form.htm');
}
The searchform has changed from .7x to .8
Now we have all variables of one module in a html form array named like the module:
This Example is taken from the admin messages module. It's important that the test in brackets (here: Admin_Messages) is exactly the modulename (case sensitive) and that it's equal to the title field from above.
<div>
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" checked="checked" />
<label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGESSEARCH]--></label>
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" checked="checked" />
<label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGESACTIVEONLY]--></label>
</div>
/**
This function returns the search result prepared as html source and the number of search results in an array with two fields ('html' and 'resultcount')
$args contains several variables:
The searchphrase:
$args['q']
The boolean operation AND or OR, which tells you how to treat the space separated words:
$args['bool']
For paging:
$args['numlimit'];
$args['startnum']:
$args['total'] (I have no idea why this is there)
*/
function helloworld_searchapi_search($args)
{
....
}
if (SecurityUtil::checkPermission('Admin_Messages:search∞:', '::', ACCESS_READ))
{
{
pnModLangLoad('Admin_Messages', 'admin');
Create and setup output render object
$pnRender = new pnRender('Admin_Messages');
$pnRender->assign(pnModGetVar('Admin_Messages'));
$pnRender->assign('active', (isset($args['active']) && isset($args['active']['Admin_Messages']))
Deletions
But let's first take a look at how searching actually work. Here is what happens:
You need to implement the following functions:
function helloworld_searchapi_info()
function helloworld_searchapi_options()
Create and setup output render object
$pnRender = new pnRender('Admin_Messages');
$pnRender->assign(pnModGetVar('Admin_Messages'));
$pnRender->assign('active', (isset($args['active']) && isset($args['active']['Admin_Messages']))
| (!isset($args['active']))); $pnRender->assign('activeonly', (isset($args['modvar']) && isset($args['modvar']['Admin_Messages']) && isset($args['modvar']['Admin_Messages']['activeonly'])) | !isset($args['modvar'])); return $pnRender->fetch('admin_messages_search_options.htm'); else return ; The searchform has changed from .7x to .8. This Example is taken from the admin messages module. It's important that the text in brackets (here: Admin_Messages) is exactly the module's name (case sensitive) and that it's equal to the title field from above.
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" <!--[if $active]-->checked="checked"<!--[/if]--> />
<!--[if $allowsearchinactive]--><label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGES_SEARCH]--></label>
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" <!--[if $activeonly]-->checked="checked"<!--[/if]--> />
<!--[/if]--><label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGES_ACTIVEONLY]--></label> Performing the search ... more to come ... |
Deletions
But let's first take a look at how searching actually work. Here is what happens:
1. The user enters a search query - some keywords like "Zikula administration".
3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
So the most important thing for your search plugin to do, is to find items, based on the search query and insert information about the found items in the Search module's result table. This is a rather drastical change from the Zikula .76 API and is done for the following reasons:3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
You need to implement the following functions:
function helloworld_searchapi_info()
$search_module = array('title' =>'helloworld', 'type' => 'API');
return $search_module;
return $search_module;
if (!pnModAvailable('helloworld')
_EDITED
2007-05-16 22:29:29
by
[ backup ]
Additions
To be able to find your items via the normal search function provided by Zikula .8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
But let's first take a look at how searching actually work. Here is what happens:
| !pnSecAuthAction(0, 'helloworld::', '::', ACCESS_READ)) {
return;
$pnRender = &new pnRender('helloworld'); return $pnRender->fetch('helloworld_search_form.htm'); The searchform has changed from .7x to .8 This Example is taken from the admin messages module. It's important that the test in brackets (here: Admin_Messages) is exactly the modulename (case sensitive) and that it's equal to the title field from above.
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" checked="checked" />
<label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGESSEARCH]--></label> <input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" checked="checked" /> <label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGESACTIVEONLY]--></label> function helloworld_searchapi_search($args) .... %% |
Additions
To be able to find your items via the normal search function provided by Zikula .8, you need to implement Zikula's Search API interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory and implement a couple of specific functions in it.
But let's first take a look at how searching actually work. Here is what happens:
1. The user enters a search query - some keywords like "Zikula administration".
2. The Search module scans all modules for an implementation of the Search interface.
3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
4. All items found by the plugin must be inserted in the Search module's result database table.
5. When all modules are finished searching then the search module presents all the found items from it's result table and lets the user browse through them.
So the most important thing for your search plugin to do, is to find items, based on the search query and insert information about the found items in the Search module's result table. This is a rather drastical change from the Zikula .76 API and is done for the following reasons:2. The Search module scans all modules for an implementation of the Search interface.
3. Each search "plugin" is passed the query and asked to make a search of it in all the module's items.
4. All items found by the plugin must be inserted in the Search module's result database table.
5. When all modules are finished searching then the search module presents all the found items from it's result table and lets the user browse through them.
1. All search results are presented in the same way independently of the module they originate from.
2. Paging, browsing, and sorting can all be done through SQL. This performs a lot better than doing so in PHP (for "large" result sets - where ever that treshold is). .
Deletions
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
Oldest known version of this page was edited on 2007-05-16 22:17:19
by
[ Temporary submit - must move to Firefox ]
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
You need to implement the following functions:
The searchform has changed from .7x to .8
Now we have all variables of one module in a html form array named like the module:
This Example is taken from the admin messages module. It's important that the test in brackets (here: Admin_Messages) is exactly the modulename (case sensitive) and that it's equal to the title field from above.
2. Paging, browsing, and sorting can all be done through SQL. This performs a lot better than doing so in PHP (for "large" result sets - where ever that treshold is). .
Deletions
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
To be able to find your items via the normal search function that is provided by Zikula you need to
implement Zikula's Search API Interface - that is, you must create an API file named "pnsearchapi.php" in your module's root directory, implement a couple of functions in it, and place it in you module directory.
You need to implement the following functions:
/**
This function returns an array with the title, which needs to be exactly the module name
*/
function helloworld_searchapi_info()
{
$search_module = array('title' =>'helloworld', 'type' => 'API');
return $search_module;
}
This function returns an array with the title, which needs to be exactly the module name
*/
function helloworld_searchapi_info()
{
$search_module = array('title' =>'helloworld', 'type' => 'API');
return $search_module;
}
/**
You also need to present search options to the user, at least an option to disable the search
*/
function helloworld_searchapi_options()
{
if (!pnModAvailable('helloworld') || !pnSecAuthAction(0, 'helloworld::', '::', ACCESS_READ)) {
return;
}
pnModLangLoad('helloworld', 'user');
$pnRender = &new pnRender('helloworld');
return $pnRender->fetch('helloworld_search_form.htm');
}
You also need to present search options to the user, at least an option to disable the search
*/
function helloworld_searchapi_options()
{
if (!pnModAvailable('helloworld') || !pnSecAuthAction(0, 'helloworld::', '::', ACCESS_READ)) {
return;
}
pnModLangLoad('helloworld', 'user');
$pnRender = &new pnRender('helloworld');
return $pnRender->fetch('helloworld_search_form.htm');
}
The searchform has changed from .7x to .8
Now we have all variables of one module in a html form array named like the module:
This Example is taken from the admin messages module. It's important that the test in brackets (here: Admin_Messages) is exactly the modulename (case sensitive) and that it's equal to the title field from above.
<div>
<input type="checkbox" id="active_admin_messages" name="active[Admin_Messages]" value="1" checked="checked" />
<label for="active_admin_messages"><!--[pnml name="_ADMINMESSAGESSEARCH]--></label>
<input type="checkbox" id="admin_messages_activeonly" name="modvar[Admin_Messages][activeonly]" value="1" checked="checked" />
<label for="admin_messages_activeonly"><!--[pnml name="_ADMINMESSAGESACTIVEONLY]--></label>
</div>
/**
This function returns the search result prepared as html source and the number of search results in an array with two fields ('html' and 'resultcount')
$args contains several variables:
The searchphrase:
$args['q']
The boolean operation AND or OR, which tells you how to treat the space separated words:
$args['bool']
For paging:
$args['numlimit'];
$args['startnum']:
$args['total'] (I have no idea why this is there)
*/
function helloworld_searchapi_search($args)
{
....
}
This function returns the search result prepared as html source and the number of search results in an array with two fields ('html' and 'resultcount')
$args contains several variables:
The searchphrase:
$args['q']
The boolean operation AND or OR, which tells you how to treat the space separated words:
$args['bool']
For paging:
$args['numlimit'];
$args['startnum']:
$args['total'] (I have no idea why this is there)
*/
function helloworld_searchapi_search($args)
{
....
}
