Display Joomla plugin fields data in template | first K2 extension - php

I have a problem and I'm new to Joomla and K2, so any help will be highly appreciated.
I'm developing a simple joomla plugin based on Example K2 Plugin (http://getk2.org/extend/extensions/90-example-k2-plugin-for-developers).
What i'm trying to create is a K2 extension for Categories, so i'll be able to add extra content to categories. I already did a search and there is not plugin or extension to cover my needs for this project with Joomal 3.x.
For each category I set information in the backend as currency, language, country , etc. I added this fields to the backend via the xml file.
I have tried several ways, but I haven't been able to access this information on my k2 template. When i dump parameters I get the default value from the xml, but not the one already saved for the category.
So i'm being able to easily display the content with a plugin template but by defect the only function available for categories will be onK2CategoryDisplay, but what i'm trying to achieve here is to call the fields values from the K2 template, next to the title for example, or below a gallery.
I found this lines, but it only displays the default text saved on the xml file, and not the new content. If i'm not being clear, please let me know and i'll update this post. Thanks in advance.
$plugin = JPluginHelper::getPlugin('k2', 'categories');
$pluginParams = new JRegistry();
$pluginParams->loadString($plugin->params);
$param = $pluginParams->get('localCountry_cat');
var_dump($param);
Here is the categories.xml:
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="k2" method="upgrade">
<name>Categories K2 Plugin</name>
<files>
<filename plugin="categories">categories.php</filename>
<folder>categories</folder>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field name="localCountry_cat" type="text" size="80" default="test" label="Country local name" description="" />
<field name="capital_cat" type="text" size="80" default="test" label="Capital" description="" />
<field name="languages_cat" type="text" size="80" default="test" label="Official Languages" description="" />
</fieldset>
</fields>
</config>
<!-- K2 backend field parameters -->
<fields group="category">
<field name="localCountry_cat" type="text" size="80" default="" label="Country local name" description="" />
<field name="capital_cat" type="text" size="80" default="" label="Capital" description="" />
<field name="languages_cat" type="text" size="80" default="" label="Official Languages" description="" />
</fields>
Here is the categories.php
// no direct access
defined('_JEXEC') or die('Restricted access');
// Load the K2 plugin API
JLoader::register('K2Plugin', JPATH_ADMINISTRATOR.DS.'components'.DS.'com_k2'.DS.'lib'.DS.'k2plugin.php');
class plgK2categories extends K2Plugin {
// Required global reference parameters
var $pluginName = 'categories';
var $pluginNameHumanReadable = 'Categories K2 Plugin';
var $plgCopyrightsStart = " "
var $plgCopyrightsEnd = " ";
function plgK2categories( & $subject, $params) {
parent::__construct($subject, $params);
}
function onK2CategoryDisplay( & $category, & $params, $limitstart) {
// API
$mainframe = JFactory::getApplication();
$document = JFactory::getDocument();
// ---------- Get plugin parameters ---------------
// Global plugin params
$plugin = JPluginHelper::getPlugin('k2', $this->pluginName);
$pluginGlobalParams = new JRegistry( $plugin->params );
// K2 Category plugin specific params
$pluginParams = new K2Parameter($category->plugins, '', $this->pluginName);
$local = $pluginParams->get('localCountry_cat');
$capital = $pluginParams->get('capital_cat');
$languages = $pluginParams->get('languages_cat');
$currency = $pluginParams->get('currency_cat');
// --------- Requirements -------
require_once(dirname(__FILE__).DS.$this->pluginName.DS.'includes'.DS.'helper.php');
// ---------- Fetch the template -------
ob_start();
$getTemplatePath = categoriesHelper::getTemplatePath($this->pluginName,'default.php');
$getTemplatePath = $getTemplatePath->file;
include($getTemplatePath);
$getTemplate = $this->plgCopyrightsStart.ob_get_contents().$this->plgCopyrightsEnd;
ob_end_clean();
// ----- Output -----
return $getTemplate;
}
} // END CLASS

