Actions

J3.x

Difference between revisions of "Using Tags in an Extension"

From Joomla! Documentation

m (type_alias)
m (Notes)
Line 108: Line 108:
 
=====Notes=====
 
=====Notes=====
  
* The table name for the common table is <tt>#__ucm_content</tt>; this is INCORRECT in 3.1 and 3.1.1 data but is not currently used. The data was updated in 3.1.4.
+
* The table name for the common table is <tt>#__ucm_content</tt>; this is incorrect in 3.1 and 3.1.1 data but is not currently used. The data was updated in 3.1.4.
  
* The <tt>type_title</tt> field would potentially be used for display although this is not implemented currently except in the contenttype field.  Usually it should begin with an upper case letter if it is in English. See note about how to make this translatable. To make your type names translatable add <tt>COM_TAGS_CONTENT_TYPE_+type_title="Type Title"</tt> in both the ini and sys.ini files.  
+
* The <tt>type_title</tt> field would potentially be used for display although this is not implemented currently except in the contenttype field.  Usually it should begin with an upper case letter if it is in English. See note about how to make this translatable. To make your type names translatable add <tt>COM_TAGS_CONTENT_TYPE_+type_title="Type Title"</tt> in both the ini and sys.ini files.
  
 
====<tt>rules</tt>====
 
====<tt>rules</tt>====

Revision as of 10:34, 26 April 2014

Copyedit.png
This Page Needs Copy Editing

This article has been tagged and requires copy editing for grammar, style, cohesion, tone, or spelling. Please help maintain and improve our documentation by editing it.


Contents

Introduction

Joomla's tagging system is used in all core content extensions and is designed to be be easy to integrate into other extensions that use standard Joomla design patterns.

Using tags in an extension is fairly straightforward. It requires these changes to a typical extension:

  • Register a 'Content type' for the extension view(s)
  • Add 'Observer methods' to the extension table class(es)
  • Add 'Tag fields' to the extension edit forms
  • Add 'Tag display' code to the extension view files
  • Optionally, add a batch tagging method to the extension administration

Register a content type for each view

In Joomla! 3 content types e.g. articles, weblinks, contacts, . . . are registered in the #__content_types table with a separate record for each content view e.g. article, weblink, article category, weblink category, . . .

Your extension installer needs to create a new record for each view.

You can create records in the installer in three different ways:

  • in the postflight method
  • by creating a JTableContenttype instance and adding a row, or
  • by using SQL to create a record directly

The structure of the #__content_types table is fairly straightforward:

Column name Column type Purpose
type_id int(10) Record key
type_title varchar(255) Type title e.g. Article
type_alias varchar(255) Type alias e.g. com_content.article
table varchar(255) Information about the Table class
rules text Not currently used
field_mappings text Maps the table column names to standard Joomla! names
router varchar(255) Optional: name of a router method

Construct the Content Type entry

For each table/option/view you will need to make an entry in #__content_types table (see above).

type_id

This is the auto-incremented record key, nothing to be done here.

type_title

The title for your Content Type e.g. Article, Contact, Weblink, You can do this either using sql or postflight by creating an instance of JTableContenttype. Don't forget a category type if you use the Joomla categories API.

type_alias

A string identifying the component and view (that would be in the page request, typically matching the model name) e.g. com_contact.contact, com_weblinks.weblink.

table

You need to identify which tables used by your component contain records to be tagged. For example the 'Contact' view of the Contacts component uses #__contact_details and similarly the 'Weblinks' view of the Weblinks component uses #__weblinks .

Each of these components uses a class to write to the table: ContactTableContact for the Contacts component and WeblinksTableWeblink for the Weblinks component. You will need the class prefixes e.g. ContactTable, WeblinksTable.

Note that Category types all use the #__categories table.

The type_table entry gives the complete table class information for the table class as a JSON object with two elements. The first element represents your "special" table and the second an optional common table (otherwise it will default the JTableCorecontent).

