J3.x

開發一個 Model-View-Controller 元件/新增 Feed

From Joomla! Documentation

< J3.x:Developing an MVC Component
Revision as of 02:42, 5 February 2021 by Shawnhy (talk | contribs) (Created page with "== 修改 model ==")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Other languages:
English • ‎français • ‎italiano • ‎中文(台灣)‎
Joomla! 
3.x
教學
開發一個 Model-View-Controller 元件

在選單類型中新增一個變數請求

使用資料庫

基本的後台

新增語言管理

新增後台行為

新增後台的佈置

新增表單驗證

新增類別

新增設定介面

  1. 新增 ACL

新增一個安裝/移除/更新程式碼檔案

新增一個前台表單

  1. 新增一個圖片
  2. 新增一個 map
  3. 新增 AJAX
  4. 新增一個別名

使用語言過濾功能

  1. 新增一個 model
  2. 新增關聯
  3. 新增回存
  4. 新增排序
  5. 新增階層
  6. 新增版本控制
  7. 新增標籤
  8. 新增存取權限
  9. 新增批次作業
  10. 新增快取
  11. 新增 Feed

新增更新伺服器

  1. 新增客製化欄位
  2. Upgrading to Joomla4



這是一系列的多篇文章,旨在介紹如何開發一個 Joomla! VersionJoomla 3.x Model-View-Controller 元件

讓我們從簡介開始,您可以使用底下的導覽按鈕來瀏覽文章,或是右側的方塊中的連結(列出所有的文章)。



In this step we add a feed to our component. A video accompanying this tutorial may be found at Adding a Feed.

介紹

If you're not familiar with feeds then it's worth doing some background reading on the Internet. Joomla provides the capability of generating a feed of featured articles, or articles in a category – see for example this tutorial. In this tutorial step we enable equivalent functionality for generating a feed of helloworld records associated with a helloworld category.

On the Joomla website setting up a feed associated with an article category involves

  1. creating a menuitem pointing to a webpage showing articles in a given category
  2. enabling the Syndication Feed module and displaying it on that menuitem.

This module displays an RSS symbol on the webpage which has behind it a link to the URL of the RSS or Atom feed associated with that article category.

To subscribe to the feed a user copies this URL into his or her feed aggregator. When the feed aggregator sends an HTTP request to this URL, then the Joomla website returns an XML document containing details of the articles in that category – their titles, descriptions, published dates, etc.

So for example, if the webpage displays a list of the articles associated with a category "technology" then the URL behind the RSS image will point to the associated feed. When a browser or feed aggregator sends an HTTP request to that feed URL then the server will return an XML document in RSS or Atom format containing details of those articles with a category of "technology".

In this way a feed aggregator can send HTTP requests to all of the feeds to which the user has subscribed, and collate them so that user doesn't have to visit each of the individual news websites. And the user can configure the news aggregator to check the feeds at specific times, so that the information can been already collected and collated by the time the user wishes to view it.

Note that in addition to the syndicated feed which we're considering here, Joomla also has a newsfeed capability, which enables you to display a webpage showing information collected from syndicated feeds elsewhere – similar to what a feed aggregator would do – but this isn't the functionality which this tutorial step is about.


Approach

We currently have a site category view which displays the helloworld records associated with a given category. In this step we add an RSS syndicated feed to this page. This will result in an RSS symbol shown as an image, with a URL behind which will give an XML feed in RSS or Atom format of the helloworld records associated with that category.

If you haven't already got a site menuitem which points to a category view then you should configure one as a starting point.

To enable the syndicated feed we must do the following.

  1. Under Modules, find and enable the Syndicated Feed module. Click on this module to edit its options, and under the Menu Assignment tab ensure that it's shown just on the site page which displays the helloworld category view. Note that among the options there is one which defines whether Joomla presents the XML data in the RSS or Atom format.
  2. Define a helloworld configuration parameter which controls whether the RSS symbol with its link is shown or not. The Joomla code displays the RSS symbol only if it finds this parameter and it's set to Show.
  3. In the category view.html.php we need to inherit from JViewCategory (which in the revised namespacing scheme is CategoryView in namespace Joomla\CMS\MVC\View) and call the addFeed() method of this class. This method inserts the RSS/Atom links into the document <head> – which is where the Syndicated Feed module expects to find the URL for putting behind the RSS symbol.
  4. The URL for the RSS feed includes the query parameter "format=feed" so we need to have a file view.feed.php and the code for this new file is found below. Note that it inherits from the class JViewCategoryfeed, or in the newer namespaced structure CategoryFeedView within the namespace Joomla\CMS\MVC\View.
  5. Include in the SQL query within the helloworld category model all the fields which you want to populate within the RSS/Atom feed XML document.

