J3.x

Développement d'un composant MVC - Ajout d'ACL

From Joomla! Documentation

< J3.x:Developing an MVC Component
This page is a translated version of the page J3.x:Developing an MVC Component/Adding ACL and the translation is 100% complete.

Other languages:
العربية • ‎English • ‎español • ‎français
Joomla! 
3.x
Didacticiel
Développement d'un composant MVC


Ceci est une série qui regroupe plusieurs articles pour devenir un didacticiel sur la façon de développer un Composant pour Joomla! Joomla 3.x 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.



Introduction

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.

Ajouter des contrôles d'accès

Grâce au contrôle d'accès de Joomla, nous pouvons définir les groupes d'utilisateurs qui sont autorisés ou non à faire des actions dans votre composant. Dans cet exemple, nous utilisons les actions qui sont définies nativement. Pour le composant dans son ensemble : core.admin (accès à la configuration) et core.manage (accès au backend). Et à différents niveaux d'actions tels que créer, supprimer et modifier. Outre ces actions natives, vous pouvez définir vos propres actions, mais cela n'est souvent pas nécessaire et ne figure donc pas dans cet exemple. L'accès Voir/Lire n'est pas géré via ces actions mais par les niveaux d'accès des vues. Consultez la documentation générale sur les ACL de Joomla pour cela.

La liste actuelle est stockée dans la table #__assets : quels sont les groupes d'utilisateurs autorisés ou non à faire quels types d'actions sur quelles ressources (assets). C'est l'implémentation de la liste de contrôle d'Accès (ACL).

Dans cet article, nous allons vous montrer comment ajouter et utiliser les droits d'accès à plusieurs niveaux : pour votre composant dans son ensemble, pour les catégories et pour les éléments individuels.