I already solved it. It was easier than I thought, but took me a while to discover it. The lack of documentation for K2 and it's developers is a huge pain.
Retrieved from the database the information with $this->params->get('itemK2Plugins'), but also with: $this->category->plugins
<?php if($this->params->get('itemK2Plugins')): ?>
<?php
$array = json_decode($this->category->plugins, true);
foreach($array as $key => $value) {
$keys[$key] = $value;
}
$countryL = $keys['categorieslocalCountry_cat'];
$MottoL = $keys['categorieslocalMotto_cat'];
?>
<?php endif; ?>
If there is a different and correct way to do it, please let me know!
Thanks :)

Related

Sulu CMF - Pass parameter to autocomplete field in FormOverlayList add form

This question is a followup.
I have two entities DataSet and DataGroup.
class DataSet {
string $name;
Collection $groups; // Collection<int, DataGroup>
}
class DataGroup {
string $name;
DataSet $dataSet;
?DataGroup $nextGroup; // Condition: $nextGroup !== $this && $nextGroup->dataSet === $this->dataSet
}
The property DataGroup::nextGroup may refer to any other DataGroup entity associated with the same DataSet.
I want to create a CRUD form where I can add, edit and remove DataSet entities. In this DataSet form, I also want to include a tab where I can CRUD DataGroup entities associated with the current DataSet.
I have created list metadata data_sets.xml and data_groups.xml, as well as form metadata data_set.xml and data_group.xml.
<!-- lists/data_sets.xml -->
<list xmlns="http://schemas.sulu.io/list-builder/list">
<key>data_sets</key>
<properties>
<property name="name" visibility="always" searchability="yes">
<field-name>name</field-name>
<entity-name>App\Entity\DataSet</entity-name>
</property>
</properties>
</list>
<!-- lists/data_groups.xml -->
<list xmlns="http://schemas.sulu.io/list-builder/list">
<key>data_groups</key>
<properties>
<property name="name" visibility="always" searchability="yes">
<field-name>name</field-name>
<entity-name>App\Entity\DataSet</entity-name>
</property>
<property name="dataSet" visibility="always">
<field-name>name</field-name>
<entity-name>App\Entity\DataSet</entity-name>
<joins>
<join>
<entity-name>App\Entity\DataSet</entity-name>
<field-name>App\Entity\DataGroup.dataSet</field-name>
</join>
</joins>
</property>
</properties>
</list>
<!-- forms/data_set.xml -->
<form xmlns="http://schemas.sulu.io/template/template"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sulu.io/template/template
http://schemas.sulu.io/template/form-1.0.xsd"
>
<key>data_set</key>
<properties>
<property name="name" type="text_line" mandatory="true">
<params>
<param name="headline" value="true"/>
</params>
</property>
</properties>
</form>
<!-- forms/data_group.xml -->
<form xmlns="http://schemas.sulu.io/template/template"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.sulu.io/template/template
http://schemas.sulu.io/template/form-1.0.xsd"
>
<key>data_group</key>
<properties>
<property name="name" type="text_line" mandatory="true">
<params>
<param name="headline" value="true"/>
</params>
</property>
<property name="nextGroup" type="single_data_group_selection">
<params>
<param name="type" value="auto_complete"/>
<param name="resource_store_properties_to_request" type="collection">
<param name="dataSetId" value="id"/>
</param>
</params>
</property>
</properties>
</form>
I have also configured sulu_admin.yaml for REST routes and the custom single selection:
sulu_admin:
resources:
data_sets:
routes:
list: app.get_data_sets
detail: app.get_data_set
data_groups:
routes:
list: app.get_data_groups
details: app.get_data_group
field_type_options:
single_selection:
single_data_group_selection:
default_type: 'auto_complete'
resource_key: 'data_groups'
types:
auto_complete:
display_property: 'name'
search_properties:
- 'name'
I implemented two REST controllers for both entities. DataSetController is built as of the Docs, while DataGroupController has a small extension for the list route:
class DataGroupController implements ClassResourceInterface
{
public function cgetAction(int $dataSetId, Request $request): Response
{
// ... Init field descriptors and execute listBuilder
$list = new ListRepresentation(
$listResponse,
'data_groups',
\array_merge(['dataSetId' => $dataSetId], $request->query->all()), // add DataSet ID
$listBuilder->getCurrentPage(),
$listBuilder->getLimit(),
$listBuilder->count()
);
// ... handle view
}
// ...
}
Finally, I implemented a custom Admin class like explained in the Docs.
class DataAdmin extends Admin
{
public const DATA_SET_DETAILS = 'data_set_details';
public const DATA_SET_GROUPS = 'data_set_groups';
public const DATA_SET_LIST = 'app.data_sets_list';
public const DATA_SET_ADD_FORM = 'app.data_set_add_form';
public const DATA_SET_ADD_FORM_DETAILS = 'app.data_set_add_form.details';
public const DATA_SET_EDIT_FORM = 'app.data_set_edit_form';
public const DATA_SET_EDIT_FORM_DETAILS = 'app.data_set_edit_form.details';
public const DATA_SET_EDIT_FORM_GROUPS = 'app.data_set_edit_form.groups';
public function configureViews(ViewCollection $viewCollection): void
{
// Add DataSet list view
// Add DataSet add form view
// Add DataSet edit form view (details)
/*
* Custom second DataSet edit form tab for DataGroup CRUDding
*/
$groupsFormOverlayList = $this->viewBuilderFactory
->createFormOverlayListViewBuilder(self::DATA_SET_EDIT_FORM_GROUPS, '/groups')
->setResourceKey(self::DATA_SET_GROUPS)
->setListKey(self::DATA_SET_GROUPS)
->addListAdapters(['table'])
->addRouterAttributesToListRequest(['id' => 'dataSetId'])
->setFormKey(self::DATA_SET_GROUPS)
->addRouterAttributesToFormRequest(['id' => 'dataSetId'])
->setTabTitle('app.data_groups')
->addToolbarActions([
new ToolbarAction('sulu_admin.add'),
new ToolbarAction('sulu_admin.delete')
])
;
$viewCollection->add($groupsFormOverlayList->setParent(self::DATA_SET_EDIT_FORM));
}
}
As of now
I can perform all CRUD operations on DataSet entities.
I can list and remove DataGroup entities belonging to a DataSet.
When trying to add a new DataGroup, I can't perform autocomplete search for nextGroup because the dataSetId parameter is not passed to the field, forbidding the ResourceRequester to perform the REST request.
How do I pass dataSetId to fields of the "New DataGroup" form in order to search for matching entities only?
Thanks a lot for the detailed description! Unfortunately, I am afraid that it is not possible to implement what you are trying to do while using the built-in autocomplete component at the moment.
The resource_store_properties_to_request param reads the values from the data of the form that renders the autocomplete component. If you are creating a new DataGroup entity, the data of the form is empty (because there is now existing data for a new entity) and therefore the resource_store_properties_to_request param is not able to read a dataSetId value.
I am sorry to say, but I think you would need to implement a custom autocomplete field-type that reads the dataSetId value from the current url to achieve the desired functionality. If you are interested in doing this, I would recommend to have a look at the basic field-type example in the sulu-demo repository.