The URL of the RSS feed will be something like: http://yourDomain.com/yourJoomlaInstance/index.php?option=com_helloworld&view=category&id=37&Itemid=822&lang=en&format=feed&type=rss When Joomla receives a URL like this, it handles it in the same way as usual:

  • the option is "com_helloworld", so it will run our helloworld.php file
  • it will run the display() method within the helloworld controller – this will as usual set up the view and the model
  • because the URL parameter format = "feed" it will expect the view to be in ./views/category/view.feed.html and will run the HelloworldViewCategory::display() method.
  • this display() code is found from the parent class JViewCategoryfeed / CategoryFeedView. This is the code which brings together the data to be put into the response XML document – for example, the titles, descriptions, links – mapping them from the fields in the SQL query result, and I would recommend looking through the code to get an idea of what it does.
    • it calls $this->get('Items'), which gets translated into a call getItems() in the model – so we need to ensure that our SQL query in this function provides all the fields we want to be present in the RSS XML response.
    • it calls $this->get('Category'), so we need to have a method getCategory() in our model
    • it maps some of the fields using the ucm content-types field mapping data which we supplied in the step Adding Tags. To find the correct record in this table it uses the key formed by the extension ("com_helloworld") and the view ("helloworld"), so this is why we need to set the $viewname property in this class.
    • it allows us to define mappings of other fields through the method reconcileNames(). We use this to include in the description field a link to the associated image.

Configuration changes

Following standard Joomla practice, we put the Show Feed Link option within the integration tab of the Helloworld configuration options.

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>
		<field
			name="save_history"
			type="radio"
			class="btn-group btn-group-yesno"
			default="1"
			label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
			description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
		>
			<option
				value="0">JNO</option>
			<option
				value="1">JYES</option>
		</field>
		<field
			name="history_limit"
			type="text"
			filter="integer"
			label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
			description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
			default="5"
		>
		</field>
	</fieldset>
	<fieldset name="integration"
		label="JGLOBAL_INTEGRATION_LABEL"
		description="COM_HELLOWORLD_CONFIG_INTEGRATION_SETTINGS_DESC"
	>
		<field
			name="show_feed_link"
			type="radio"
			class="btn-group btn-group-yesno"
			default="1"
			label="JGLOBAL_SHOW_FEED_LINK_LABEL"
			description="JGLOBAL_SHOW_FEED_LINK_DESC">
			<option value="1">JSHOW</option>
			<option value="0">JHIDE</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>

Category View code files

In our updated category view html file we change the class we're inheriting from and include a call to the parent addFeed() method. This method expects the params to have been set.

site/views/category/view.html.php

<?php
/*
 * View file for the view which displays a list of helloworld messages in a given category
 */
 
defined('_JEXEC') or die;

class HelloworldViewCategory extends JViewCategory
{
	public function display($tpl = null)
	{
		$this->categoryName = $this->get("CategoryName");

		$this->items = $this->get('Items');
		$this->pagination = $this->get('Pagination');
		$this->state = $this->get('State');
		$this->filterForm    	= $this->get('FilterForm');
		$this->activeFilters 	= $this->get('ActiveFilters');

		$this->subcategories = $this->get('Subcategories');

		$this->params = JFactory::getApplication()->getParams();

		parent::display($tpl);
	}

	protected function prepareDocument()
	{
		parent::prepareDocument();
		parent::addFeed();
	}
}

We also have the new view file for the feed format.

site/views/category/view.feed.php

<?php
/**
 * view file associated with the Syndicated Feed for a helloworld category
 */

defined('_JEXEC') or die;

class HelloworldViewCategory extends JViewCategoryfeed
{
	// required so that the parent class can find the helloworld content-type record containing the field mapping details
	protected $viewName = 'helloworld';

	/**
	 * Function overriding the parent reconcileNames() method. 
	 * We use this to insert an html link to the helloworld image into the description
	 * 
	 * The input parameter is the helloworld item as extracted from the database, passed by reference
	 *
	 * The result of the method is that the helloworld item passed as a parameter gets its description property changed
	 */
	protected function reconcileNames($item)
	{ 
		$description = '';
		
		if (!empty($item->image))
		{
			// Convert the JSON-encoded image info into an array
			$imageDetails = new JRegistry;
			$imageDetails->loadString($item->image, 'JSON');
			$src = $imageDetails->get('image','');
			if (!empty($src))
			{
				$description .= '<p><img src="' . $src . '" /></p>';
			}
		}
		$item->description =  $description . $item->description;
	}
}

修改 model

site/models/category.php

