Part 2 of the component tutorial explaines all files creating backend interface for my sample JPortfSimple component:
- admin.jportfsimple.php
- admin.jportfsimple.html.php
- toolbar.jportfsimple.php
- toolbar.jportfsimple.html.php
- install.jportfsimple.php
- uninstall.jportfsimple.php
- jportfsimple.xml
which are placed in administrator/components/com_jportfsimple folder during installation. Well, .xml file was explained earlier (see p. 4).
7. BackendSimilarly to frontend, one file is responsible for "logic" of the component (it's backend interface) - admin.jportfsimple.php, and second file is displaying the information (admin.jportfsimple.html.php).
admin.jportfsimple.php // no direct access defined('_VALID_MOS') or die('Direct Access to this location is not allowed.'); // ensure user has access to this function if (!($acl->acl_check( 'administration', 'edit', 'users', $my->usertype, 'components', 'all' ) | $acl->acl_check( 'administration', 'edit', 'users', $my->usertype, 'components', 'com_jportfsimple' ))) { mosRedirect( 'index2.php', _NOT_AUTH ); } global $mosConfig_live_site, $mosConfig_absolute_path, $mosConfig_lang, $mosConfig_list_limit; // load .class.php and .html.php files for the component require_once( $mainframe->getPath( 'admin_html' ) ); require_once( $mainframe->getPath( 'class' ) ); // get task and act from request $task = trim( mosGetParam ( $_REQUEST, 'task', '' )); $act = trim( mosGetParam ( $_REQUEST, 'act', '' )); // get selected objects $id = josGetArrayInts( 'cid' ); // load language file if (file_exists( $mosConfig_absolute_path. '/components/com_jportfsimple/lang/'. $mosConfig_lang. '.php')) include_once( $mosConfig_absolute_path.'/components/com_jportfsimple/lang/'.$mosConfig_lang.'.php'); else if (file_exists( $mosConfig_absolute_path. '/components/com_jportfsimple/lang/english.php')) include_once( $mosConfig_absolute_path.'/components/com_jportfsimple/lang/english.php'); // get configuration parameters $database->setQuery('SELECT * FROM #__jportfsimple_conf' ); $conf_rows = $database -> loadObjectList(); if ($database -> getErrorNum()) { echo $database -> stderr(); return false; } if ($conf_rows) { $jpConf = $conf_rows[0]; $base_path = $jpConf->base_path; }
First part of frontend file does the following: lines 12 to 16 - acl check - does logged in user has access to the component ?
19 to 21 - loads the required class and backend html (admin.jportfsimple.html.php) files 23 to 28 - gets variables defining what to do ($act, $task) and with which object ($id)
30 to 35 - loads language file, default is english.php in
com_jportfsimple/lang folder 37 to 47 - reads data from database table containing configuration parameters. They are stored in $jpConf object, and location of images in $base_path
Main backend "logic": admin.jportfsimple.php switch( $act ) { case 'configure': switch($task) { case 'save': Conf_save( $option ); break; default: Conf_list( $option ); break; } break; case 'categories': switch ($task) { case 'save' : Cat_save( $option ); break; case 'cancel' : Cat_cancel( $option, $act); break; case 'edit' : Cat_edit( $option, $id ); break; case 'new' : $id = ''; Cat_edit( $option, $id ); break; case 'delete' : Cat_del( $option, $id ); break; case 'publish' : Cat_publish( $option, '1', $id ); break; case 'unpublish' : Cat_publish( $option, '0', $id ); break; case 'orderup': ordercat ( intval( $id[0] ), -1, $option, $act ); break; case 'orderdown': ordercat ( intval( $id[0] ), 1, $option, $act ); break; default: Cat_list($option); break; } break; case 'projects': switch ( $task ) { case 'save' : Proj_save( $option ); break; case 'cancel' : Proj_cancel( $option, $act); break; case 'edit' : Proj_edit( $option, $id ); break; case 'new' : $id = ''; Proj_edit( $option, $id ); break; case 'delete' : Proj_del( $option, $id ); break; case 'publish' : Proj_publish( $option, '1', $id ); break; case 'unpublish' : Proj_publish( $option, '0', $id ); break; case 'orderup': orderproj ( intval( $id[0] ), -1, $option, $act ); break; case 'orderdown': orderproj ( intval( $id[0] ), 1, $option, $act ); break; default: Proj_list( $option ); break; } break; case 'info': HTML_jportfsimple::Info( $option ); break; default: break; }
Variable $act get it's value from chosen menu. You remember this part of xml file: <menu>jportfsimple</menu> <submenu> <menu act="categories">Categories</menu> <menu act="projects">Projects</menu> <menu act="configure">Configuration</menu> <menu act="info">About</menu> </submenu>
So for example, if Categories was clicked, $act would be 'categories', and then variable $task will be checked (line 64). Initially $task is empty, so the default action is performed: function Cat_list in line 95. Other functions are called when you click toolbar buttons. Configuration saving function:
admin.jportfsimple.php /** * Configuration saving */ function Conf_save( $option ) { global $database, $mosConfig_absolute_path, $jfiles; // no . in path, and must end in slash if (! (strpos($_POST['base_path'], '..')=== FALSE)) { $err2=_COM_JP_ERROR; $_POST['base_path']= 'images/stories/'; } if (substr($_POST['base_path'], -1, 1)!== '/') $_POST['base_path']= $_POST['base_path']. '/'; - $row = new jportfsimpleConf($database);
// bind it to the table if (!$row -> bind($_POST)) { echo "<script> alert('". $row-> getError(). "'); window.history.go(-1); </script>\n"; } // store it in the db if (!$row -> store()) { echo "<script> alert('". $row-> getError(). "'); window.history.go(-1); </script>\n"; } mosRedirect( 'index2.php?option='.$option.'&act=configure', 'Configuration Saved'.$err2 ); }
Function called after editing configuration parameters, when "Save" is clicked. First some specific for this component checks - if base_path variable containes two dots, then it's changed to default one; if it does not end with slash, one is added. Lines 159 to 172 - whichever object in Joomla! is being saved (from those defined in .class file) similar actions are performed:
- new object is created (line 159)
- bind - copies values from $_POST to the above object - if for example you have a field in a form with a name which is not in object's class, then this part will throw an error (line 162)
- storing to database - here also an error may show up, if for example you added field to .class file, but you didn't update database table
- if no errors, then component redirects to the page depending on act variable in mosRedirect function, with nice message "Configuration Saved"
Configuration listing function:
admin.jportfsimple.php /** * Configuration listing */ function Conf_list( $option ) { HTML_jportfsimple::Conf_list( $option ); HTML_jportfsimple::bottom(); }
It just calls display function, since configuration data is already in $jpConf variable (see line 45). Function publishing a category: admin.jportfimple.php /** * Category publishing */ function Cat_publish( $option, $publish=1 ,$cid ) { $action = $publish ? 'publish' : 'unpublish'; echo "<script> alert('Select an item to $action'); window.history.go(-1);</script>\n"; } $database->setQuery( 'UPDATE #__jportfsimple_categories SET published='.$publish.' WHERE id IN ('.$cids.')');
if (!$database->query()) { echo "<script> alert('". $database-> getErrorMsg(). "'); window.history.go(-1); </script>\n"; } mosRedirect( 'index2.php?option='.$option.'&act=categories' ); }
First it checks if at least one category is checked (line 192), if not - it displays popup window with error message (this is one exeption of the rule to not use output commands in this file). Then it runs a query to update 'published' column in jos_jportfsimple_categories table (line 198), and if no errors (line 201) it redirects back to categories page. Category saving function: admin.jportfsimple.php /** * Category saving */ function Cat_save( $option ) { $row = new jportfsimpleCategories($database); // bind it to the table if (!$row -> bind($_POST)) { echo "<script> alert('". $row-> getError(). "'); window.history.go(-1); </script>\n"; } // store it in the db if (!$row -> store()) { echo "<script> alert('". $row-> getError(). "'); window.history.go(-1); </script>\n"; } $row->updateOrder(); mosRedirect( 'index2.php?option='.$option.'&act=categories', 'Saved' ); }
As you see, it's almost the same as configuration saving function earlier, just one additional function updating order of all categories (line 225).
Category deleting function: admin.jportfsimple.php /** * Category deleting */ function Cat_del( $option, $cid ) { echo "<script> alert('Select an item to delete'); window.history.go(-1);</script>\n"; } { $database->setQuery('DELETE FROM #__jportfsimple_categories WHERE id IN ('.$ids.')'); } if (!$database->query()) { echo "<script> alert('". $database-> getErrorMsg(). "'); window.history.go(-1); </script>\n"; } mosRedirect( 'index2.php?option='.$option.'&act=categories' ); }
Similar to category publishing function, just different query is used (line 242).
Category editing function. As you perhaps noticed (line 72 and 76), the same function is used for creating new category and for editing existing one. admin.jportfsimple.php /** * Category editing */ function Cat_edit( $option, $uid ) { // build the html select list for ordering $query = 'SELECT ordering AS value, cat_name AS text FROM #__jportfsimple_categories ORDER BY ordering'; $lists['ordering'] = mosAdminMenus::SpecificOrdering( $row, $uid, $query, 1 ); $row = new jportfsimpleCategories($database); if($uid){ $row -> load($uid[0]); } HTML_jportfsimple::Cat_edit( $option, $row, $lists ); }
Lines 258, 259 are needed only if you want to be able to change order of categories during editing. You would also need 'ordering' field in database table. Actual category editing part is in lines 261 to 266: first new object is needed ($row), then if it is in fact editing of an existing category ($uid is not empty) load function loads it from the database. Finally, edit page is displayed (line 266). Cancellation of editing: admin.jportfsimple.php /** * Category editing cancel */ function Cat_cancel( $option, $act ) { mosRedirect( 'index2.php?option='.$option.'&act='.$act ); }
Just redirecting after pressing "Cancel". Category listing: admin.jportfsimple.php /** * Category listing */ function Cat_list( $option ) { global $database, $mainframe, $mosConfig_absolute_path, $mosConfig_list_limit; $limit = intval( $mainframe-> getUserStateFromRequest( 'viewlistlimit', 'limit', $mosConfig_list_limit ) ); $limitstart = intval( $mainframe-> getUserStateFromRequest( "view{$option}limitstart", 'limitstart', 0 ) ); require_once( $mosConfig_absolute_path . '/administrator/includes/pageNavigation.php' ); $query = 'SELECT COUNT(*) FROM #__jportfsimple_categories'; $database->setQuery( $query ); $total = $database->loadResult(); $pageNav = new mosPageNav( $total, $limitstart, $limit ); $database->setQuery('SELECT * FROM #__jportfsimple_categories ORDER BY ordering LIMIT '.$pageNav->limitstart.', '.$pageNav->limit ); $rows = $database -> loadObjectList(); if ($database -> getErrorNum()) { echo $database -> stderr(); return false; } HTML_jportfsimple::Cat_list( $option, $rows, $pageNav ); HTML_jportfsimple::bottom(); }
Main function listing all categories. Lines 285 to 287 - gets current page and number of categories per page, selected by user, and loads required class 289 to 291 - first query, loading just the total number of existing categories (SELECT COUNT), needed for pagination 293 - creates new $pageNav object 295 to 300 - second query, loading just the categories on current page 302, 303 - displaying functions are called
Project functions next are very similar to the above function dealing with categories. I will list only main differences instead of full rest of the code. In Proj_publish, Proj_save and Proj_del (project publishing, saving and deleting functions) redirecting function in last line goes to projects page: admin.jportfsimple.php mosRedirect( 'index2.php?option='.$option.'&act=projects' );
Project editing function: admin.jportfimple.php /** * Project editing */ function Proj_edit( $option, $uid ) { $proj = new jportfsimpleProjects($database); if($uid) { $proj -> load($uid[0]); } else $proj-> date = date( 'Y-m-d H:i:s' ); // creation date, 2006-09-01 10:00:00 $database->setQuery('SELECT * FROM #__jportfsimple_categories ORDER BY cat_name'); $rows = $database -> loadObjectList(); if ($database -> getErrorNum()) { echo $database -> stderr(); return false; } foreach ($rows as $row) { $urow2[]=$row->id; $urow[]=$row->cat_name; } $i=0; $j=0; //$j for Select category text in case of new item if (!$uid) { $categories[$i] = mosHTML::makeOption( '0', _COM_JP_SEL_ALBUM ); $i++; $j=1; } foreach ($urow as $row) { $categories[$i] = mosHTML::makeOption( $urow2[$i-$j], $urow[$i-$j]); $i++; } $size=1; $javascript = ''; $category = mosHTML::selectList( $categories, 'catid', 'class="inputbox" size="'. $size .'" '. $javascript, 'value', 'text', $proj->catid ); $lists['category'] = $category; // build the html select list for ordering $query = 'SELECT ordering AS value, name AS text ' . ' FROM #__jportfsimple_projects' . ' WHERE catid = '.$proj->catid . ' ORDER BY ordering'; $lists['ordering'] = mosAdminMenus::SpecificOrdering( $proj, $uid, $query, 1 ); foreach ($rows as $c) { $c2[$c->id]=$c; } HTML_jportfsimple::Proj_edit( $option, $proj, $base_path, $c2, $lists); }
Lines 376 to 380 - if editing existing project, load it's data, or set a creation date for new project 382 to 408 - this part is used to create a list of categories in HTML select form, for easier selecting a category the project should belong to, instead of entering a category name manually. The challenge here is to select a name, but return a category id. First it gets list of categories, then it creates a $categories array with HTML code for select function, with category id and a name (lines 389 - 402), finally it finishes HTML preparation. It uses functions from Joomla's mosHTML class. 410 to 415 - builds another HTML select list, this one for ordering of a project 419 - calles display function
Project listing function is also similar to category listing, added is the above code for creating HTML select function for filtering projects by a category. Last two functions: ordercat and orderproj - are used whenever reorder arrow is clicked. admin.jportfsimple.php /** * Category ordering */ function ordercat( $uid, $inc, $option, $act ) { $row = new jportfsimpleCategories( $database ); $row->load( $uid ); $row->updateOrder(); $row->move( $inc, 'published >= 0' ); $row->updateOrder(); mosRedirect( 'index2.php?option='. $option .'&act='. $act); }
This is nothing else like using internal Joomla function (updateOrder in this case) to reorder objects.
Now the display file - admin.jportfsimple.html.php - which displays the information provided by the "logic" file, earlier, or shows forms and input fields to enter new information. All backed functions are members of HTML_jportfsimple class: admin.jportfsimple.html.php // no direct access defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); class HTML_jportfsimple{
Configuration listing function is an example of using tabs, and also editor: admin.jportfsimple.html.php /** * Configuration listing */ function Conf_list( $option ) { ?> <script language="javascript" type="text/javascript"> function submitbutton(pressbutton) { <?php getEditorContents( 'editor', 'description' ); ?> submitform( pressbutton ); } </script> <script language="Javascript" src="js/dhtml.js"></script> <table class="adminheading"> <tr> <th><?php echo _COM_JP_CONFIG_INFO ?></th> </tr> </table> <table cellpadding="4" cellspacing="0" border="0" width="100%"> <tr> <td width="5%" class="tabpadding"> </td> <td id="tab1" class="offtab" onClick="dhtml.cycleTab(this.id)">Settings</td> <td id="tab2" class="offtab" onClick="dhtml.cycleTab(this.id)">CSS</td> <td width="5%" class="tabpadding"> </td> </tr> </table> <form action="index2.php" method="post" name="adminForm"> <div id="page1" class="pagetext"> <table cellpadding="4" cellspacing="0" border="0" width="90%" class="adminlist"> <tr> <th class= "title" width= "10%"><?php echo _COM_JP_CONFIG_PARAMETER ?></th> <th class= "title" width= "20%"><?php echo _COM_JP_CONFIG_VALUE ?></th> <th class= "title"><?php echo _COM_JP_CONFIG_DESCR ?></th> </tr> <tr> <td><?php echo _COM_JP_CONFIG_BASEPATH ?> </td> <td><input size="30" name="base_path" value="<?php echo $jpConf->base_path; ?>"> </td> <td><?php echo _COM_JP_CONFIG_BASEPATH_DESCR ?> </td> </tr> <tr> <td><?php echo _COM_JP_CONFIG_TITLE ?> </td> <td><input size="30" name="title" value="<?php echo $jpConf->title; ?>"> </td> <td><?php echo _COM_JP_CONFIG_TITLE_DESCR ?> </td> </tr> <tr> <td valign= "top" ><?php echo _COM_JP_CONFIG_FRONT_DESCR ?> </td> <td align="center" colspan="2"> <?php editorArea( 'editor', $jpConf->description , 'description', '600', '220', '60', '40' ) ; ?> </td> </tr> </table> </div> <div id="page2" class="pagetext"> <table cellpadding="4" cellspacing="0" border="0" width="90%" class="adminlist"> <tr> <th class= "title" width= "10%"><?php echo _COM_JP_CONFIG_PARAMETER ?></th> <th class= "title" width= "20%"><?php echo _COM_JP_CONFIG_VALUE ?></th> <th class= "title"><?php echo _COM_JP_CONFIG_DESCR ?></th> </tr> <tr> <td valign= "top" ><?php echo _COM_JP_CONFIG_CSS ?> </td> <td><input size="30" name="css_file" value="<?php echo $jpConf->css_file; ?>"> </td> <td valign= "top" ><?php echo _COM_JP_CONFIG_CSS_DESCR ?> </td> </tr> </table> </div> <input type="hidden" name="option" value="<?php echo $option; ?>" /> <input type="hidden" name="task" value="" /> <?php if ($jpConf->id) { ?> <input type= "hidden" name= "id" value= <?php echo $jpConf-> id ?> /> <?php } ?> <input type="hidden" name="act" value="configure" /> </form> <script language="javascript" type="text/javascript">dhtml.cycleTab('tab1');</script> <?php }
Lines 38 to 43 - are required for using WYSIWYG editor in a form (actually to get back the content of an editor). Editor is loaded in line 88. Notice the name of the editor field: 'editor' - if you'd like to use more than one editor, their names should be unique. 45 - this is needed for tabs. Their displayed names are defined in lines 56, 57, first open tab is defined in line 121, and then each tab content is displayed within a div. So here: tab1 - name: Settings, div id=page1 (line 63, 93) tab2 - name: CSS, div id=page2 (line 95, 111) As you see, each input field must have it's name, which must be the same as defined in class file, depending on object which is edited. The "hidden" fields (lines 113 to 118) are used to pass other variables, like $option or $act, so the backend "knows" where to go after you press "Save". Variable $task is empty initially - it's value is assigned when actual button in pressed. Variable $id is needed so the right record is saved. In case of configuration there is always only 1 record. Categories listing function: admin.jportfsimple.html.php /** * Category listing */ function Cat_list( $option, &$rows, &$pageNav ) { ?> <form action="index2.php" method="post" name="adminForm"> <table class="adminheading"> <tr> <th><?php echo _COM_JP_ALBUMS_INFO ?></th> </tr> </table> <table cellpadding="4" cellspacing="0" border="0" width="100%" class="adminlist"> <tr> <th width="20"><input type="checkbox" name="toggle" value="" onclick="checkAll(<?php echo count($rows); ?>);" /></th> <th class= "title" width= "20%"><?php echo _COM_JP_ALBUM_NAME ?></th> <th class= "title"><?php echo _COM_JP_ALBUM_PATH ?></th> <th class= "title"><?php echo _COM_JP_ALBUM_INFO ?></th> <th width= "5%"colspan= "2" align= "center"><?php echo _COM_JP_ORDER; ?></th> <th width="7%"></th> <th width= "7%"><?php echo _COM_JP_CONFIG_PUBLISHED; ?> </th> </tr> <?php if (count($rows)< 1) echo '<tr><td colspan="8" ><center><b>'._COM_JP_NO_CAT. '</b></center></td></tr>'; $k = 0; for ($i= 0, $n= count( $rows ); $i < $n; $i++ ) { $row = &$rows[$i]; ?> <tr class="<?php echo "row$k"; ?>"> <td><input type="checkbox" id="cb<?php echo $i;?>" name="cid[]" value="<?php echo $row->id; ?>" onclick="isChecked(this.checked);" /></td> <td><a href= "#edit" onclick= "hideMainMenu();return listItemTask('cb<?php echo $i;?>','edit')"><?php echo $row-> cat_name; ?></a></td> <td><?php echo $row-> cat_path; ?></td> <td><?php echo substr($row-> cat_info, 0, 30); ?></td> <td> <?php echo $pageNav-> orderUpIcon( $i, 1 ); ?> </td> <td> <?php echo $pageNav-> orderDownIcon( $i, $n, 1 ); ?> </td> <td> </td> <td align="center"> <?php if ($row->published == "1") { echo "<a href=\"javascript: void(0);\" onClick=\"return listItemTask('cb$i','unpublish')\"><img src=\"images/publish_g.png\" border=\"0\" /></a>"; } else { echo "<a href=\"javascript: void(0);\" onClick=\"return listItemTask('cb$i','publish')\"><img src=\"images/publish_x.png\" border=\"0\" /></a>"; } ?> </td> <?php $k = 1 - $k; ?> </tr> <?php } ?> </table> <?php echo $pageNav-> getListFooter(); ?> <input type="hidden" name="option" value="<?php echo $option; ?>" /> <input type="hidden" name="task" value="" /> <input type="hidden" name="boxchecked" value="0" /> <input type="hidden" name="hidemainmenu" value="0" /> <input type="hidden" name="act" value="categories" /> </form> <?php }
Here or in any similar listing function, few blocks are used: lines 141 to 150 - start of table, and column headers 153 - if no category defined yet, display warning 156 - loop through all categories 162 - checkbox for selecting categories 163 - displays category name with Javascript returning 'edit' value for $task variable 167, 170 - displays reordering icons 176 to 180 - displays 'published' or 'unpublished' icon 191 - displays select list - how many categories per page to display
Next function - category editing - is similar to configuration editing. Additionally it has Javascript doing basic field validation. It displays popup warning if category name or folder are not entered.
admin.jportfsimple.html.php <script language="javascript" type="text/javascript"> function submitbutton(pressbutton) { var form = document.adminForm; if (pressbutton == 'cancel') { submitform( pressbutton ); return; } // do fields validation if (form.cat_name.value == ''){ alert( "Category must have a name" ); } else if (form.cat_path.value == ''){ alert( "You must select a category folder" ); } else { <?php getEditorContents( 'editor', 'description' ); ?> submitform( pressbutton ); } } </script>
Project listing and project editing functions are similar to the above ones. Last function is 'Info' which displays information about the component. It shows logo, short description and version as defined in language file constants (_COM_JP_DESC, _COM_JP_VER1) and then it includes HTML file from help folder. admin.jportfsimple.html.php if (file_exists( $mosConfig_absolute_path. '/administrator/components/com_jportfsimple/help/'. $mosConfig_lang. '.html')) include_once( $mosConfig_absolute_path.'/administrator/components/com_jportfsimple/help/'. $mosConfig_lang.'.html'); else if (file_exists( $mosConfig_absolute_path. '/administrator/components/com_jportfsimple/help/english.html')) include_once( $mosConfig_absolute_path.'/administrator/components/com_jportfsimple/help/english.html');
If information in other language is not available, it will show english.html by default. It could be done differently - whole information could be also entered in one constant in language file, but I found it easier to update this way.
8. Backend - toolbarsToolbar is defined with help of two files:
- toolbar.jportfsimple.php
- toolbar.jportfsimple.html.php
toolbar.jportfsimple.php // no direct access defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); require_once( $mainframe->getPath( 'toolbar_html' ) ); $task = mosGetParam( $_REQUEST, 'task', '' ); $act = mosGetParam( $_REQUEST, 'act', '' ); switch ( $task ) { case 'edit': case 'new': menujportfsimple::EDIT_MENU(); break; default: switch($act) { case "configure": case "css": menujportfsimple::CONFIGURE_MENU(); break; case "info": menujportfsimple::INFO_MENU(); break; case "categories": case "projects": menujportfsimple::DEFAULT_MENU(); break; default: break; } break; }
Depending on $act and $task it calls certain menu function from menujportfsimple class, which displays the right toolbar. toolbar.jportfsimple.html.php // no direct access defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); class menujportfsimple{ function DEFAULT_MENU() { mosMenuBar::startTable(); mosMenuBar::publish('publish'); mosMenuBar::unpublish('unpublish'); mosMenuBar::divider(); mosMenuBar::addNew('new'); mosMenuBar::editList('edit', 'Edit'); mosMenuBar::deleteList( ' ', 'delete', 'Remove' ); mosMenuBar::divider(); mosMenuBar::endTable(); } function EDIT_MENU() { mosMenuBar::startTable(); mosMenuBar::cancel(); mosMenuBar::save('save'); mosMenuBar::endTable(); } function CONFIGURE_MENU() { mosMenuBar::startTable(); mosMenuBar::save('save'); mosMenuBar::endTable(); } function INFO_MENU() { mosMenuBar::startTable(); mosMenuBar::endTable(); } }
Each _MENU function uses startTable and endTable from mosMenuBar class at the beginning and at the end of a toolbar. Then it defines actual buttons using functions like: addNew, editList or save.
9. Backend - install, uninstallLast two files contain functions which are run after installing or uninstalling a component.
- install.jportfsimple.php
- uninstall.jportfsimple.php
Both are almost identical, only the function name inside is different, and the constant used to display information.
install.jportfsimple.php // no direct access defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); function com_install() { global $mosConfig_live_site, $mosConfig_absolute_path, $mosConfig_lang; if (file_exists( $mosConfig_absolute_path. "/components/com_jportfsimple/lang/". $mosConfig_lang. ".php")) include_once( $mosConfig_absolute_path."/components/com_jportfsimple/lang/". $mosConfig_lang.".php"); else if (file_exists( $mosConfig_absolute_path. "/components/com_jportfsimple/lang/english.php")) include_once( $mosConfig_absolute_path."/components/com_jportfsimple/lang/english.php"); echo _COM_JP_INFO_BOTTOM; }
10. SummaryIn the above tutorial I tried to explain the structure and functions of sample component written for Joomla! CMS v. 1.0.12.
|