How to get parameters from article's custom field?

I have some custom field for artciles. For example this is text field named "MyText".
I tryin' to write simple plugin, wich will be display text from this field on article's page (frontend). So how can I get value from this field and transfer it to plugin?
Joomla version is 2.5
Thanks in advance for everybody.
This is field in XML:
<field name="MyText" type="inputbox"
label="MyText"
description=""
class="inputbox" size="25"
/>
Ok! Finally I wrote it by myself. So here is solution:
public function onContentAfterDisplay($context, &$row, &$params, $page = 0)
{
$articleId = (JRequest::getVar('option')==='com_content' && JRequest::getVar('view')==='article')? JRequest::getInt('id') : 0;
$article =& JTable::getInstance('content');
$article->load($articleId);
$art_attribs = new JParameter($article->attribs);
$mytext = $art_attribs->get('MyText');
echo $mytext;
}

Joomla item level ACL issue - Permissions not working correctly

I have followed the Joomla Docs tutorial on how to add ACL to my custom component.
While I had success to add the component wide permission management I am struggeling to get the item level ACL to work.
I am trying to implement an ACL for the table books. I have added an asset_id column there as described in the tutorial.
I added a file book.xml in admin/models/forms/ - this is the content:
<?xml version="1.0" encoding="utf-8"?>
<form>
<field name="asset_id" type="hidden" filter="unset" />
<field name="rules"
type="rules"
label="JFIELD_RULES_LABEL"
translate_label="false"
filter="rules"
validate="rules"
class="inputbox"
component="com_mytest"
section="book"
/>
</form>
This is how my access.xml looks like:
<?xml version="1.0" encoding="utf-8" ?>
<access component="com_mytest">
<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.edit" title="JACTION_EDIT_BOOK" description="COM_MYTEST_ACCESS_EDIT_BOOK_DESC" />
<action name="core.delete" title="JACTION_DELETE_BOOK" description="COM_MYTEST_ACCESS_DELETE_BOOK_DESC" />
</section>
<section name="book">
<action name="core.edit" title="JACTION_EDIT_BOOK" description="COM_MYTEST_ACCESS_EDIT_BOOK_DESC" />
<action name="core.delete" title="JACTION_DELETE_BOOK" description="COM_MYTEST_ACCESS_DELETE_BOOK_DESC" />
</section>
</access>
In my JTable variant in admin/tables/mytest_books.php I have added this methods:
public function bind($array, $ignore = '')
{
if (isset($array['jform']) && isset($array['jform']['rules']) && is_array($array['jform']['rules']))
{
$rules = new JAccessRules($array['jform']['rules']);
$this->setRules($rules);
}
return parent::bind($array, $ignore);
}
protected function _getAssetName()
{
return 'com_mytest.book.'.(int) $this->id;
}
protected function _getAssetTitle()
{
return $this->name;
}
protected function _getAssetParentId()
{
$asset = JTable::getInstance('Asset');
$asset->loadByName('com_mytest');
return $asset->id;
}
As you might notice in the bind() method above I have to extract the rules array from with in the jform array. In all tutorials I saw they simply reference $array['rules'] and not $array['jform']['rules'].
Maybe this is my issue?
This is my book model admin/models/book.php:
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm('com_mytest.book', 'book', array('control' => 'jform', 'load_data' => $loadData));
if (empty($form)){
return false;
}
return $form;
}
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_mytest.edit.book.data', array());
if (empty($data))
{
$data = $this->getItem($this->_id);
}
return $data;
}
Here is what I added at the bottom in the book editing screen admin/views/book/tmpl/default.php:
<?php echo JHtml::_('sliders.start', 'permissions-sliders-'.$this->row->id, array('useCookie'=>1)); ?>
<?php echo JHtml::_('sliders.panel', JText::_('COM_MYTEST_FIELDSET_RULES'), 'access-rules'); ?>
<fieldset class="panelform">
<?php echo $this->form->getLabel('rules'); ?>
<?php echo $this->form->getInput('rules'); ?>
</fieldset>
<?php echo JHtml::_('sliders.end'); ?>
Here is what is working:
When I save a book after editing the book level ACL for a group the settings save correctly. My asset table looks good, showing entries like:
id | name | title | rules
198 | com_mytest.book.2 | The guide to something | {"core.edit":{"1":0,"6":1,"7":1,"2":0,"3":0,"4":1,"5":0,"10":0,"12":0,"8":0},"core.delete":{"1":0,"6":1,"7":0,"2":0,"3":0,"4":0,"5":0,"10":0,"12":0,"8":0}}
And yes, the book with ID 2 has 198 in the asset_id column.
Here is my problem
When I save the book ACL by setting Allowed for all actions for the Administrator user group the dialog shows Conflict beside the permission. Setting everything to Denied does not show this message.
For the Allowed case (and the Conflict-situation):
When I use a second browser to login as an Administrator user group user this condition always returns false (yes, $row->id does contain a valid ID):
$canEdit = JFactory::getUser()->authorise('core.edit',
'com_mytest.book.'.$row->id);
Can you help me solving this puzzle?
Thank you very much!
Are your book assets getting the correct parent id in the asset table?
Any time you use ACL when not using categories you need to be extremely careful about parenting. Usually you want to ensure that the items are getting the component as the parent.
This is something that is a bit messy in the classes, but you can look at com_modules and see how this can work.
A conflict situation exists when a group has a hard deny somewhere between the item and the the start of the branch. Usually that might be denied on a component but allowed for a category of that component, as one example. You can get into a conflict situation if your parenting is not done correctly.