Afin de tester cette fonctionnalité, créez des utilisateurs et associez les à des groupes d'utilisateurs qui peuvent accéder au fonctionnalités de l'administration du site (ie les groupes d'utilisateurs qui ont les droits "Connexion à l'administration" dans la Configuration > Droits). Par défaut, il s'agit de Gestionnaire et Administrateur, mais vous pouvez également définir vos propres groupes d'utilisateur, et par exemple les créer en tant qu'enfant de Gestionnaire ou Administrateur.

Si vous n'êtes déjà très familiarisé avec le Contrôle d'Accès Joomla! alors il est recommandé de regarder cette vidéo entre la 2ème minute et la 32ème minute Explication sur la Liste de Contrôle d'Accès et lisez le Tutoriel sur la Liste de Contrôle d'Accès.

Trois vidéos sont associées avec les étapes de ce didacticiel pour traiter de l'Infrastructure de contrôle d'accès Joomla!, une explication de l'étape code du didactiel et une vidéo supplémentaire sur la vue des niveaux d'accès.

Pré-requis d'ACL minimum au niveau composant

Pour un composant sous Joomla! 2.5+, deux actions doivent être définies au niveau du composant afin de permettre la mise en oeuvre des ACL :

  • Configuration (core.admin): quels sont les groupes autorisés à configurer les droits au niveau du composant via le bouton 'Options' de la barre d'outils ?
  • Accès au composant (core.manage): quels sont les groupes autorisés à accéder au backend du composant ?

La mise en oeuvre de ces ACL de base se fait en 4 étapes simples :

Ajouter les 2 niveaux d'actions minimales du composant au fichier access.xml

Un fichier d'ACL minimal access.xml devrait contenir seulement ces 2 actions de base :

Basic admin/access.xml

<?xml version="1.0" encoding="utf-8" ?>
<access component="com_helloworld">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
	</section>
</access>

Consultez admin/access.xml pour voir la version actuelle et une version plus élaborée.

Ajouter les droits au fieldset du fichier config.xml

Ajoutez les droits de fieldset suivants au fichier admin/config.xml afin d'être en mesure de définir les niveaux de droits de notre composant.

	<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>

Consultez ci-dessous un exemple plus élaboré d'un fichier config.xml pour voir où insérer exactement ce code.

Ajouter le bouton 'Options' à la barre d'outils lorsque l'utilisateur a les droits nécessaires

Dans le fichier admin/views/helloworlds/view.html.php, vous pouvez ajouter le code suivant afin de vérifier si l'utilisateur est en mesure de modifier les préférences :

    // Options button.
    if (JFactory::getUser()->authorise('core.admin', 'com_helloworld')) 
    {
	JToolBarHelper::preferences('com_helloworld');
    }

Consultez ci-après un exemple plus élaboré de admin/views/helloworlds/view.html.php dans lequel JToolBarHelper::preferences('com_helloworld') se fait dans une méthode addToolBar() conjointement avec les autres boutons de la barre d'outils et la vérification JUser->authorise() se fait avec JHelperContent, résultant en la propriété $canDo.

Restreindre l'accès au backend du composant aux seuls groupes d'utilisateurs autorisés

Afin de contrôler l'accès au backend du composant, ajoutez les lignes suivantes au fichier d'entrée admin/helloworld.php :

// Access check: is this user allowed to access the backend of this component?
if (!JFactory::getUser()->authorise('core.manage', 'com_helloworld')) 
{
	throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'));
}

Consultez ci-dessous le code complet du fichier admin/helloworld.php.

Ajouter des actions supplémentaires, notamment aux niveaux des catégories et des éléments

Lors de l'ajout d'actions et de niveaux supplémentaires, ces quatre étapes sont également réalisées :

En outre, il nous faut également réaliser les étapes suivantes :

Décrire les actions dont vous souhaitez contrôler l'accès

Chaque composant (ou une partie) a son propre ensemble de droits pouvant être contrôlés. Ils sont décrits dans un fichier access.xml situé à la racine du dossier admin. Dans cet exemple helloworld, les actions dont l'accès est contrôlé sont divisées en trois sections : au niveau du composant, au niveau de la catégorie et au niveau de l'élément. Un 'élément' est appelé un 'message' dans notre exemple de composant, d'où le nom de la troisième section.

admin/access.xml

<?xml version="1.0" encoding="utf-8" ?>
<access component="com_helloworld">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
	</section>
	<section name="category">
		<action name="core.create" title="JACTION_CREATE" description="COM_CATEGORIES_ACCESS_CREATE_DESC" />
		<action name="core.delete" title="JACTION_DELETE" description="COM_CATEGORIES_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_CATEGORIES_ACCESS_EDIT_DESC" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CATEGORIES_ACCESS_EDITSTATE_DESC" />
		<action name="core.edit.own" title="JACTION_EDITOWN" description="COM_CATEGORIES_ACCESS_EDITOWN_DESC" />
	</section>
	<section name="message">
		<action name="core.delete" title="JACTION_DELETE" description="COM_HELLOWORLD_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT" description="COM_HELLOWORLD_ACCESS_EDIT_DESC" />
	</section>
</access>

Ajouter les paramètres des droits dans les préférences du composant

Nous utilisons désormais les droits de contrôle d'accès dans notre composant, de ce fait, nous devons être en mesure de les définir au niveau du composant. Cela se fait via les préférences du composant : l'écran qui s'affiche après avoir cliqué sur le bouton 'Options'. Le fichier config.xml est un formulaire des définitions pour ces préférences. Nous pourrions également y définir les actions au niveau du composant, comme étant un enfant des règles de la balise field, mais il est préférable d'indiquer ces actions dans le fichier access.xml, ainsi, toutes les règles d'accès du composant seront en un seul et même endroit.

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>
	</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>

Afficher uniquement les boutons de la barre d'outil de droite

Les boutons de la barre d'outils à afficher dépendent des droits d'accès de l'utilisateur.

En même temps que les composants de base de Joomla!, nous utilisons JHelperContent::getActions() pour trouver les droits. Nous passons à cette fonction le nom du composant, et elle retourne un objet contenant toutes les Actions associées au composant helloworld, ainsi que (pour chaque Action) le fait que l'utilisateur actuellement connecté a ou non ce droit. Si ensuite nous appelons get('une.action') sur cet objet, il retourne 'true' ou 'false', selon que l'utilisateur a ou non ce droit.

Dans le fichier admin/views/helloworlds/view.html.php, ajoutez ce code :

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');
		$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')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// 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'));
	}
}

Dans le fichier admin/views/helloworld/view.html.php, ajoutez ce code :

admin/views/helloworld/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
 *
 * @since  0.0.1
 */