Here is the JSON entry for the Weblink content type:

{
  "special": {
    "dbtable": "#__weblinks",
    "key": "id",
    "type": "Weblink",
    "prefix": "WeblinksTable",
    "config": "array()"
  },
  "common": {
    "dbtable": "#__ucm_content",
    "key": "ucm_id",
    "type": "Corecontent",
    "prefix": "JTable",
    "config": "array()"
  }
}

The values to be included are:

Entry name Content
dbtable Table name
key Primary key name
type Content type
prefix Class prefix
config An option array, as used in your component constructor and getInstance() methods, may be empty

This information enables the tagging system (and other APIs) to access your table easily.

If you are using Joomla categories make sure to create a category type so that they can be tagged. In Joomla 3.1 and 3.1.1 there is an error where the tag field will show even if there is not a type, but this is corrected in 3.1.4.

Notes
  • The table name for the common table is #__ucm_content; this is incorrect in 3.1 and 3.1.1 data but is not currently used. The data was updated in 3.1.4.
  • The type_title field would potentially be used for display although this is not implemented currently except in the contenttype field. Usually it should begin with an upper case letter if it is in English. See note about how to make this translatable. To make your type names translatable add COM_TAGS_CONTENT_TYPE_+type_title="Type Title" in both the ini and sys.ini files.

rules

Rules is currently not used. It will likely be removed in favor of an asset_id for each type, but currently you can ignore this field which will be managed by JTable.

field_mappings

This entry maps the names of specific fields in your table to a set of standard names. This mapping is stored as a JSON array with the first element mapping to the common fields and the second one mapping the other fields from the table.

Important note The JHelperTags and JUcm APIS at 3.1.1 supported arrays for this field, but as of 3.1.4 either arrays or objects with a default of objects are supported.

'{"common":[{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}], "special": [{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}]}'

is the field mapping for the Article type. Note that article uses the name attribs for the core field called params. If your table does not contain a field, put “null” instead. Leaving it blank may cause SQL issues. The special fields are optional. At a minimum for common fields you need to map: content_item_id, alias and title in order to successfully create urls in the tagged items list. You also will probably want: access, status, and language.

router

Router is an optional entry to include the name of a static helper router method for this type found in its front end helpers folder.

If you only store data in #__ucm_content you will eventually be able to leave the router field blank although this option is not currently implemented. If you do not have a custom router tags falls back to the rules found in JHelperRoute.

Modify your component's table class (or classes if you have multiple tables)

Add the following to your JTable constructor:

$this->_observers = new JObserverUpdater($this); JObserverMapper::attachAllObservers($this);

The addition material formerly located here is no longer needed after 3.1.4 Please read the document history for this page if you are required to support 3.1.0 or 3.1.1.

For joomla 3.2 I needed this line: ( Dont forget to replace weblinks by your component name )

JObserverMapper::addObserverClassToClass('JTableObserverTags', 'WeblinksTableWeblink', array('typeAlias' => 'com_weblinks.weblink'));

Add tags to the getItem() method of the model

Note: this was only required in 3.1.0 and 3.1.1. It should not be used in 3.1.4 or later. Please read the history of this page if you need instructions for older versions.


Add a tag field to edit screens

In any edit layouts where you want to allow tagging, you need to add the field to the xml and the appropriate layouts if necessary. The core layouts us a JLayout to manage this and the same layout by any extension.

Update: Note that in 3.1.1 only there is special handling of this in the core. Tags in the edit screen MUST be part of a metadata <fields></fields> group. The core provides two JLayouts to help you manage standard layouts, one (details) for the metadata and one for the sidebar that includes the tabs. In update an extension to 3.1.4 you may need to fix adjust your edit views.

In 3.1.4 or later this special handling is not necessary. Best practice is to use the standard JLayouts since this provides a consistent experience for users.

                <field name="tags" type="tag"
                        label="JTAG" description="JTAG_DESC"
                        class="inputbox span12 small" multiple="true"
                >
                </field>