Block not deleted from DB

Situation:
I'm developing a package for Concrete 5 Version 5.6.3.1.
The problem:
When deleting an already published block from the frontend (like any
user does), the corresponding row in the DB-table isn't deleted.
When deleting the block without publishing, it works.
Here's my controller
class PcShooterChShowSomeThingsBlockController extends Concrete5_Controller_Block_Content {
protected $btName = "Show Some Things";
protected $btTable = 'btPcShooterChShowSomeThings';
protected $btInterfaceWidth = 500;
protected $btInterfaceHeight = 400;
protected $btWrapperClass = 'ccm-ui';
//...
public $pkgHandle = 'pc_shooter_ch_show_some_things';
//...
/**
* --------------- Overrides ----------------------
*/
public function delete() {
$db = Loader::db();
//Log::addEntry('DELETE FROM ' . $this->btTable . ' WHERE bID = ' . $this->bID);
$db->Execute('DELETE FROM ' . $this->btTable . ' WHERE bID = ' . $this->bID);
parent::delete();
}
}
The block itself works well, the package too. It isn't My first package at all, also I develop block/packages as recommended by C5.
I start thinking, its a bug, but before I post something on C5, I'm interested to hear from other C5 developers...
In the forum of C5 it says, that overriding the Concrete5_Controller_Block_Content's delete-method helps.
Also I tried to call the parent::delete(); at the beginnig instead of the end, but no difference.
UPDATE
The parents delete method from the Concrete5_Library_BlockController:
/**
* Automatically run when a block is deleted. This removes the special data
* from the block's specific database table. If a block needs to do more
* than this this method should be overridden.
* #return $void
*/
public function delete() {
if ($this->bID > 0) {
if ($this->btTable) {
$ni = new BlockRecord($this->btTable);
$ni->bID = $this->bID;
$ni->Load('bID=' . $this->bID);
$ni->delete();
}
}
}
UPDATE 1
Cache settings print screen
And, maybe it helps, the db.xml
<?xml version="1.0"?>
<schema version="0.3">
<table name="btPcShooterChShowSomeThings">
<field name="bID" type="I">
<key />
<unsigned />
</field>
<field name="desc_true" type="I2">
</field>
<field name="block_css_style" type="C" size="255">
</field>
<field name="block_css_id" type="C" size="255">
</field>
<field name="block_css_class" type="C" size="255">
</field>
<field name="title_css_class" type="C" size="255">
</field>
<field name="desc_css_class" type="C" size="255">
</field>
</table>
</schema>
If you need any further infos or code, just tell me. I'd be glad to get some tips on this.
UPDATE 2
A uninstall/install of the package does not help neither.
UPDATE 3
When deleting an already published block from the frontend (like any
user does), the corresponding row in the DB-table isn't deleted
and no delete() method is firing, neither myne nor the parent's
So finally, I've got an answer from a developer of the C5-team:
Not a bug. Blocks still store their data so that they can be
reinstated in case a previous version of a page gets approved and
rolled back to. Block's will only call BlockController::delete() when
they no longer need to keep their data around.
For other C5 developers:
Go to Dashboard > System & Settings > Automated Jobs (under "Optimization") and run the job:
"Remove Old Page Versions"
The child's (or parent's) delete method is firing.
The block is deleted.
Thx to Andrew Embler from the C5-Team!