<?php
/**
 * Model for displaying the helloworld messages in a given category
 */

defined('_JEXEC') or die;

class HelloworldModelCategory extends JModelList
{
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id',
				'greeting',
				'alias',
				'lft',
			);
		}

		parent::__construct($config);
	}
    
	protected function populateState($ordering = null, $direction = null)
	{
		parent::populateState($ordering, $direction);
        
		$app = JFactory::getApplication('site');
		$catid = $app->input->getInt('id');

		$this->setState('category.id', $catid);
	}
    
	protected function getListQuery()
	{
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true);

		$catid = $this->getState('category.id'); 
		$query->select('id, greeting, alias, catid, access, description, image')
			->from($db->quoteName('#__helloworld'))
			->where('catid = ' . $catid);

		if (JLanguageMultilang::isEnabled())
		{
			$lang = JFactory::getLanguage()->getTag();
			$query->where('language IN ("*","' . $lang . '")');
		}

		$orderCol	= $this->state->get('list.ordering', 'lft');
		$orderDirn 	= $this->state->get('list.direction', 'asc');

		$query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));

		return $query;	
	}

	public function getCategoryName()
	{
		$catid = $this->getState('category.id'); 
		$categories = JCategories::getInstance('Helloworld', array('access' => false));
		$categoryNode = $categories->get($catid);   
		return $categoryNode->title; 
	}
    
	public function getSubcategories()
	{
		$catid = $this->getState('category.id'); 
		$categories = JCategories::getInstance('Helloworld', array('access' => false));
		$categoryNode = $categories->get($catid);
		$subcats = $categoryNode->getChildren(); 
        
		$lang = JFactory::getLanguage()->getTag();
		if (JLanguageMultilang::isEnabled() && $lang)
		{
			$query_lang = "&lang={$lang}";
		}
		else
		{
			$query_lang = '';
		}
        
		foreach ($subcats as $subcat)
		{
			$subcat->url = JRoute::_("index.php?view=category&id=" . $subcat->id . $query_lang);
		}
		return $subcats;
	}

	public function getCategoryAccess()
	{
		$catid = $this->getState('category.id'); 
		$categories = JCategories::getInstance('Helloworld', array('access' => false));
		$categoryNode = $categories->get($catid);   
		return $categoryNode->access; 
	}
	
	public function getItems()
	{
		$items = parent::getItems();
		$user = JFactory::getUser();
		$loggedIn = $user->get('guest') != 1;

		if ($user->authorise('core.admin')) // ie superuser
		{
			return $items;
		}
		else
		{
			$userAccessLevels = $user->getAuthorisedViewLevels();
			$catAccess = $this->getCategoryAccess();
			
			if (!in_array($catAccess, $userAccessLevels))
			{  // the user hasn't access to the category
				if ($loggedIn)
				{	
					return array();
				}
				else
				{
					foreach ($items as $item)
					{
						$item->canAccess = false;
					}
					return $items;
				}
			}

			foreach ($items as $item) 
			{
				if (!in_array($item->access, $userAccessLevels))
				{
					if ($loggedIn)
					{
						unset($item);
					}
					else
					{
						$item->canAccess = false;
					}
				}
			}
		}
		return $items;
	}

	public function getCategory()
	{
		$categories = JCategories::getInstance('Helloworld', array());
		$category = $categories->get($this->getState('category.id', 'root'));
		return $category;
	}
}