The field loads all the Javascript libraries required. You don't need to worry about that.

The field supports two modes:

  • Nested tags mode. Hierarchical tag list. Doesn't support on the fly tag creation.
  • AJAX mode. Tags are searched while user types (3 min. chars required to launch the AJAX search). Custom tags are added by pressing ENTER or COMMA keys. Tags show the global route/path. Example: grandpa/parent/tag

The field mode can be forced or use the com_tags setting Tag field mode to determine its mode. To set/force the field mode we have to add mode="ajax" or mode="nested" to the tag field definition.

Example of forced AJAX mode:


                <field name="tags" type="tag" mode="ajax"
                        label="JTAG" description="JTAG_DESC"
                        class="inputbox span12 small" multiple="true"
                >
                </field>

The field also includes an attribute to allow/deny the user to enter custom values. Currently this only works in AJAX mode. The attribute has to be added to the field definition like **custom="allow"** or **custom="deny"**

Example field definition with custom tags denied:

                <field name="tags" type="tag" mode="ajax" custom="denied"
                        label="JTAG" description="JTAG_DESC"
                        class="inputbox span12 small" multiple="true"
                >
                </field>

if it is not already there. Usually multiple should be true unless you have a specific reason for it not to be. In the core components in administrator, the field is in the group shown on the right, below the language field.

Note: As of 3.1.2 if you wish to use the field to designate parent tags you must add parent="parent" to the xml definition of the field.

Prepare the view

Add an appropriate version of this to your view.html.php file before loading the layout:

$item->tags = new JHelperTags;
$item->tags->getItemTags('com_newsfeeds.newsfeed.' , $this->item->id);

The first parameter should match a type in the types table. The second parameter is the primary key under which this record is stored in your table. This would be used in any display in any view where you want the tags associated with the item to display.


Set up the display

In any layout where you want to display the tags associated with an item add:

                <?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
                <?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>

Changing the object and property names as appropriate.

You will most likely want to add the show_tags parameter to the item parameters, the menu item parameters and component configuration as appropriate for your use case.

        <?php if ($this->params->get('show_tags', 1) && !empty($this->item->tags)) : ?>
                <?php $this->item->tagLayout = new JLayoutFile('joomla.content.tags'); ?>
                <?php echo $this->item->tagLayout->render($this->item->tags->itemTags); ?>
        <?php endif; ?>

Batch processing

If you want to add the ability to do batch tagging to a backend list view do the following.

Add tag to the default_batch layout


        <div class="control-group">
                        <div class="controls">
                                <?php echo JHtml::_('batch.tag');?>
                        </div>
                </div>

And add tag to the button class in the modal footer (Not totally necessary at this point, but good for potential future changes e.g. if unTag is added.)

<button class="btn" type="button" onclick="document.id('batch-category-id').value='';document.id('batch-access').value='';document.id('batch-language-id').value='';document.id('batch-user-id').value='';document.id('batch-tag-id)').value=''" data-dismiss="modal">

Add a batch method to your model if you are not extending JModelAdmin or overriding the batch method.

        /**
         * Batch tag a list of item.
         *
         * @param   integer  $value     The value of the new tag.
         * @param   array    $pks       An array of row IDs.
         * @param   array    $contexts  An array of item contexts.
         *
         * @return  void.
         *
         * @since   3.1
         */
        protected function batchTag($value, $pks, $contexts)
        {
                $tagsHelper = new JHelperTags();
                $tagsHelper->tagItems($value, $pks, $contexts);
 
                return true;
        }

And modify your batch method by adding

                if (!empty($commands['tag']))
                {
                        if (!$this->batchTag($commands['tag'], $pks, $contexts))
                        {
                                return false;
                        }
 
                        $done = true;
                }

Pay attention to any JSON encoded strings that you need special handling for in batch processing -- remember that you are saving a copy of the core fields and you need save to work as expected.


That’s it, now create some tags, tag some items and you are set.