class HelloWorldViewHelloWorld extends JViewLegacy
{
	protected $form;
	protected $item;
	protected $script;
	protected $canDo;

	/**
	 * Display the Hello World view
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  void
	 */
	public function display($tpl = null)
	{
		// Get the Data
		$this->form = $this->get('Form');
		$this->item = $this->get('Item');
		$this->script = $this->get('Script');

		// What Access Permissions does this user have? What can (s)he do?
		$this->canDo = JHelperContent::getActions('com_helloworld', 'helloworld', $this->item->id);

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new Exception(implode("\n", $errors), 500);
		}

		// Set the toolbar
		$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()
	{
		$input = JFactory::getApplication()->input;

		// Hide Joomla Administrator Main menu
		$input->set('hidemainmenu', true);

		$isNew = ($this->item->id == 0);

		JToolBarHelper::title($isNew ? JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLD_NEW')
		                             : JText::_('COM_HELLOWORLD_MANAGER_HELLOWORLD_EDIT'), 'helloworld');
		// Build the actions for new and existing records.
		if ($isNew)
		{
			// For new records, check the create permission.
			if ($this->canDo->get('core.create')) 
			{
				JToolBarHelper::apply('helloworld.apply', 'JTOOLBAR_APPLY');
				JToolBarHelper::save('helloworld.save', 'JTOOLBAR_SAVE');
				JToolBarHelper::custom('helloworld.save2new', 'save-new.png', 'save-new_f2.png',
				                       'JTOOLBAR_SAVE_AND_NEW', false);
			}
			JToolBarHelper::cancel('helloworld.cancel', 'JTOOLBAR_CANCEL');
		}
		else
		{
			if ($this->canDo->get('core.edit'))
			{
				// We can save the new record
				JToolBarHelper::apply('helloworld.apply', 'JTOOLBAR_APPLY');
				JToolBarHelper::save('helloworld.save', 'JTOOLBAR_SAVE');
 
				// We can save this record, but check the create permission to see
				// if we can return to make a new one.
				if ($this->canDo->get('core.create')) 
				{
					JToolBarHelper::custom('helloworld.save2new', 'save-new.png', 'save-new_f2.png',
					                       'JTOOLBAR_SAVE_AND_NEW', false);
				}
			}
			if ($this->canDo->get('core.create')) 
			{
				JToolBarHelper::custom('helloworld.save2copy', 'save-copy.png', 'save-copy_f2.png',
				                       'JTOOLBAR_SAVE_AS_COPY', false);
			}
			JToolBarHelper::cancel('helloworld.cancel', 'JTOOLBAR_CLOSE');
		}
	}
	/**
	 * Method to set up the document properties
	 *
	 * @return void
	 */
	protected function setDocument() 
	{
		$isNew = ($this->item->id == 0);
		$document = JFactory::getDocument();
		$document->setTitle($isNew ? JText::_('COM_HELLOWORLD_HELLOWORLD_CREATING')
		                           : JText::_('COM_HELLOWORLD_HELLOWORLD_EDITING'));
		$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');
	}
}

Restreindre l'accès au composant

L'idée principale des ACL est de restreindre les actions à des groupes d'utilisateurs. La première action de restriction est l'accès au backend d'administration du composant lui-même. A l'aide de votre éditeur de fichier préféré, modifiez le fichier admin/helloworld.php et ajoutez ces lignes, contenant le contrôle d'accès.

admin/helloworld.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');

// Set some global property
$document = JFactory::getDocument();
$document->addStyleDeclaration('.icon-helloworld {background-image: url(../media/com_helloworld/images/tux-16x16.png);}');

// Access check: is this user allowed to access the backend of this component?
if (!JFactory::getUser()->authorise('core.manage', 'com_helloworld'))
{
	throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'));
}

// Require helper file
JLoader::register('HelloWorldHelper', JPATH_COMPONENT . '/helpers/helloworld.php');

// Get an instance of the controller prefixed by HelloWorld
$controller = JControllerLegacy::getInstance('HelloWorld');

// Perform the Request task
$controller->execute(JFactory::getApplication()->input->get('task'));;

// Redirect if set by the controller
$controller->redirect();

Ajouter la colonne asset_id à la table de la base de données

Afin d'être en mesure de travailler avec JTable, une colonne asset_id doit être ajoutée à la table #__helloworld de la base de données.