更新語言字串

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_LANGUAGE="Language"
COM_HELLOWORLD_CREATED_DATE="Created"
COM_HELLOWORLD_PUBLISHED="Published"
COM_HELLOWORLD_HELLOWORLDS_NAME="Name"
COM_HELLOWORLD_HELLOWORLDS_POSITION="Position"
COM_HELLOWORLD_HELLOWORLDS_IMAGE="Image"
COM_HELLOWORLD_HELLOWORLDS_ASSOCIATIONS="Associations"
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_DESCRIPTION_DESC="Message description"
COM_HELLOWORLD_HELLOWORLD_FIELD_DESCRIPTION_LABEL="Description"
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_FIELD_LATITUDE_LABEL="Latitude"
COM_HELLOWORLD_HELLOWORLD_FIELD_LATITUDE_DESC="Enter the position latitude, between -90 and +90 degrees"
COM_HELLOWORLD_HELLOWORLD_FIELD_LONGITUDE_LABEL="Longitude"
COM_HELLOWORLD_HELLOWORLD_FIELD_LONGITUDE_DESC="Enter the position longitude, between -180 and +180 degrees"
COM_HELLOWORLD_HELLOWORLD_FIELD_PARENT_LABEL="Parent"
COM_HELLOWORLD_HELLOWORLD_FIELD_PARENT_DESC="Select the parent record"
COM_HELLOWORLD_ITEM_FIELD_ORDERING_VALUE_FIRST="-- First record"
COM_HELLOWORLD_ITEM_FIELD_ORDERING_VALUE_LAST="-- Last record"
COM_HELLOWORLD_ITEM_FIELD_ORDERING_TEXT="Ordering will be available after saving."
COM_HELLOWORLD_HELLOWORLD_FIELD_LANGUAGE_DESC="Select the appropriate language"
COM_HELLOWORLD_IMAGE_FIELDS="Image details"
COM_HELLOWORLD_HELLOWORLD_FIELD_IMAGE_LABEL="Select image"
COM_HELLOWORLD_HELLOWORLD_FIELD_IMAGE_DESC="Select an image from the library, or upload a new one"
COM_HELLOWORLD_HELLOWORLD_FIELD_ALT_LABEL="Alt text"
COM_HELLOWORLD_HELLOWORLD_FIELD_ALT_DESC="Alternative text (if image cannot be displayed)"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTION_LABEL="Caption"
COM_HELLOWORLD_HELLOWORLD_FIELD_CAPTION_DESC="Provide a caption for the image"
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_CONFIG_INTEGRATION_SETTINGS_DESC="Settings relating to integration with the Syndicated Feed module"
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_ASSOCIATIONS="Associations"
COM_HELLOWORLD_TAB_PERMISSIONS="Permissions"
COM_HELLOWORLD_TAB_IMAGE="Image"
COM_HELLOWORLD_LEGEND_DETAILS="Message Details"
COM_HELLOWORLD_LEGEND_PARAMS="Message Parameters"
COM_HELLOWORLD_LEGEND_ASSOCIATIONS="Message Associations"
COM_HELLOWORLD_LEGEND_PERMISSIONS="Message Permissions"
COM_HELLOWORLD_LEGEND_IMAGE="Image info"
; Column ordering in the Helloworlds view
COM_HELLOWORLD_ORDERING_ASC="Ordering ascending"
COM_HELLOWORLD_ORDERING_DESC="Ordering descending"
COM_HELLOWORLD_GREETING_ASC="Greeting ascending"
COM_HELLOWORLD_GREETING_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"
COM_HELLOWORLD_LANGUAGE_ASC="Language ascending"
COM_HELLOWORLD_LANGUAGE_DESC="Language descending"
COM_HELLOWORLD_ASSOCIATION_ASC="Association ascending"
COM_HELLOWORLD_ASSOCIATION_DESC="Association descending"
COM_HELLOWORLD_ACCESS_ASC="Access ascending"
COM_HELLOWORLD_ACCESS_DESC="Access descending"
; Helloworld menuitem - selecting a greeting via modal
COM_HELLOWORLD_MENUITEM_SELECT_MODAL_TITLE="Select greeting"
COM_HELLOWORLD_MENUITEM_SELECT_HELLOWORLD="Select"
COM_HELLOWORLD_MENUITEM_SELECT_BUTTON_TOOLTIP="Select a helloworld greeting"
; Checking in records
COM_HELLOWORLD_N_ITEMS_CHECKED_IN_0="No records checked in."
COM_HELLOWORLD_N_ITEMS_CHECKED_IN_1="%d record successfully checked in."
COM_HELLOWORLD_N_ITEMS_CHECKED_IN_MORE="%d records successfully checked in."
; Batch functionality
COM_HELLOWORLD_BATCH_OPTIONS="Helloworld component batch options"
COM_HELLOWORLD_BATCH_SETPOSITION_LABEL="Set location"
COM_HELLOWORLD_BATCH_KEEP_POSITION="Keep existing location"
COM_HELLOWORLD_BATCH_CHANGE_POSITION="Change location"

包裝元件

Contents of your code directory. Each file link below takes you to the step in the tutorial which has the latest version of that source code file.

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.32</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>
		<filename>router.php</filename>
		<folder>controllers</folder>
		<folder>views</folder>
		<folder>models</folder>
		<folder>helpers</folder>
	</files>

		<languages folder="site/language">
			<language tag="en-GB">en-GB/en-GB.com_helloworld.ini</language>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language>
		</languages>

	<media destination="com_helloworld" folder="media">
		<filename>index.html</filename>
		<folder>images</folder>
		<folder>js</folder>
		<folder>css</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>
			<!-- layout files section -->
			<folder>layouts</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>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.ini</language>
			<language tag="fr-FR">fr-FR/fr-FR.com_helloworld.sys.ini</language>
		</languages>
	</administration>

</extension>

貢獻者