Need help with joomla 1.6 module custom basic settings?

I am writing an integration module for our product to go into any Joomla 1.6 page. I need some help with getting custom data (from the API) into the basic settings part but can't seem to find a way to get it.
If you look at the documentation for the creation of a module, the settings for your module you set up in an XML format. That leaves you to hard code any values or selections without any dynamic options whatsoever. Basically what I want to do is setup a very basic module that takes three basic properties:
URL (used to define the path to the API)
API key (The API key)
List selection (Connects to the API and gets list names from your account.)
The list selection would change for every user's API key naturally but because you setup the module with an XML file I see no way around the hard coding of list selection options.
Please tell me if you can build a dynamic <select> with options in a Joomla 1.6 module.
NOTE: I say 1.6 because there is a major difference between 1.5 and 1.6 development in Joomla.
Well after a hell of a struggle and no help here whatsoever I can finally say that I have done it. Here is the process for any googlers in the future:
To build a dynamic dropdown you have to do a bunch of thing right for it to be pulled together by Joomla finally.
Also remember to read the documentation carefully, This answer's methods are not contained in it but maybe someone will wake up and put it there someday.
So after inspection of how the 1.6 architecture puts module variables together using the XML build file here we go.
The XML will look something like this :
<?xml version="1.0" encoding="UTF-8"?>
<extension type="module" version="1.6.0" client="site">
<name>...</name>
<author>...</author>
<creationDate>April 2011</creationDate>
<copyright>Copyright (C) 2011 ... All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>...</authorEmail>
<authorUrl>...</authorUrl>
<version>1.6.0</version>
<description>
...
</description>
<files>
<filename module="mod_your_mod">mod_your_mod.php</filename>
<filename>helper.php</filename>
<filename>index.html</filename>
<folder>tmpl</folder>
<folder>elements</folder>
<folder>lib</folder>
</files>
<languages />
<help />
<config>
<fields name="params">
<fieldset name="basic">
<!-- Custom field, list selection from API -->
<!-- Path to module external parameters -->
<field addfieldpath="/modules/mod_your_mod/elements"
name="mod_your_mod_id_selection" <!-- Name of variable -->
type="lists" <!-- New variable type -->
default=""
label="Select lists"
description="This is the list selection, where you select the list a contact can subscribe to." />
</fieldset>
<fieldset
name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
description="JFIELD_ALT_MODULE_LAYOUT_DESC" />
<field
name="moduleclass_sfx"
type="text"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC" />
<field
name="cache"
type="list"
default="1"
label="COM_MODULES_FIELD_CACHING_LABEL"
description="COM_MODULES_FIELD_CACHING_DESC">
<option
value="1">JGLOBAL_USE_GLOBAL</option>
<option
value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>
<field
name="cache_time"
type="text"
default="900"
label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
description="COM_MODULES_FIELD_CACHE_TIME_DESC" />
<field
name="cachemode"
type="hidden"
default="itemid">
<option value="itemid"></option>
</field>
</fieldset>
</fields>
</config>
</extension>
So after following the Joomla way of implementing a module here and here, I added the new parameter variable type into the elements folder as lists.php, see the name is the same as the type you declared in the XML file.
The class inside of this file looks like this :
<?php
// No direct access
defined('_JEXEC') or die('Direct Access to this location is not allowed.');
jimport('joomla.html.html');
//import the necessary class definition for formfield
jimport('joomla.form.formfield');
// Include API utility file
require_once(dirname(__FILE__) . '/../lib/your_api.php');
class JFormFieldLists extends JFormField
{
/**
* The form field type.
*
* #var string
* #since 1.6
*/
protected $type = 'lists'; //the form field type see the name is the same
/**
* Method to retrieve the lists that resides in your application using the API.
*
* #return array The field option objects.
* #since 1.6
*/
protected function getInput()
{
$options = array();
$attr = '';
$attr .= ' multiple="multiple"';
$attr .= ' style="width:220px;height:220px;"';
// Get the database instance
$db = JFactory::getDbo();
// Build the select query
$query = 'SELECT params FROM jos_modules'
. ' WHERE module="mod_your_mod"';
$db->setQuery($query);
$params = $db->loadObjectList();
// Decode the options to get thje api key and url
$options = json_decode($params[0]->params, true);
// Gracefully catch empty fields
if ( empty($options['api_key']) === true )
{
$tmp = JHtml::_(
'select.option',
0,
'No lists available, please add an API key'
);
$lists[] = $tmp;
// The dropdown output, return empty list if no API key specified
return JHTML::_(
'select.genericlist',
$lists,
$this->name,
trim($attr),
'value',
'text',
$this->value,
$this->id
);
}
if ( empty($options['url']) === true )
{
$tmp = JHtml::_(
'select.option',
0,
'No lists available, please add the enterprise URL'
);
$lists[] = $tmp;
// The dropdown output, return empty list if no API key specified
return JHTML::_(
'select.genericlist',
$lists,
$this->name,
trim($attr),
'value',
'text',
$this->value,
$this->id
);
}
// Create a new API utility class
$api = new APIClass(
$options['url'],
$options['api_key']
);
try
{
// Get the lists needed for subscription
$response = $api->getLists();
}
catch ( Exception $e )
{
$tmp = JHtml::_(
'select.option',
0,
'Could not connect to the API'
);
$lists[] = $tmp;
// The dropdown output, return empty list if no API key specified
return JHTML::_(
'select.genericlist',
$lists,
$this->name,
trim($attr),
'value',
'text',
$this->value,
$this->id
);
}
$lists = array();
// Builds the options for the dropdown
foreach ( $response['data'] as $list )
{
// Build options object here
$tmp = JHtml::_(
'select.option',
$list['list_id'],
$list['list_name']
);
$lists[] = $tmp;
}
// The dropdown output
/* The name of the select box MUST be the same as in the XML file otherwise
* saving your selection using Joomla will NOT work. Also if you want to make it
* multiple selects don't forget the [].
*/
return JHTML::_(
'select.genericlist',
$lists,
'jform[params][mod_your_mod_id_selection][]',
trim($attr),
'value',
'text',
$this->value,
$this->id
);
}
}
?>
So you will know when everything is working because your selection of the drop down list, built by the API(hence completely dynamic), will save into the module database entry with the name of the select box which you can easily retrieve by calling:
$api_key = $params->get('api_key', '');
in your module file. In this case its called mod_your_mod.php.
I really hope that this helps you when defining customized parameters in the back end of your Joomla 1.6 modules. This allows for extreme customizations and integrates tightly with whatever application you like to use's API.
The only downside is that it might be slow, but using a bunch of checks it fails gracefully when the API is down or not pulling data through correctly. All in all a very unpleasant CMS to work with but that is only my opinion.
There is also a much simpler solution if your needs are basic: http://docs.joomla.org/SQL_form_field_type
There is an "sql" form field type:
<field name="title" type="sql" default="10" label="Select an article" query="SELECT id AS value, title FROM #__content" />
(I sympathize with your frustration - the documentation is terrible, scattered and hard to find)

Categories