Ainsi, le fichier admin/sql/install.mysql.utf8.sql devient :

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',
	`greeting` VARCHAR(25) NOT NULL,
	`published` tinyint(4) NOT NULL,
	`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!'),
('Good bye World!');

Pour les mises à jour, nous ajoutons un fichier de mise à jour sql :

admin/sql/updates/mysql/0.0.14.sql

ALTER TABLE `#__helloworld` ADD COLUMN `asset_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`;

Restreindre l'accès aux messages

Jusqu'ici, nous avons restreint l'accès au composant lui-même, mais il nous faut également le faire au niveau du message.

Afin de vérifier les droits de "core.delete", il nous faut modifier la classe du modèle admin/models/helloworld.php en ajoutant ces lignes :

admin/models/helloworld.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 HelloWorldModelHelloWorld 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.helloworld',
			'helloworld',
			array(
				'control' => 'jform',
				'load_data' => $loadData
			)
		);

		if (empty($form))
		{
			return false;
		}

		return $form;
	}
	/**
	 * Method to get the script that have to be included on the form
	 *
	 * @return string	Script files
	 */
	public function getScript() 
	{
		return 'administrator/components/com_helloworld/models/forms/helloworld.js';
	}
	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @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()
		);

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}
	/**
	 * Method to check if it's OK to delete a message. Overrides JModelAdmin::canDelete
	 */
	protected function canDelete($record)
	{
		if( !empty( $record->id ) )
		{
			return JFactory::getUser()->authorise( "core.delete", "com_helloworld.helloworld." . $record->id );
		}
	}
}

Afin de pouvoir contrôler "core.edit" (et, si vous le souhaitez, core.add), vous devez mettre à jour le sous-contrôleur (pas le modèle). Je ne suis pas sûr de savoir pourquoi il en est ainsi, mais c'est ainsi que procède les autres composants standards de Joomla. Ajoutez les lignes suivantes au fichier admin/controllers/helloworld.php :

admin/controllers/helloworld.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 Controller
 *
 * @package     Joomla.Administrator
 * @subpackage  com_helloworld
 * @since       0.0.9
 */
class HelloWorldControllerHelloWorld extends JControllerForm
{
	/**
	* Implement to allowAdd or not
	*
	* Not used at this time (but you can look at how other components use it....)
	* Overwrites: JControllerForm::allowAdd
	*
	* @param array $data
	* @return bool
	*/
	protected function allowAdd($data = array())
	{
		return parent::allowAdd($data);
	}
	/**
	* Implement to allow edit or not
	* Overwrites: JControllerForm::allowEdit
	*
	* @param array $data
	* @param string $key
	* @return bool
	*/
	protected function allowEdit($data = array(), $key = 'id')
	{
		$id = isset( $data[ $key ] ) ? $data[ $key ] : 0;
		if( !empty( $id ) )
		{
			return JFactory::getUser()->authorise( "core.edit", "com_helloworld.helloworld." . $id );
		}
	}
}

Vous remarquerez que allowAdd appelle simplement son parent. Je l'ai ajouté ici dans le cas où vous souhaiteriez l'utiliser dans votre composant. Si vous jetez un oeil à votre fichier admin/access.xml, vous remarquerez qu'aucune action core.add n'est définie pour les messages, il vous faudra donc, si besoin, l'ajouter, de même si vous souhaitez être en mesure de la configurer dans l'interface.

Paramétrer les valeurs de droits dans la table des assets

Afin de stocker les droits pour chaque message dans la table des assets de la base de données, in nous faut instruire la classe de la table associée au modèle afin d'enregistrer ces droits dans la table des assets.

JTable fournit non seulement une interface pour stocker les données de l'enregistrement lui-même dans l'élément de la table de base de données, mais aussi pour stocker les autorisations de cet enregistrement dans la table d'assets de la base de données. Par conséquent, nous devons ajouter des informations à la méthode bind() concernant les valeurs des droits. Nous devons également indiquer le nom de l'asset, son titre et l'id de l'asset parent via la JTable helloworld. Nous remplaçons donc 3 méthodes :

  • _getAssetName(): un nom unique pour cet asset, par lequel il peut être récupéré,
  • _getAssetTitle(): une façon plus conviviale d'identifier l'asset (n'a pas besoin d'être unique),
  • _getAssetParentId(): l'id d'asset du parent dans la table d'asset de la base de données (à partir duquel les droits sont hérités).

