Chapter 3: Category type
In the category.php file, we define our class as follows:
class ARKContextsMyCCKCategory extends ARKContextsBase
{
}
Note: the class name is made up of the prefix ARKContents + [COMPONENT NAME/Context Name] + [Type]
Now, let us look at the constructor of this class:
public function __construct($id)
{
JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_mycck/tables');
$this->table = JTable::getInstance('category',’MyCCK’);
$this->table->load($id);
return parent::__construct($id);
}
Firstly, in this constructor, we set up the table member variable, that holds the data from the database for the currently selected record.
Now, let us take a look at the implementation of the get method:
public function get()
{
if($this->id == null) //check if Id has been passed and bail if not!
return parent::get();
$this->table->articletext = $this->table->description;
return parent::get(); //call parent function always.
}
In this function, we set up the ‘articletext’ property. This property or the ‘title’ are passed back to the parent get function. We only need to populate one, and the one you need depends on the type you are editing. If the type is text only, such as a text input, you would only set the title property. If the type allows HTML, like a Textarea, then you would populate the ‘aritcletext’ property as in the above example.
The next function we need to implement is the triggerContentPlugins function, and this is the method we use when we want to render the content back to the user. In this function, we simply follow the rendering process we do in our component, calling any content plugins that are required.
So here is our implementation for the MyCCK content construction kit:
public function triggerContentPlugins($rawText)
{
$item = new stdclass;
$item->text = '';
if(isset($rawText))
{
$item->text = $rawText;
$params = new JObject;
$params->set('inline',false); //set this so that we don't trigger the inline content plugins
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('content');
$dispatcher->trigger('onContentPrepare', array ('com_mycck.category', &$item, &$params, 0));
}
return array( 'data'=>$item->text);
}
As you can see in the code, we do the standard Joomla code for firing off a plugin event. And in this case, it is the onContentPrepare event, similar to what happens when we render the category description for our component.
The important line here is this one:
$params->set('inline',false); //set this so that we don't trigger the inline content plugins
We need to set this parameter setting to ensure we do not call any inline content plugins again; in doing this we will ensure we will not be responsible for causing any self-conflicting issues.
The last function we need to implement for now, is the save function. In our inline app for our MyCCK component, we have implemented the following:
public function save($data,$type = 'body')
{
if($this->id == null)
return array( 'title'=>'','data'=>'');
if($type == $body)
{
$data['description'] = base64_decode($data['articletext']);
}
else
{
$data['title'] = strip_tags($data['title']);
}
$this->table->save($data);
//We need to process data as we are sending it back to the client
$item = $this->table;
$item->text = $item->description;
//let's detect if any plugin tags are beig used
//if so let's inform the system to warn the user
$message = $this->detectPluginTags($item->text);
$params = new JObject;
$params->set('inline',false); //set this so that we don't trigger the inline content plugins
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('content');
$dispatcher->trigger('onContentPrepare', array ('com_content.category', &$item, &$params, 0));
return array( 'title'=>$item->title,'data'=>$item->text,'message'=>$message);
An associated array of data will be passed into the save function from the post. So in our method, we check to see what type of data is being passed in, by checking the type flag.
If the type flag is set to ‘body’ then HTML data will be passed back to the save method; otherwise it will be text only.
The $data associative array will contain one of the following items:
Key |
Value |
articletext |
HTML string or empty string |
title |
Text only string or empty string |
If the data type is ‘body’, then the ‘articletext’ key will be set with the HTML data. If the type is set to ‘title’, then the title key will be set with the text only data, that was sent via post.
So, in case, for our MyCCK component for the category description, we set $data[‘description’] to $data[‘articletext]. We do this so that we can bind and save that data using our JTable instance.
Strictly speaking, you only need to do the following in this method if auto-save is enabled for inline editing. However, since this is the default behaviour we must make certain we do it.
Once the data is saved and completed, we have to get the updated data and render it back into the inline editor. This process is similar to the implementation of the triggerContentPlugins method.
The only real difference is this line:
$message = $this->detectPluginTags($item->text);
The detectPluginTags method we call, as the name suggests, checks for any plugin code in our content for our component. If this is the case, we generate a message to tell the user that because the content contains content plugin code, that it may not be rendered correctly, and so they may need to refresh the page.
Please note: In most cases, this will not likely happen; however, for those using JavaScript to further transform their content, this will most likely be the case.
In this function, we must return an associative array with the following structure:
Key |
Value |
title |
Text only string or empty string |
data |
HTML or empty string |
message |
Text only string or empty string |
Please note: that with the ‘title’ and ‘data’ values, at least one must be not an empty string.
So putting it all together, the code we needed to do for our category type, for our MyCCK component, is as follows:
class ARKContextsMyCCKCategory extends ARKContextsBase
{
public function __construct($id)
{
JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_mycck/tables');
$this->table = JTable::getInstance('category',’MyCCK’);
$this->table->load($id);
return parent::__construct($id);
}
public function get()
{
if($this->id == null)
return parent::get();
$this->table->articletext = $this->table->description;
return parent::get();
}
public function triggerContentPlugins($rawText)
{
$item = new stdclass;
$item->text = '';
if(isset($rawText))
{
$item->text = $rawText;
$params = new JObject;
$params->set('inline',false); //set this so that we don't trigger the inline content plugins
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('content');
$dispatcher->trigger('onContentPrepare', array ('com_mycck.category', &$item, &$params, 0));
}
return array( 'data'=>$item->text);
}
public function save($data,$type = 'body')
{
if($this->id == null)
return array( 'title'=>'','data'=>'');
if($type == $body)
{
$data['description'] = base64_decode($data['articletext']);
}
else
{
$data['title'] = strip_tags($data['title']); //ensure only text is allowed
}
$this->table->save($data);
//We need to process data as we are sending it back to the client
$item = $this->table;
$item->text = $item->description;
//let's detect if any plugin tags are beig used
//if so let's inform the system to warn the user
$message = $this->detectPluginTags($item->text);
$params = new JObject;
$params->set('inline',false); //set this so that we don't trigger the inline content plugins
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('content');
$dispatcher->trigger('onContentPrepare', array ('com_content.category', &$item, &$params, 0));
return array( 'title'=>$item->title,'data'=>$item->text,'message'=>$message);
}
}