You can view a working example of a Control Panel page with a custom list here: Example: creating a custom list of elements.
Generally, a Control Panel page displaying a list of elements requires the implementation of the following functions:
The Control Panel page creation API allows to perform these functions independently. For example, a list can be built in such a way that it can be updated and navigated using AJAX without having to update the whole page.
Let us see how a Control Panel page with a list of elements can be created. Use the Subscription/Newsletter module page as example.
Before we start the page output, we have to perform some preliminary steps. Create a file /bitrix/modules/subscribe/rubric_admin.php and add the following code to it:
<? // include all necessary files: require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php"); // the first common prologue // initialise the module require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/include.php"); // a module proloque require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/prolog.php"); // include a language file IncludeModuleLangFile(__FILE__); // obtain the current user module access level to the $POST_RIGHT = $APPLICATION->GetGroupRight("subscribe"); // if access is denied, direct the visitor to the authorization form if ($POST_RIGHT == "D") $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); ?> <? // prepare all the data here ?> <? // the second common prologue require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); ?> <? // display the page here ?> <?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php");?>
Now we have the page body indicated on the figure above.
Now create a language file, for example:
/bitrix/modules/subscribe/lang/ru/rubric_admin.php for French. In this
file, create all language messages as the array
elements: $MESS['message_identifier'] = "message_text";
.
Since the /bitrix/modules/ catalog is not accessible via HTTP as has been set by the BSM installation, create a file /bitrix/admin/rubric_admin.php:
<? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/subscribe/admin/rubric_admin.php"); ?>
Now this file is available at: http://mysite.ru/bitrix/admin/rubric_admin.php.
As shown on the figure above, all page functions can be conditionally divided into several components.
For this, we need instances of the following classes.
Class | Description |
---|---|
CAdminList | The main class used with the Control Panel element lists. |
CAdminResult | The CDBResult class extension used with element lists in the Control Panel scripts. |
CAdminSorting | Used for list sorting. |
CAdminFilter | Used for list filtering. |
First, create instances of the CAdminList and CAdminSorting classes:
$sTableID = "tbl_rubric"; // table ID $oSort = new CAdminSorting($sTableID, "ID", "desc"); // object to sort $lAdmin = new CAdminList($sTableID, $oSort); // main object of the list
In the example below, the result filter includes of the following parameters:
The preparatory actions can be as follows:
// move filter validation to a separate function function CheckFilter() { global $FilterArr, $lAdmin; foreach ($FilterArr as $f) global $$f; /* check values of $find_name variables and if an error occurs, call $lAdmin->AddFilterError("error_text"). */ // return false on error return count($lAdmin->arFilterErrors) == 0; } // describe filter elements $FilterArr = Array( "find_id", "find_lid", "find_active", "find_visible", "find_auto", ); // initialise the filter $lAdmin->InitFilter($FilterArr); // if all filter values are correct, process the filter if (CheckFilter()) { // create a filter array for CRubric::GetList() // using the filter values $arFilter = Array( "ID" => $find_id, "LID" => $find_lid, "ACTIVE" => $find_active, "VISIBLE" => $find_visible, "AUTO" => $find_auto, ); }
The following actions are possible with elements:
To verify that an action was performed on a list element, you can call CAdminList::EditAction or CAdminList::GroupAction. Don't forget to check permissions in both cases (here, check the write access permission for the Subscription module - $POST_RIGHT=="W").
Example:
// save modified elements if($lAdmin->EditAction() && $POST_RIGHT=="W") { // check the list of passed elements foreach($FIELDS as $ID=>$arFields) { if(!$lAdmin->IsUpdated($ID)) continue; // save changes for each element $DB->StartTransaction(); $ID = IntVal($ID); $cData = new CRubric; if(($rsData = $cData->GetByID($ID)) && ($arData = $rsData->Fetch())) { foreach($arFields as $key=>$value) $arData[$key]=$value; if(!$cData->Update($ID, $arData)) { $lAdmin->AddGroupError(GetMessage("rub_save_error")." ".$cData->LAST_ERROR, $ID); $DB->Rollback(); } } else { $lAdmin->AddGroupError(GetMessage("rub_save_error")." ".GetMessage("rub_no_rubric"), $ID); $DB->Rollback(); } $DB->Commit(); } } // process single and group actions if(($arID = $lAdmin->GroupAction()) && $POST_RIGHT=="W") { // if "For all elements" is selected if($_REQUEST['action_target']=='selected') { $cData = new CRubric; $rsData = $cData->GetList(array($by=>$order), $arFilter); while($arRes = $rsData->Fetch()) $arID[] = $arRes['ID']; } // walk the list of elements foreach($arID as $ID) { if(strlen($ID)<=0) continue; $ID = IntVal($ID); // perform the required action for each element switch($_REQUEST['action']) { // delete case "delete": @set_time_limit(0); $DB->StartTransaction(); if(!CRubric::Delete($ID)) { $DB->Rollback(); $lAdmin->AddGroupError(GetMessage("rub_del_err"), $ID); } $DB->Commit(); break; // activate or deactivate case "activate": case "deactivate": $cData = new CRubric; if(($rsData = $cData->GetByID($ID)) && ($arFields = $rsData->Fetch())) { $arFields["ACTIVE"]=($_REQUEST['action']=="activate"?"Y":"N"); if(!$cData->Update($ID, $arFields)) $lAdmin->AddGroupError(GetMessage("rub_save_error").$cData->LAST_ERROR, $ID); } else $lAdmin->AddGroupError(GetMessage("rub_save_error")." ".GetMessage("rub_no_rubric"), $ID); break; } } }
The process of selection of elements is similar to that in a component or page except that an instance of the CAdminResult class needs to be created from the selection.
// select the list of mail lists $cData = new CRubric; $rsData = $cData->GetList(array($by=>$order), $arFilter); // transform the list into an instance of the CAdminResult class $rsData = new CAdminResult($rsData, $sTableID); // initialise pagewise navigation similar to CDBResult. $rsData->NavStart(); // emit the navigation code to $lAdmin $lAdmin->NavText($rsData->GetNavPrint(GetMessage("rub_nav")));
In order to build a table of elements, we have to create an array of table
headers; and then send the list of elements to $lAdmin.
The
first action is performed by calling CAdminList::AddHeaders passing an array of
table columns to it. Each column is described by an array, containing the
following keys:
Key | Description |
---|---|
id | The column identifier. |
content | The column header. |
sort | The value of the GET request parameter for sorting. |
default | Specifies if a column is displayed in the list by default
(true|false ). |
Example:
$lAdmin->AddHeaders(array( array( "id" =>"ID", "content" =>"ID", "sort" =>"id", "default" =>true, ), array( "id" =>"NAME", "content" =>GetMessage("rub_name"), "sort" =>"name", "default" =>true, ), array( "id" =>"LID", "content" =>GetMessage("rub_site"), "sort" =>"lid", "default" =>true, ), array( "id" =>"SORT", "content" =>GetMessage("rub_sort"), "sort" =>"sort", "align" =>"right", "default" =>true, ), array( "id" =>"ACTIVE", "content" =>GetMessage("rub_act"), "sort" =>"act", "default" =>true, ), array( "id" =>"VISIBLE", "content" =>GetMessage("rub_visible"), "sort" =>"visible", "default" =>true, ), array( "id" =>"AUTO", "content" =>GetMessage("rub_auto"), "sort" =>"auto", "default" =>true, ), array( "id" =>"LAST_EXECUTED", "content" =>GetMessage("rub_last_exec"), "sort" =>"last_executed", "default" =>true, ), ));
The list of elements is passed to the main object in the following way:
You can combine different methods when creating a row field.
The element context menu is specified as an array whose elements are associated arrays with the following keys:
Key | Description |
---|---|
ICON | The CSS class name with an action button. |
DISABLED | Specifies whether the menu item is disabled or not
(true|false ). |
DEFAULT | Specifies whether the menu item is a default action
(true|false ). Double clicking the row activates the default
action. |
TEXT | The menu item title. |
TITLE | The menu item tooltip. |
ACTION | The action to be performed performed when the menu item is activated (Javascript). |
SEPARATOR | Inserts a separator {true|false }.
If true, all other keys will be
ignored. |
Example:
while($arRes = $rsData->NavNext(true, "f_")): // create a row. the result is a CAdminListRow class instance $row =& $lAdmin->AddRow($f_ID, $arRes); // now configure the value display format // for viewing and editing // the NAME parameter will be edited as a text and displayed as a link $row->AddInputField("NAME", array("size"=>20)); $row->AddViewField("NAME", '<a href="rubric_edit.php?id='.$f_id.'&lang='.lang.'">'.$f_name.'</a>'); // the LID parameter will be edited as a drop down list of languages $row->AddEditField("LID", CLang::SelectBox("LID", $f_LID)); // the SORT parameter will be edited as a text $row->AddInputField("SORT", array("size"=>20)); // the ACTIVE and VISIBLE flags will be edited as checkboxes $row->AddCheckField("ACTIVE"); $row->AddCheckField("VISIBLE"); // the AUTO parameter will be displayed as "Yes" or "No" in bold when edited $row->AddViewField("AUTO", $f_AUTO=="Y"?GetMessage("POST_U_YES"):GetMessage("POST_U_NO")); $row->AddEditField("AUTO", "<b>".($f_AUTO=="Y"?GetMessage("POST_U_YES"):GetMessage("POST_U_NO"))."</b>"); // create the context menu $arActions = Array(); // element editing $arActions[] = array( "ICON"=>"edit", "DEFAULT"=>true, "TEXT"=>GetMessage("rub_edit"), "ACTION"=>$lAdmin->ActionRedirect("rubric_edit.php?ID=".$f_ID) ); // element deletion if ($POST_RIGHT>="W") $arActions[] = array( "ICON"=>"delete", "TEXT"=>GetMessage("rub_del"), "ACTION"=>"if(confirm('".GetMessage('rub_del_conf')."')) ".$lAdmin->ActionDoGroup($f_ID, "delete") ); // insert a separator $arActions[] = array("SEPARATOR"=>true); // check the automated mail list template if (strlen($f_TEMPLATE)>0 && $f_AUTO=="Y") $arActions[] = array( "ICON"=>"", "TEXT"=>GetMessage("rub_check"), "ACTION"=>$lAdmin->ActionRedirect("template_test.php?ID=".$f_ID) ); // if the last item is separator, remove it. if(is_set($arActions[count($arActions)-1], "SEPARATOR")) unset($arActions[count($arActions)-1]); // apply the context menu to the row $row->AddActions($arActions); endwhile;
Now we have to add a table footer and assign group actions to elements to complete the table preparation.
The table resume is formed as an array whose elements are associated arrays with the following keys:
"title"
- parameter name;"value"
- parameter value.
Additionally, the associated array may contain an
entry "counter"
set to true
, which makes the
element a table row selection counter. The value of
"counter"
will change dynamically whenever a user selects or
deselects table rows.
A footer can be attached by calling CAdminList::AddFooter.
A list of possible group actions is specified as an array of elements in the format:
"action_identifier" => "action_name"
It can be attached to the table by calling CAdminList::AddGroupActionTable. Processing group actions is discussed above.
Example:
// table footer $lAdmin->AddFooter( array( // element count array("title"=>GetMessage("MAIN_ADMIN_LIST_SELECTED"), "value"=>$rsData->SelectedRowsCount()), // selection counter array("counter"=>true, "title"=>GetMessage("MAIN_ADMIN_LIST_CHECKED"), "value"=>"0"), ) ); // group actions $lAdmin->AddGroupActionTable(Array( // delete selected elements "delete"=>GetMessage("MAIN_ADMIN_LIST_DELETE"), // activate selected elements "activate"=>GetMessage("MAIN_ADMIN_LIST_ACTIVATE"), // deactivate selected elements "deactivate"=>GetMessage("MAIN_ADMIN_LIST_DEACTIVATE"), ));
If required, you can assign the Control Panel menu which is displayed above the table (for users having the editing permissions). The menu is created as an array whose elements are associated arrays with the following keys:
Key | Description |
---|---|
TEXT | The menu item text. |
TITLE | The menu item tooltip. |
LINK | The button link. |
LINK_PARAM | Additional link parameters (will be added to the <A>
tag). |
ICON | The button CSS class. |
HTML | Specifies the menu item HTML code. |
SEPARATOR | Specifies that an item is a separator (true|false ). |
NEWBAR | Starts a new block of menu items (true|false ). |
MENU | Creates a drop down menu. The value is specified similarly to the table row context menu. |
The context menu is attached by calling CAdminList::AddAdminContextMenu.
Example:
// build a menu consisting of only one item - "Add newsletter" $aContext = array( array( "TEXT"=>GetMessage("POST_ADD"), "LINK"=>"rubric_edit.php?lang=".LANG, "TITLE"=>GetMessage("POST_ADD_TITLE"), "ICON"=>"btn_new", ), ); // and attach it to the list $lAdmin->AddAdminContextMenu($aContext);
Now the list preparation is completed. Call CAdminList::CheckListMode to enable alternative rendering methods (AJAX, export to Excel):
// alternative display $lAdmin->CheckListMode();
Finally, set the page title immediately before output.
// set the page title $APPLICATION->SetTitle(GetMessage("rub_title"));
As the figure shows, the page preparation and the main output must be separated by including the system file prolog_admin_after.php:
// remember to separate data preparation from presentation require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
As it has been mentioned above, data output can be split into two parts:
To render the filter, we need to create a CAdminFilter class instance, pass the list of fields to it, and then build the filter form.
Example:
// create a filter object $oFilter = new CAdminFilter( $sTableID."_filter", array( "ID", GetMessage("rub_f_site"), GetMessage("rub_f_active"), GetMessage("rub_f_public"), GetMessage("rub_f_auto"), ) ); ?> <form name="find_form" method="get" action="<?echo $APPLICATION->GetCurPage();?>"> <?$oFilter->Begin();?> <tr> <td><?="ID"?>:</td> <td> <input type="text" name="find_id" size="47" value="<?echo htmlspecialchars($find_id)?>"> </td> </tr> <tr> <td><?=GetMessage("rub_f_site").":"?></td> <td><input type="text" name="find_lid" size="47" value="<?echo htmlspecialchars($find_lid)?>"></td> </tr> <tr> <td><?=GetMessage("rub_f_active")?>:</td> <td> <? $arr = array( "reference" => array( GetMessage("POST_YES"), GetMessage("POST_NO"), ), "reference_id" => array( "Y", "N", ) ); echo SelectBoxFromArray("find_active", $arr, $find_active, GetMessage("POST_ALL"), ""); ?> </td> </tr> <tr> <td><?=GetMessage("rub_f_public")?>:</td> <td><?echo SelectBoxFromArray("find_visible", $arr, $find_visible, GetMessage("POST_ALL"), "");?></td> </tr> <tr> <td><?=GetMessage("rub_f_auto")?>:</td> <td><?echo SelectBoxFromArray("find_auto", $arr, $find_auto, GetMessage("POST_ALL"), "");?></td> </tr> <? $oFilter->Buttons(array("table_id"=>$sTableID,"url"=>$APPLICATION->GetCurPage(),"form"=>"find_form")); $oFilter->End(); ?> </form>
Having prepared all the required data, we can now render the report table just with one call:
// output the table of element list $lAdmin->DisplayList();
Here you can find the complete example of an administration page with the list.
© 2001-2008 Bitrix | Bitrix Site Manager |