admin/tables/helloworld.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
defined('_JEXEC') or die('Restricted access');

/**
 * Hello Table class
 *
 * @since  0.0.1
 */
class HelloWorldTableHelloWorld extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  &$db  A database connector object
	 */
	function __construct(&$db)
	{
		parent::__construct('#__helloworld', 'id', $db);
	}
	/**
	 * Overloaded bind function
	 *
	 * @param       array           named array
	 * @return      null|string     null is operation was satisfactory, otherwise returns an error
	 * @see JTable:bind
	 * @since 1.5
	 */
	public function bind($array, $ignore = '')
	{
		if (isset($array['params']) && is_array($array['params']))
		{
			// Convert the params field to a string.
			$parameter = new JRegistry;
			$parameter->loadArray($array['params']);
			$array['params'] = (string)$parameter;
		}

		// Bind the rules.
		if (isset($array['rules']) && is_array($array['rules']))
		{
			$rules = new JAccessRules($array['rules']);
			$this->setRules($rules);
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Method to compute the default name of the asset.
	 * The default name is in the form `table_name.id`
	 * where id is the value of the primary key of the table.
	 *
	 * @return	string
	 * @since	2.5
	 */
	protected function _getAssetName()
	{
		$k = $this->_tbl_key;
		return 'com_helloworld.helloworld.'.(int) $this->$k;
	}
	/**
	 * Method to return the title to use for the asset table.
	 *
	 * @return	string
	 * @since	2.5
	 */
	protected function _getAssetTitle()
	{
		return $this->greeting;
	}
	/**
	 * Method to get the asset-parent-id of the item
	 *
	 * @return	int
	 */
	protected function _getAssetParentId(JTable $table = NULL, $id = NULL)
	{
		// We will retrieve the parent-asset from the Asset-table
		$assetParent = JTable::getInstance('Asset');
		// Default: if no asset-parent can be found we take the global asset
		$assetParentId = $assetParent->getRootId();

		// Find the parent-asset
		if (($this->catid)&& !empty($this->catid))
		{
			// The item has a category as asset-parent
			$assetParent->loadByName('com_helloworld.category.' . (int) $this->catid);
		}
		else
		{
			// The item has the component as asset-parent
			$assetParent->loadByName('com_helloworld');
		}

		// Return the found asset-parent-id
		if ($assetParent->id)
		{
			$assetParentId=$assetParent->id;
		}
		return $assetParentId;
	}
}

Le code pour _getAssetParentId() ci-dessus utilise JTableAsset pour récupérer l'id d'asset de l'asset parent. Ce qui diffère du code de la version actuelle du com_content, où l'id d'asset de la catégorie est récupéré à partir de la table #__categories de la base de données. Ceci est donc une autre possibilité, plusieurs chemins mènent à Rome. Toutefois, dans com_content, si un élément n'est pas catégorisé, alors l'id d'asset de l'asset général est retourné. Bien sur, ce ne serait pas bon, cela est corrigé ici en indiquant une catégorie par défaut uncategorised, de sorte qu'un article soit toujours catégorisé.

Afficher le réglage des droits au niveau de l'élément

Ajoutez le field rules au formulaire de définition du formulaire d'édition.

admin/models/forms/helloworld.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"
				validate="greeting"
				required="true"
				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>
	</fieldset>
	<fields name="params">
		<fieldset
				name="params"
				label="JGLOBAL_FIELDSET_DISPLAY_OPTIONS"
		>
			<field
					name="show_category"
					type="list"
					label="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_LABEL"
					description="COM_HELLOWORLD_HELLOWORLD_FIELD_SHOW_CATEGORY_DESC"
					default=""
			>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>
		</fieldset>
	</fields>
	<fieldset
			name="accesscontrol"
			label="COM_HELLOWORLD_FIELDSET_RULES"
	>
    	<field
				name="asset_id"
				type="hidden"
				filter="unset"
				/>
    	<field
				name="rules"
				type="rules"
				label="COM_HELLOWORLD_FIELD_RULES_LABEL"
				filter="rules"
				validate="rules"
				class="inputbox"
				component="com_helloworld"
				section="message"
				/>
    </fieldset>
</form>

La version précédente du fichier de layout edit.php va afficher le champ des droits automatiquement ; cependant, nous avons modifié le layout pour réaliser un affichage sous forme d'onglets, comme c'est le cas des autres composants Joomla!. Lorsqu'un utilisateur change un droit, un appel Ajax recalcule le Paramètre Calculé (Calculated Setting), et nous avons besoin d'un peu de javascript afin que cela fonctionne.

admin/views/helloworld/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
 */

// No direct access
defined('_JEXEC') or die('Restricted access');
JHtml::_('behavior.formvalidator');

// The following is to enable setting the permission's Calculated Setting 
// when you change the permission's Setting. 
// The core javascript code for initiating the Ajax request looks for a field
// with id="jform_title" and sets its value as the 'title' parameter to send in the Ajax request
JFactory::getDocument()->addScriptDeclaration('
	jQuery(document).ready(function() {
        greeting = jQuery("#jform_greeting").val();
		jQuery("#jform_title").val(greeting);
	});
');

?>
<form action="<?php echo JRoute::_('index.php?option=com_helloworld&layout=edit&id=' . (int) $this->item->id); ?>"
    method="post" name="adminForm" id="adminForm" class="form-validate">
    
    <input id="jform_title" type="hidden" name="helloworld-message-title"/>
    
    <div class="form-horizontal">

    <?php echo JHtml::_('bootstrap.startTabSet', 'myTab', array('active' => 'details')); ?>
    <?php echo JHtml::_('bootstrap.addTab', 'myTab', 'details', 
        empty($this->item->id) ? JText::_('COM_HELLOWORLD_TAB_NEW_MESSAGE') : JText::_('COM_HELLOWORLD_TAB_EDIT_MESSAGE')); ?>
        <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>
    <?php echo JHtml::_('bootstrap.endTab'); ?>

    <?php echo JHtml::_('bootstrap.addTab', 'myTab', 'params', JText::_('COM_HELLOWORLD_TAB_PARAMS')); ?>
        <fieldset class="adminform">
            <legend><?php echo JText::_('COM_HELLOWORLD_LEGEND_PARAMS') ?></legend>
            <div class="row-fluid">
                <div class="span6">
                    <?php echo $this->form->renderFieldset('params');  ?>
                </div>
            </div>
        </fieldset>
    <?php echo JHtml::_('bootstrap.endTab'); ?>

    <?php echo JHtml::_('bootstrap.addTab', 'myTab', 'permissions', JText::_('COM_HELLOWORLD_TAB_PERMISSIONS')); ?>
        <fieldset class="adminform">
            <legend><?php echo JText::_('COM_HELLOWORLD_LEGEND_PERMISSIONS') ?></legend>
            <div class="row-fluid">
                <div class="span12">
                    <?php echo $this->form->renderFieldset('accesscontrol');  ?>
                </div>
            </div>
        </fieldset>
    <?php echo JHtml::_('bootstrap.endTab'); ?>
    <?php echo JHtml::_('bootstrap.endTabSet'); ?>

    </div>
    <input type="hidden" name="task" value="helloworld.edit" />
    <?php echo JHtml::_('form.token'); ?>
</form>

Ajouter des chaînes de langue

Nous avons utilisé plusieurs chaînes de caractères de langues qui doivent être ajoutées au fichier de langues du backend.

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_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&rsquo;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_FIELDSET_RULES="Message Permissions"
COM_HELLOWORLD_FIELD_RULES_LABEL="Permissions"
COM_HELLOWORLD_ACCESS_EDIT_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="Edit Message"
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"

A lire

Pour plus d'informations sur les actions, les assets et les ACL, veuillez consulter les sur les pages suivantes :

Empaqueter le composant

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.

Créez un fichier compressé de ce répertoire ou téléchargez directement l'archive et installez-le en utilisant le gestionnaire des extensions Joomla. Vous pouvez ajouter un élément de menu pour ce composant à l'aide du gestionnaire de menus dans le backend.

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.14</version>
	<!-- The description is optional and defaults to the name -->
	<description>COM_HELLOWORLD_DESCRIPTION</description>

	<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>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>

Contributeurs