Développement d'un composant MVC - Ajout d'un formulaire de frontend
From Joomla! Documentation
< J3.x:Developing an MVC Component
Les articles de cette série
Ajout d'un type de menu à la partie site
Ajout d'un modèle à la partie site
Ajout d'une requête de variable dans le type de menu
Utilisation de la base de données
Backend de base
Ajout de la gestion des langues
Ajout d'actions en backend
Ajout de décorations pour le backend
Ajout de vérifications
Ajout de catégories
Ajout de configuration
Ajout d'un fichier script installation/désinstallation/mise à jour
Ajout d'un formulaire de frontend
Utilisation du filtre de langues
- Ajouter une fenêtre modale
- Ajout d'associations
- Ajout de Checkout
- Ajout d'un filtre
- Ajout de niveaux
- Ajout de versions
- Ajout de tags
- Ajout d'accès
- Ajout d'un processus de traitement
- Ajout d'un cache
- Ajout d'un fil d'actualité
Ajout d'un serveur de mise à jour
Ceci est une série qui regroupe plusieurs articles pour devenir un didacticiel sur la façon de développer un Composant pour Joomla! suivant le principe Modèle-Vue-Contrôleur.
Commencez avec l'introduction, et naviguez dans les articles de cette série soit à l'aide des boutons de navigation en bas des articles, soit grâce au menu de droite : Les articles de cette série.
- Ce didacticiel fait partie de la série de didacticiels sur le Développement d'un Composant MVC pour Joomla! 3.x. Vous êtes invité à lire les articles précédents de cette série avant de lire celui-ci.
Introduction
Dans cette étape nous ajouterons un formulaire au site (front end) pour permettre aux utilisateurs d'ajouter une nouvel enregistrement "Helloworld". Vous pouvez adapter le code présenté ici pour ajouter un ensemble de fonctionnalités d'entrée de données allant de par exemple,
- un formulaire d'enregistrement pour permettre aux visiteurs du site d'exprimer leur intérêt, jusqu'à
- la possibilité de faire de la maintenance de données dans certaines tables de la base, toutefois sans leur donner accès à l'administration du site.
Il y a deux videos associées à cette étape, couvrant l'approche globale et autres thèmes évoqué ici.
- L'approche globale
- Autres thèmes
Fonctionnalité
Dans cette étape nous allons construire la fonctionnalité suivante:
- Un formulaire coté site pour permettre à quelqu'un d'entrer un nouvel enregistrement "helloworld" avec les traditionnels boutons Enregistrer et Annuler.
- On ajoutera aussi des champs dans la base de donnée pour garder la trace de quel utilisateur à entré un enregistrement et quand.
- On ajoutera un système de validation des données dans les champs, inclant l'élimination de chaines de caractères dangereuse tel que des balises html
- On ajoutera un contrôle d'accès, pour controler qui peut ajouter un nouvel enregistrement
- un courrier électronique à un administrateur, pour indiquer que quelqu'un a entré un nouvel enregistrement (et nous inclurons un champ sur le formulaire où l'utilisateur peut inclure du texte qui va simplement dans le courrier électronique)
- Un captcha (destiné à bloquer les robots) sur le formulaire
- un élément de menu dans la partie site qui pointe vers le formulaire (c.-à-d. comment les utilisateurs ont accès au formulaire)
- Une mise à jour de la partie admin de hellowordl pour afficher l'auteur et la date de création.
Approche
Créer un formulaire dans la partie site est à peu près la même démarche que celle faite dans la partie admin. Une grande partie de ce qui est développé dans cette étape est identique ce qui a été fait à l'étape [10-Ajout des actions au backend], et en particulier le formulaire Modifier pour les messages de helloworld. For this form we'll use (all in the site part)
- the same main helloworld controller (controller.php)
- a new view – which we'll call "form"
- a new layout, associated with the form view, which we'll call "edit" (like the admin layout file)
- a new model – which we'll call "form" also, to align with the view
- an xml file for the form, which we'll put in add-form.xml in the model
In addition we'll need to handle the HTTP POST requests arising from the user pressing the Save and Cancel buttons, and we'll do this in:
- a new helloworld controller in the controllers directory (handling Save and Cancel)
- the same form.php model as above (handling Save)
Upon completion of Save/Cancel we'll redirect back to the same form. As for the admin case, we'll consider our classes extending some of the controller and model classes which are richer in functionality that the simple legacy ones
- the model will extend JModelAdmin (which supports forms, as well as saving records to the database) - even though it's called JModelAdmin it's still available within the site part
- the controller handling the POST will extend JControllerForm (which includes the cancel() and save() methods).
Some of the other aspects in this step will involve using the techniques covered in earlier steps, namely Adding a menu type to the site part, Adding verifications, Adding configuration and Adding ACL.
Mettre à jour la base de données
We need to add the two new fields to our install and update scripts. To record who added the new helloworld greeting we'll store the user's userid, and this will be zero if the user is not logged on.
admin/sql/install.mysql.utf8.sql
DROP TABLE IF EXISTS `#__helloworld`;
CREATE TABLE `#__helloworld` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`asset_id` INT(10) NOT NULL DEFAULT '0',
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`created_by` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`greeting` VARCHAR(25) NOT NULL,
`published` tinyint(4) NOT NULL DEFAULT '1',
`catid` int(11) NOT NULL DEFAULT '0',
`params` VARCHAR(1024) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
)
ENGINE =MyISAM
AUTO_INCREMENT =0
DEFAULT CHARSET =utf8;
INSERT INTO `#__helloworld` (`greeting`) VALUES
('Hello World!'),
('Goodbye World!');
/admin/sql/updates/mysql/0.0.16.sql
ALTER TABLE`#__helloworld` ADD COLUMN `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `asset_id`;
ALTER TABLE`#__helloworld` ADD COLUMN `created_by` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `created`;
To enable a menu item to point to the form, we need to put an xml file into the associated layout directory. Extend your directory structure (remembering to include the index.html file in each new subdirectory which you create) and put the following into
site/views/form/tmpl/edit.xml
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_HELLOWORLD_ADD_VIEW_TITLE">
<message>COM_HELLOWORLD_ADD_VIEW_DESC</message>
</layout>
</metadata>
Once you have the new code installed you'll have to go into the admin back-end and create a menu item to point to the new front-end form.
Displaying the new form view
Create a new forms subdirectory under the site models directory, and add the definition of the form into
site/models/forms/add-form.xml
<?xml version="1.0" encoding="utf-8"?>
<form
addrulepath="/administrator/components/com_helloworld/models/rules"
>
<fieldset
name="details"
label="COM_HELLOWORLD_HELLOWORLD_DETAILS"
>
<field
name="id"
type="hidden"
/>
<field
name="greeting"
type="text"
label="COM_HELLOWORLD_HELLOWORLD_GREETING_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_GREETING_DESC"
size="40"
class="inputbox"
validate="greeting"
required="true"
hint="COM_HELLOWORLD_HELLOWORLD_GREETING_HINT"
default=""
/>
<field
name="catid"
type="category"
extension="com_helloworld"
class="inputbox"
default=""
label="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC"
required="true"
>
<option value="0">JOPTION_SELECT_CATEGORY</option>
</field>
<field
name="message"
type="textarea"
rows="5"
cols="80"
label="COM_HELLOWORLD_HELLOWORLD_MESSAGE_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_MESSAGE_DESC"
hint="COM_HELLOWORLD_HELLOWORLD_MESSAGE_HINT"
required="true"
>
</field>
<field
name="captcha"
type="captcha"
label="COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_DESC"
validate="captcha"
>
</field>
<fields name="params">
<field
name="show_category"
type="list"
label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC"
default=""
useglobal="true"
>
<option value="0">JHIDE</option>
<option value="1">JSHOW</option>
</field>
</fields>
</fieldset>
</form>
The above form includes a captcha. To get this working you need to install a captcha plugin from the selection available for Joomla. You can also use the Captcha - ReCaptcha plugin which comes with Joomla, but before using this you have to get recaptcha keys for your domain (eg localhost) from Google, and then configure the plugin with the keys which Google supplies (ie Extensions / Plugins, and then click on the plugin to edit its options - if you edit the plugin it tells you exactly what you have to do). Once the plugins are live, you can select in the Global Configuration the captcha which you want to be the system default, and also in the Helloworld Configuration select which captcha to use for this helloworld form.
The existing controller (in controller.php) will not need to be changed, but we'll need to define a new view, layout and model for the new form.
site/views/form/view.html.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* HelloWorld View
* This is the site view presenting the user with the ability to add a new Helloworld record
*
*/
class HelloWorldViewForm extends JViewLegacy
{
protected $form = null;
protected $canDo;
/**
* Display the Hello World view
*
* @param string $tpl The name of the layout file to parse.
*
* @return void
*/
public function display($tpl = null)
{
// Get the form to display
$this->form = $this->get('Form');
// Get the javascript script file for client-side validation
$this->script = $this->get('Script');
// Check that the user has permissions to create a new helloworld record
$this->canDo = JHelperContent::getActions('com_helloworld');
if (!($this->canDo->get('core.create')))
{
$app = JFactory::getApplication();
$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
$app->setHeader('status', 403, true);
return;
}
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
// Call the parent display to display the layout file
parent::display($tpl);
// Set properties of the html document
$this->setDocument();
}
/**
* Method to set up the html document properties
*
* @return void
*/
protected function setDocument()
{
$document = JFactory::getDocument();
$document->setTitle(JText::_('COM_HELLOWORLD_HELLOWORLD_CREATING'));
$document->addScript(JURI::root() . $this->script);
$document->addScript(JURI::root() . "/administrator/components/com_helloworld"
. "/views/helloworld/submitbutton.js");
JText::script('COM_HELLOWORLD_HELLOWORLD_ERROR_UNACCEPTABLE');
}
}
And into the layout file:
site/views/form/tmpl/edit.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*
* This layout file is for displaying the front end form for capturing a new helloworld message
*
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
JHtml::_('behavior.formvalidator');
?>
<form action="<?php echo JRoute::_('index.php?option=com_helloworld&view=form&layout=edit'); ?>"
method="post" name="adminForm" id="adminForm" class="form-validate">
<div class="form-horizontal">
<fieldset class="adminform">
<legend><?php echo JText::_('COM_HELLOWORLD_LEGEND_DETAILS') ?></legend>
<div class="row-fluid">
<div class="span6">
<?php echo $this->form->renderFieldset('details'); ?>
</div>
</div>
</fieldset>
</div>
<div class="btn-toolbar">
<div class="btn-group">
<button type="button" class="btn btn-primary" onclick="Joomla.submitbutton('helloworld.save')">
<span class="icon-ok"></span><?php echo JText::_('JSAVE') ?>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn" onclick="Joomla.submitbutton('helloworld.cancel')">
<span class="icon-cancel"></span><?php echo JText::_('JCANCEL') ?>
</button>
</div>
</div>
<input type="hidden" name="task" />
<?php echo JHtml::_('form.token'); ?>
</form>
All the above is similar to the admin functionality, except there are certain fields we don't want to allow the front-end user to see (eg the permissions) and instead of the standard Joomla admin buttons (and toolbar) we use a Save button and a Cancel button styled using the Bootstrap CSS, and which result in the task parameter being set to helloworld.save or helloworld.cancel.
Our new model is almost exactly the same as the admin equivalent; we just have to point to our new add-form instead.
site/models/form.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* HelloWorld Model
*
* @since 0.0.1
*/
class HelloWorldModelForm extends JModelAdmin
{
/**
* Method to get a table object, load it if necessary.
*
* @param string $type The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $config Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 1.6
*/
public function getTable($type = 'HelloWorld', $prefix = 'HelloWorldTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Method to get the record form.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
*
* @return mixed A JForm object on success, false on failure
*
* @since 1.6
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm(
'com_helloworld.form',
'add-form',
array(
'control' => 'jform',
'load_data' => $loadData
)
);
if (empty($form))
{
$errors = $this->getErrors();
throw new Exception(implode("\n", $errors), 500);
}
return $form;
}
/**
* Method to get the data that should be injected in the form.
* As this form is for add, we're not prefilling the form with an existing record
* But if the user has previously hit submit and the validation has found an error,
* then we inject what was previously entered.
*
* @return mixed The data for the form.
*
* @since 1.6
*/
protected function loadFormData()
{
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState(
'com_helloworld.edit.helloworld.data',
array()
);
return $data;
}
/**
* Method to get the script that have to be included on the form
* This returns the script associated with helloworld field greeting validation
*
* @return string Script files
*/
public function getScript()
{
return 'administrator/components/com_helloworld/models/forms/helloworld.js';
}
}
Handling the form HTTP POST
As in the admin case, we'll need to create a new controller in the /controllers subdirectory with save() and cancel() methods, and we'll need a model with a save() method. In fact, because the above model class (in site/models/form.php) extends JModelAdmin, we'll be able to reuse it without adding any more code. (For just displaying the form our model class could have extended JModelForm, but JModelAdmin extends JModelForm and provides additional functions such as the save() one which we need).
Note that we don't need any new view file or layout file, because we're just going to redirect the user back to the same form.
So the only new file we need is a new controller in a new controllers subdirectory:
site/controllers/helloworld.php
<?php
/**
* @package Joomla.Site
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* HelloWorld Controller
*
* @package Joomla.Site
* @subpackage com_helloworld
*
* Used to handle the http POST from the front-end form which allows
* users to enter a new helloworld message
*
*/
class HelloWorldControllerHelloWorld extends JControllerForm
{
public function cancel($key = null)
{
parent::cancel($key);
// set up the redirect back to the same form
$this->setRedirect(
(string)JUri::getInstance(),
JText::_('COM_HELLOWORLD_ADD_CANCELLED')
);
}
/*
* Function handing the save for adding a new helloworld record
* Based on the save() function in the JControllerForm class
*/
public function save($key = null, $urlVar = null)
{
// Check for request forgeries.
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$app = JFactory::getApplication();
$input = $app->input;
$model = $this->getModel('form');
// Get the current URI to set in redirects. As we're handling a POST,
// this URI comes from the <form action="..."> attribute in the layout file above
$currentUri = (string)JUri::getInstance();
// Check that this user is allowed to add a new record
if (!JFactory::getUser()->authorise( "core.create", "com_helloworld"))
{
$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
$app->setHeader('status', 403, true);
return;
}
// get the data from the HTTP POST request
$data = $input->get('jform', array(), 'array');
// set up context for saving form data
$context = "$this->option.edit.$this->context";
// Validate the posted data.
// First we need to set up an instance of the form ...
$form = $model->getForm($data, false);
if (!$form)
{
$app->enqueueMessage($model->getError(), 'error');
return false;
}
// ... and then we validate the data against it
// The validate function called below results in the running of the validate="..." routines
// specified against the fields in the form xml file, and also filters the data
// according to the filter="..." specified in the same place (removing html tags by default in strings)
$validData = $model->validate($form, $data);
// Handle the case where there are validation errors
if ($validData === false)
{
// Get the validation messages.
$errors = $model->getErrors();
// Display up to three validation messages to the user.
for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
{
if ($errors[$i] instanceof Exception)
{
$app->enqueueMessage($errors[$i]->getMessage(), 'warning');
}
else
{
$app->enqueueMessage($errors[$i], 'warning');
}
}
// Save the form data in the session.
$app->setUserState($context . '.data', $data);
// Redirect back to the same screen.
$this->setRedirect($currentUri);
return false;
}
// add the 'created by' and 'created' date fields
$validData['created_by'] = JFactory::getUser()->get('id', 0);
$validData['created'] = date('Y-m-d h:i:s');
// Attempt to save the data.
if (!$model->save($validData))
{
// Handle the case where the save failed
// Save the data in the session.
$app->setUserState($context . '.data', $validData);
// Redirect back to the edit screen.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
$this->setRedirect($currentUri);
return false;
}
// clear the data in the form
$app->setUserState($context . '.data', null);
// notify the administrator that a new helloworld message has been added on the front end
// get the id of the person to notify from global config
$params = $app->getParams();
$userid_to_email = (int) $params->get('user_to_email');
$user_to_email = JUser::getInstance($userid_to_email);
$to_address = $user_to_email->get("email");
// get the current user (if any)
$current_user = JFactory::getUser();
if ($current_user->get("id") > 0)
{
$current_username = $current_user->get("username");
}
else
{
$current_username = "a visitor to the site";
}
// get the Mailer object, set up the email to be sent, and send it
$mailer = JFactory::getMailer();
$mailer->addRecipient($to_address);
$mailer->setSubject("New helloworld message added by " . $current_username);
$mailer->setBody("New greeting is " . $validData['greeting']);
try
{
$mailer->send();
}
catch (Exception $e)
{
JLog::add('Caught exception: ' . $e->getMessage(), JLog::Error, 'jerror');
}
$this->setRedirect(
$currentUri,
JText::_('COM_HELLOWORLD_ADD_SUCCESSFUL')
);
return true;
}
}
In the above file we've been able to reuse the cancel() method from the parent JControllerForm class, with the exception that we want to redirect back to the same form. (The parent cancel() method redirects back to the view showing the list of records - as in the admin case).
However, our save() method functionality is significantly different from that of the parent class, so it's easier just to write our own. Note that we're recording the user and created date/time for records added via the front-end only. If we wanted to record this information for all records, then we'd need to override a save() function for the backend as well to include setting those fields.
The mailing functionality relies on you having set up mail in your Joomla instance. If you're using localhost then one possibility is to configure this using a gmail account, and you can easily find the smtp settings for this on the Internet. Note that you'll need to allow "less secure apps" on the gmail account.
Paramètres de configuration
We've introduced two new configuration parameters - the captcha to display on the form, and the user to email with notification of a new helloworld message being added. So update the configuration settings as follows:
admin/config.xml
<?xml version="1.0" encoding="utf-8"?>
<config>
<fieldset
name="greetings"
label="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL"
description="COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC"
>
<field
name="show_category"
type="radio"
label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC"
default="0"
>
<option value="0">JHIDE</option>
<option value="1">JSHOW</option>
</field>
<field
name="captcha"
type="plugins"
folder="captcha"
label="COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_DESC"
default="0"
filter="cmd"
>
<option value="">JOPTION_USE_DEFAULT</option>
<option value="0">JOPTION_DO_NOT_USE</option>
</field>
<field
name="user_to_email"
type="user"
label="COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_LABEL"
description="COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_DESC"
default="0"
>
</field>
</fieldset>
<fieldset
name="permissions"
label="JCONFIG_PERMISSIONS_LABEL"
description="JCONFIG_PERMISSIONS_DESC"
>
<field
name="rules"
type="rules"
label="JCONFIG_PERMISSIONS_LABEL"
class="inputbox"
validate="rules"
filter="rules"
component="com_helloworld"
section="component"
/>
</fieldset>
</config>
Display the new fields on the Admin list form
We want to update the admin helloworld list layout file to include the new Author and Created Date fields. This means that we also need to update our model to include these fields in the SQL query.
In addition, we've changed column ordering mechanism from what it was in Adding decorations to the backend to the more modern way that this is handled.
admin/views/helloworlds/view.html.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* HelloWorlds View
*
* @since 0.0.1
*/
class HelloWorldViewHelloWorlds extends JViewLegacy
{
/**
* Display the Hello World view
*
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
*
* @return void
*/
function display($tpl = null)
{
// Get application
$app = JFactory::getApplication();
$context = "helloworld.list.admin.helloworld";
// Get data from the model
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
$this->state = $this->get('State');
// Remove the old ordering mechanism
//$this->filter_order = $app->getUserStateFromRequest($context.'filter_order', 'filter_order', 'greeting', 'cmd');
//$this->filter_order_Dir = $app->getUserStateFromRequest($context.'filter_order_Dir', 'filter_order_Dir', 'asc', 'cmd');
$this->filterForm = $this->get('FilterForm');
$this->activeFilters = $this->get('ActiveFilters');
// What Access Permissions does this user have? What can (s)he do?
$this->canDo = JHelperContent::getActions('com_helloworld');
// Check for errors.
if (count($errors = $this->get('Errors')))
{
JError::raiseError(500, implode('<br />', $errors));
return false;
}
// Set the submenu
HelloWorldHelper::addSubmenu('helloworlds');
// Set the toolbar and number of found items
$this->addToolBar();
// Display the template
parent::display($tpl);
// Set the document
$this->setDocument();
}
/**
* Add the page title and toolbar.
*
* @return void
*
* @since 1.6
*/
protected function addToolBar()
{
$title = JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLDS');
if ($this->pagination->total)
{
$title .= "<span style='font-size: 0.5em; vertical-align: middle;'>(" . $this->pagination->total . ")</span>";
}
JToolBarHelper::title($title, 'helloworld');
if ($this->canDo->get('core.create'))
{
JToolBarHelper::addNew('helloworld.add', 'JTOOLBAR_NEW');
}
if ($this->canDo->get('core.edit'))
{
JToolBarHelper::editList('helloworld.edit', 'JTOOLBAR_EDIT');
}
if ($this->canDo->get('core.delete'))
{
JToolBarHelper::deleteList('', 'helloworlds.delete', 'JTOOLBAR_DELETE');
}
if ($this->canDo->get('core.admin'))
{
JToolBarHelper::divider();
JToolBarHelper::preferences('com_helloworld');
}
}
/**
* Method to set up the document properties
*
* @return void
*/
protected function setDocument()
{
$document = JFactory::getDocument();
$document->setTitle(JText::_('COM_HELLOWORLD_ADMINISTRATION'));
}
}
Note that in the layout file below the hidden input fields filter_order and filter_order_Dir have been removed.
admin/views/helloworlds/tmpl/default.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted Access');
JHtml::_('formbehavior.chosen', 'select');
$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));
?>
<form action="index.php?option=com_helloworld&view=helloworlds" method="post" id="adminForm" name="adminForm">
<div id="j-sidebar-container" class="span2">
<?php echo JHtmlSidebar::render(); ?>
</div>
<div id="j-main-container" class="span10">
<div class="row-fluid">
<div class="span12">
<?php echo JText::_('COM_HELLOWORLD_HELLOWORLDS_FILTER'); ?>
<?php
echo JLayoutHelper::render(
'joomla.searchtools.default',
array('view' => $this)
);
?>
</div>
</div>
<table class="table table-striped table-hover">
<thead>
<tr>
<th width="1%"><?php echo JText::_('COM_HELLOWORLD_NUM'); ?></th>
<th width="2%">
<?php echo JHtml::_('grid.checkall'); ?>
</th>
<th width="30%">
<?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_HELLOWORLDS_NAME', 'greeting', $listDirn, $listOrder); ?>
</th>
<th width="30%">
<?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_AUTHOR', 'author', $listDirn, $listOrder); ?>
</th>
<th width="30%">
<?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_CREATED_DATE', 'created', $listDirn, $listOrder); ?>
</th>
<th width="5%">
<?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_PUBLISHED', 'published', $listDirn, $listOrder); ?>
</th>
<th width="2%">
<?php echo JHtml::_('searchtools.sort', 'COM_HELLOWORLD_ID', 'id', $listDirn, $listOrder); ?>
</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="5">
<?php echo $this->pagination->getListFooter(); ?>
</td>
</tr>
</tfoot>
<tbody>
<?php if (!empty($this->items)) : ?>
<?php foreach ($this->items as $i => $row) :
$link = JRoute::_('index.php?option=com_helloworld&task=helloworld.edit&id=' . $row->id);
?>
<tr>
<td><?php echo $this->pagination->getRowOffset($i); ?></td>
<td>
<?php echo JHtml::_('grid.id', $i, $row->id); ?>
</td>
<td>
<a href="<?php echo $link; ?>" title="<?php echo JText::_('COM_HELLOWORLD_EDIT_HELLOWORLD'); ?>">
<?php echo $row->greeting; ?>
</a>
<div class="small">
<?php echo JText::_('JCATEGORY') . ': ' . $this->escape($row->category_title); ?>
</div>
</td>
<td align="center">
<?php echo $row->author; ?>
</td>
<td align="center">
<?php echo substr($row->created, 0, 10); ?>
</td>
<td align="center">
<?php echo JHtml::_('jgrid.published', $row->published, $i, 'helloworlds.', true, 'cb'); ?>
</td>
<td align="center">
<?php echo $row->id; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<input type="hidden" name="task" value=""/>
<input type="hidden" name="boxchecked" value="0"/>
<?php echo JHtml::_('form.token'); ?>
</div>
</form>
Instead of the using the hidden fields "filter_order" and "filter_order_Dir" to keep track of the current column for ordering and direction, we will use the "list"["fullordering"] field, and this will now be displayed on the form as well (as is done within com_content for the Articles view). We'll also need to include the new language strings in this field in our admin language file.
admin/models/forms/filter_helloworlds.xml
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="filter">
<field
name="search"
type="text"
label="COM_BANNERS_SEARCH_IN_TITLE"
hint="JSEARCH_FILTER"
class="js-stools-search-string"
/>
<field
name="published"
type="status"
label="JOPTION_SELECT_PUBLISHED"
description="JOPTION_SELECT_PUBLISHED_DESC"
onchange="this.form.submit();"
>
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="COM_HELLOWORLD_LIST_FULL_ORDERING"
description="COM_HELLOWORLD_LIST_FULL_ORDERING_DESC"
onchange="this.form.submit();"
default="greeting ASC"
>
<option value="">JGLOBAL_SORT_BY</option>
<option value="greeting ASC">COM_HELLOWORLD_ORDERING_ASC</option>
<option value="greeting DESC">COM_HELLOWORLD_ORDERING_DESC</option>
<option value="id ASC">JGRID_HEADING_ID_ASC</option>
<option value="id DESC">JGRID_HEADING_ID_DESC</option>
<option value="published ASC">COM_HELLOWORLD_PUBLISHED_ASC</option>
<option value="published DESC">COM_HELLOWORLD_PUBLISHED_DESC</option>
<option value="author ASC">COM_HELLOWORLD_AUTHOR_ASC</option>
<option value="author DESC">COM_HELLOWORLD_AUTHOR_DESC</option>
<option value="created ASC">COM_HELLOWORLD_CREATED_ASC</option>
<option value="created DESC">COM_HELLOWORLD_CREATED_DESC</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="25"
label="COM_CONTENT_LIST_LIMIT"
description="COM_HELLOWORLD_LIST_LIMIT_DESC"
onchange="this.form.submit();"
/>
</fields>
</form>
The above status type field (second field element, with name="published") displays the status values "Trashed" and "Archived" which the Helloworld component doesn't support. We could define our own custom helloworldStatus type field which displayed only the publishing options, but as defining such custom fields has already been covered in the step Using the database with our "helloworld" custom field, we won't bother with that here.
Within the model we need to get the author and created date fields from the database, and we also need to add these to the filter_fields array of fields which relate to sortable columns.
admin/models/helloworlds.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_helloworld
*
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
/**
* HelloWorldList Model
*
* @since 0.0.1
*/
class HelloWorldModelHelloWorlds extends JModelList
{
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
*
* @see JController
* @since 1.6
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id',
'greeting',
'author',
'created',
'published'
);
}
parent::__construct($config);
}
/**
* Method to build an SQL query to load the list data.
*
* @return string An SQL query
*/
protected function getListQuery()
{
// Initialize variables.
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// Create the base select statement.
$query->select('a.id as id, a.greeting as greeting, a.published as published, a.created as created')
->from($db->quoteName('#__helloworld', 'a'));
// Join over the categories.
$query->select($db->quoteName('c.title', 'category_title'))
->join('LEFT', $db->quoteName('#__categories', 'c') . ' ON c.id = a.catid');
// Join with users table to get the username of the author
$query->select($db->quoteName('u.username', 'author'))
->join('LEFT', $db->quoteName('#__users', 'u') . ' ON u.id = a.created_by');
// Filter: like / search
$search = $this->getState('filter.search');
if (!empty($search))
{
$like = $db->quote('%' . $search . '%');
$query->where('greeting LIKE ' . $like);
}
// Filter by published state
$published = $this->getState('filter.published');
if (is_numeric($published))
{
$query->where('a.published = ' . (int) $published);
}
elseif ($published === '')
{
$query->where('(a.published IN (0, 1))');
}
// Add the list ordering clause.
$orderCol = $this->state->get('list.ordering', 'greeting');
$orderDirn = $this->state->get('list.direction', 'asc');
$query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));
return $query;
}
}
Updated Language Strings
site/language/en-GB/en-GB.com_helloworld.ini
; add new message form
COM_HELLOWORLD_LEGEND_DETAILS="New Helloworld Message Details"
COM_HELLOWORLD_HELLOWORLD_CREATING="Add message"
COM_HELLOWORLD_HELLOWORLD_ERROR_UNACCEPTABLE="Sorry, you have an error"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Message details"
COM_HELLOWORLD_HELLOWORLD_GREETING_LABEL="Greeting"
COM_HELLOWORLD_HELLOWORLD_GREETING_DESC="Please specify the greeting to add"
COM_HELLOWORLD_HELLOWORLD_GREETING_HINT="Letters only!"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL="Category"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC="Please select the associated category"
COM_HELLOWORLD_HELLOWORLD_MESSAGE_LABEL="Reason"
COM_HELLOWORLD_HELLOWORLD_MESSAGE_DESC="Please say why you're adding this greeting"
COM_HELLOWORLD_HELLOWORLD_MESSAGE_HINT="No HTML tags!"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_LABEL="Spam protection"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_DESC="Prove you're a real person!"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Display category or not?"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="Select if you want the category displayed too"
; save and cancel confirmation messages
COM_HELLOWORLD_ADD_SUCCESSFUL="New greeting successfully saved"
COM_HELLOWORLD_ADD_CANCELLED="New greeting cancelled ok"
admin/language/en-GB/en-GB.com_helloworld.sys.ini
; Joomla! Project
; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
; Note : All ini files need to be saved as UTF-8
COM_HELLOWORLD="Hello World!"
COM_HELLOWORLD_DESCRIPTION="This is the Hello World description"
COM_HELLOWORLD_HELLOWORLD_VIEW_DEFAULT_TITLE="Hello World"
COM_HELLOWORLD_HELLOWORLD_VIEW_DEFAULT_DESC="This view displays a selected message"
COM_HELLOWORLD_ADD_VIEW_TITLE="Hello World form"
COM_HELLOWORLD_ADD_VIEW_DESC="This displays a form to allow the user to enter a new message"
COM_HELLOWORLD_INSTALL_TEXT="HelloWorld Install script"
COM_HELLOWORLD_MENU="Hello World!"
COM_HELLOWORLD_POSTFLIGHT_DISCOVER_INSTALL_TEXT="HelloWorld postflight discover install script"
COM_HELLOWORLD_POSTFLIGHT_INSTALL_TEXT="HelloWorld postflight install script"
COM_HELLOWORLD_POSTFLIGHT_UNINSTALL_TEXT="HelloWorld postflight uninstall script"
COM_HELLOWORLD_POSTFLIGHT_UPDATE_TEXT="HelloWorld postflight update script"
COM_HELLOWORLD_PREFLIGHT_DISCOVER_INSTALL_TEXT="HelloWorld preflight discover install script"
COM_HELLOWORLD_PREFLIGHT_INSTALL_TEXT="HelloWorld preflight install script"
COM_HELLOWORLD_PREFLIGHT_UNINSTALL_TEXT="HelloWorld preflight uninstall script"
COM_HELLOWORLD_PREFLIGHT_UPDATE_TEXT="HelloWorld preflight update script"
COM_HELLOWORLD_UNINSTALL_TEXT="HelloWorld Uninstall script"
COM_HELLOWORLD_UPDATE_TEXT="HelloWorld Update script. HelloWorld now updated to version %s."
admin/language/en-GB/en-GB.com_helloworld.ini
; Joomla! Project
; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
; Note : All ini files need to be saved as UTF-8
COM_HELLOWORLD_ADMINISTRATION="HelloWorld - Administration"
COM_HELLOWORLD_ADMINISTRATION_CATEGORIES="HelloWorld - Categories"
COM_HELLOWORLD_NUM="#"
COM_HELLOWORLD_HELLOWORLDS_FILTER="Filters"
COM_HELLOWORLD_AUTHOR="Author"
COM_HELLOWORLD_CREATED_DATE="Created"
COM_HELLOWORLD_PUBLISHED="Published"
COM_HELLOWORLD_HELLOWORLDS_NAME="Name"
COM_HELLOWORLD_ID="Id"
COM_HELLOWORLD_HELLOWORLD_CREATING="HelloWorld - Creating"
COM_HELLOWORLD_HELLOWORLD_DETAILS="Details"
COM_HELLOWORLD_HELLOWORLD_EDITING="HelloWorld - Editing"
COM_HELLOWORLD_HELLOWORLD_ERROR_UNACCEPTABLE="Some values are unacceptable"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_DESC="The category the messages belongs to"
COM_HELLOWORLD_HELLOWORLD_FIELD_CATID_LABEL="Category"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_DESC="This message will be displayed"
COM_HELLOWORLD_HELLOWORLD_FIELD_GREETING_LABEL="Message"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL="Show category"
COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC="If set to Show, the title of the message’s category will show."
COM_HELLOWORLD_HELLOWORLD_HEADING_GREETING="Greeting"
COM_HELLOWORLD_HELLOWORLD_HEADING_ID="Id"
COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT="HelloWorld manager: Edit Message"
COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW="HelloWorld manager: New Message"
COM_HELLOWORLD_MANAGER_HELLOWORLDS="HelloWorld manager"
COM_HELLOWORLD_EDIT_HELLOWORLD="Edit message"
COM_HELLOWORLD_N_ITEMS_DELETED_1="One message deleted"
COM_HELLOWORLD_N_ITEMS_DELETED_MORE="%d messages deleted"
COM_HELLOWORLD_N_ITEMS_PUBLISHED="%d message(s) published"
COM_HELLOWORLD_N_ITEMS_UNPUBLISHED="%d message(s) unpublished"
COM_HELLOWORLD_HELLOWORLD_GREETING_LABEL="Greeting"
COM_HELLOWORLD_HELLOWORLD_GREETING_DESC="Add Hello World Greeting"
COM_HELLOWORLD_SUBMENU_MESSAGES="Messages"
COM_HELLOWORLD_SUBMENU_CATEGORIES="Categories"
COM_HELLOWORLD_CONFIGURATION="HelloWorld Configuration"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_LABEL="Messages settings"
COM_HELLOWORLD_CONFIG_GREETING_SETTINGS_DESC="Settings that will be applied to all messages by default"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_LABEL="Captcha"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTCHA_DESC="Select Captcha to use on front end form"
COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_LABEL="User to email"
COM_HELLOWORLD_HELLOWORLD_FIELD_USER_TO_EMAIL_DESC="Select user to email when a new message is entered on front end"
COM_HELLOWORLD_FIELDSET_RULES="Message Permissions"
COM_HELLOWORLD_FIELD_RULES_LABEL="Permissions"
COM_HELLOWORLD_ACCESS_DELETE_DESC="Is this group allowed to edit this message?"
COM_HELLOWORLD_ACCESS_DELETE_DESC="Is this group allowed to delete this message?"
COM_HELLOWORLD_TAB_NEW_MESSAGE="New Message"
COM_HELLOWORLD_TAB_EDIT_MESSAGE="Message Details"
COM_HELLOWORLD_TAB_PARAMS="Parameters"
COM_HELLOWORLD_TAB_PERMISSIONS="Permissions"
COM_HELLOWORLD_LEGEND_DETAILS="Message Details"
COM_HELLOWORLD_LEGEND_PARAMS="Message Parameters"
COM_HELLOWORLD_LEGEND_PERMISSIONS="Message Permissions"
; Column ordering in the Helloworlds view
COM_HELLOWORLD_ORDERING_ASC="Greeting ascending"
COM_HELLOWORLD_ORDERING_DESC="Greeting descending"
COM_HELLOWORLD_AUTHOR_ASC="Author ascending"
COM_HELLOWORLD_AUTHOR_DESC="Author descending"
COM_HELLOWORLD_CREATED_ASC="Creation date ascending"
COM_HELLOWORLD_CREATED_DESC="Creation date descending"
COM_HELLOWORLD_PUBLISHED_ASC="Unpublished first"
COM_HELLOWORLD_PUBLISHED_DESC="Published first"
Packaging the Component
Contenu de votre répertoire de code. Chaque lien ci-dessous vous emmène vers l'étape du didacticiel qui contient la dernière version du code source de ce fichier.
- helloworld.xml
- script.php
- site/helloworld.php
- site/index.html
- site/controller.php
- site/controllers/helloworld.php
- site/views/index.html
- site/views/helloworld/index.html
- site/views/helloworld/view.html.php
- site/views/helloworld/tmpl/index.html
- site/views/helloworld/tmpl/default.xml
- site/views/helloworld/tmpl/default.php
- site/views/form/index.html
- site/views/form/view.html.php
- site/views/form/tmpl/index.html
- site/views/form/tmpl/edit.php
- site/views/form/tmpl/edit.xml
- site/models/index.html
- site/models/helloworld.php
- site/models/form.php
- site/models/forms/index.html
- site/models/forms/add-form.xml
- site/language/index.html
- site/language/en-GB/index.html
- site/language/en-GB/en-GB.com_helloworld.ini
- admin/index.html
- admin/helloworld.php
- admin/config.xml
- admin/controller.php
- admin/access.xml
- admin/helpers/helloworld.php
- admin/helpers/index.html
- admin/sql/index.html
- admin/sql/install.mysql.utf8.sql
- admin/sql/uninstall.mysql.utf8.sql
- admin/sql/updates/index.html
- admin/sql/updates/mysql/index.html
- admin/sql/updates/mysql/0.0.1.sql
- admin/sql/updates/mysql/0.0.6.sql
- admin/sql/updates/mysql/0.0.12.sql
- admin/sql/updates/mysql/0.0.13.sql
- admin/sql/updates/mysql/0.0.14.sql
- admin/sql/updates/mysql/0.0.16.sql
- admin/models/index.html
- admin/models/fields/index.html
- admin/models/fields/helloworld.php
- admin/models/helloworlds.php
- admin/models/helloworld.php
- admin/models/forms/filter_helloworlds.xml
- admin/models/forms/index.html
- admin/models/forms/helloworld.js
- admin/models/forms/helloworld.xml
- admin/models/rules/greeting.php
- admin/models/rules/index.html
- admin/controllers/helloworld.php
- admin/controllers/helloworlds.php
- admin/controllers/index.html
- admin/views/index.html
- admin/views/helloworld/index.html
- admin/views/helloworld/view.html.php
- admin/views/helloworld/tmpl/index.html
- admin/views/helloworld/tmpl/edit.php
- admin/views/helloworld/submitbutton.js
- admin/views/helloworlds/index.html
- admin/views/helloworlds/view.html.php
- admin/views/helloworlds/tmpl/index.html
- admin/views/helloworlds/tmpl/default.php
- admin/tables/index.html
- admin/tables/helloworld.php
- admin/language/index.html
- admin/language/en-GB/index.html
- admin/language/en-GB/en-GB.com_helloworld.ini
- admin/language/en-GB/en-GB.com_helloworld.sys.ini
- media/index.html
- media/images/index.html
- media/images/tux-16x16.png
- media/images/tux-48x48.png
helloworld.xml
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.0" method="upgrade">
<name>COM_HELLOWORLD</name>
<!-- The following elements are optional and free of formatting constraints -->
<creationDate>January 2018</creationDate>
<author>John Doe</author>
<authorEmail>john.doe@example.org</authorEmail>
<authorUrl>http://www.example.org</authorUrl>
<copyright>Copyright Info</copyright>
<license>License Info</license>
<!-- The version string is recorded in the components table -->
<version>0.0.16</version>
<!-- The description is optional and defaults to the name -->
<description>COM_HELLOWORLD_DESCRIPTION</description>
<!-- Runs on install/uninstall/update; New in 2.5 -->
<scriptfile>script.php</scriptfile>
<install> <!-- Runs on install -->
<sql>
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
</sql>
</install>
<uninstall> <!-- Runs on uninstall -->
<sql>
<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
</sql>
</uninstall>
<update> <!-- Runs on update; New since J2.5 -->
<schemas>
<schemapath type="mysql">sql/updates/mysql</schemapath>
</schemas>
</update>
<!-- Site Main File Copy Section -->
<!-- Note the folder attribute: This attribute describes the folder
to copy FROM in the package to install therefore files copied
in this section are copied from /site/ in the package -->
<files folder="site">
<filename>index.html</filename>
<filename>helloworld.php</filename>
<filename>controller.php</filename>
<folder>controllers</folder>
<folder>views</folder>
<folder>models</folder>
</files>
<languages folder="site/language">
<language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language>
</languages>
<media destination="com_helloworld" folder="media">
<filename>index.html</filename>
<folder>images</folder>
</media>
<administration>
<!-- Administration Menu Section -->
<menu link='index.php?option=com_helloworld' img="../media/com_helloworld/images/tux-16x16.png">COM_HELLOWORLD_MENU</menu>
<!-- Administration Main File Copy Section -->
<!-- Note the folder attribute: This attribute describes the folder
to copy FROM in the package to install therefore files copied
in this section are copied from /admin/ in the package -->
<files folder="admin">
<!-- Admin Main File Copy Section -->
<filename>index.html</filename>
<filename>config.xml</filename>
<filename>helloworld.php</filename>
<filename>controller.php</filename>
<filename>access.xml</filename>
<!-- SQL files section -->
<folder>sql</folder>
<!-- tables files section -->
<folder>tables</folder>
<!-- models files section -->
<folder>models</folder>
<!-- views files section -->
<folder>views</folder>
<!-- controllers files section -->
<folder>controllers</folder>
<!-- helpers files section -->
<folder>helpers</folder>
</files>
<languages folder="admin/language">
<language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language>
<language tag="en-GB">en-GB/en-GB.com_helloworld.sys.ini</language>
</languages>
</administration>
</extension>