Chapter 7: Adding Extra Fields [Adding Read and Update functionality for your extra field]

Chapter 7: Adding Extra Fields [Adding Read and Update functionality for your extra field]

So for our mycck component, we have to create an ARKContexts class as we did for the Item type. In our case, the class will be called ARKContextsMyCCKTextarea.

Therefore, we will add another file in the contexts folder of our package and name it ‘textarea.php.’  The name of the file will have to match the name of the extra field you are adding for inline editing support.

 

Now, once we have done that, we will create ARKContextsMyCCKTextarea as follows:

class ARKContextsMyCCKTextarea extends ARKContextsBase
{


}

Okay, now, let us look at the constructor first.

public function __construct($id)
{
	JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_mycck/tables'); 
	
	list($item_id,$id) =  explode('_',$id);
	
	$this->table = 	JTable::getInstance('fields','MyCCK');

	$this->table->load($id);
	$this->table->item_id = $item_id;
	$db = JFactory::getDBO();
	$query = $db->getQuery(true);
	$query->select('value')
		->from('#__mycck_fields_item')
		->where('field_id = '.(int)$id)
		->where('item_id = '.(int)$item_id);
	$db->setQuery($query);	
	$value = $db->loadResult();
	
	$this->table->text = $value;
	$this->table->title = '';
	$this->item = JTable::getInstance('items','MyCCK');
	$this->item->load($item_id);
	
	parent::__construct($id);		
}

The ID that is passed into the constructor contains both the field type id and the associated item id. We need both of these references, so that we can retrieve the field value in the link table.

You will probably have a similar setup if you are dealing with a Content Construction Kit, so you will have to do something similar to what we have done here.

 

Now, let us look at the get method:

public function get()
{
	if($this->id == null)
		return parent::get();	

	$this->table->articletext = $this->table->text;

	return parent::get();	
}

Pretty much, standard stuff here. In this method, we set the 'articletext' property to the field's current value as we did for our other types.

Again, in the triggerContentPlugins, method the code implementation is similar to what we did for the Item main type.

public function triggerContentPlugins($rawText)
{
	
	$item = new stdclass;
				
	$item->text = '';
	if(isset($rawText))
	{
		$item->text = $rawText;
		$item->file_id = $this->id;
		$item->item_id = $this->item_id;
		$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.textarea', &$item, &$params, 0));
		
	}	
		
	return array( 'data'=>$item->text);
}

The main difference, you will find, is in the save method, this is because we have to manually save the updated text because we are using a link table. Also, this is the same regarding versioning, because of the use of a link table to store the textarea’s text content.

public function save($data,$type = 'body')
{
	if($this->id == null)
		return array( 'title'=>'','data'=>'');	
		
	if($type == 'body')
	{
		$data['articletext'] = base64_decode($data['text']);	
	}
	else	
	{
		$data['articletext'] = strip_tags($data['title']); 
	}

	
	//update data into link table
	$db = JFactory::getDBO();	
	$query = $db->getQuery(true);
	$query->update($db->quoteName('#__flexicontent_fields_item'))->set($db->quoteName('value').' = '. $db->quote($data['articletext']))->where('field_id = '. (int) $this->id)
		->where('item_id'.' = '. (int)$this->id);
	$db->setQuery($query);
	$db->query();
	
	//Let's save version manually as we cannot use JTableObserverContenthistory in this case!
	$typeAlias = 'com_mycck.textarea';	
	$contenthistoryHelper = new JHelperContenthistory($typeAlias);	$this->table->id = $thi->id + $this->item_id	
	//Set description field so that is displayed in Joomla's version Manager preview screen
	$this->table->description = $data['articletext'];
	$contenthistoryHelper->store($this->table);
	$this->table->id = $this->id; //reset id 
	
	//We need to process data as we are sending it back to the client
	$item = new stdclass;
	$item->text = $data['articletext'];
	$item->filed_id = $this->id;
	$item->item_id = $this->item_id;
	$params = new JObject;
	$params->set('inline',false); //set this so that we don't trigger the inline content plugins
		
	//let's detect if any plugin tags are being used 
	//if so let's inform the system to warn the user
	$message = $this->detectPluginTags($item->text);
	
	$dispatcher	= JEventDispatcher::getInstance();
	JPluginHelper::importPlugin('content');
	$dispatcher->trigger('onContentPrepare', array ('com_mycck.textarea', &$item, &$params, 0));
	
	return array( 'title'=>$item->text,'data'=>$item->text,'message'=>$message);
}

You may have noticed that we set the description property of the MyCCKFields JTable instance. We do this because we have explicitly told the Joomla Version Manager, that the description field is one of the properties that should be displayed on the preview screen, by listing it in our XML file. The description field does not exist in the database, so, we have to manually add it to our MyCCKFields instance.

 

And again, the version method is virtually identical to the code implementation in the Item context class.

public function version($versionId,$type)
{
			
	$historyTable = JTable::getInstance('Contenthistory');
	$historyTable->load($versionId);
	$rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data));
		
	$item = $this->table;

	$item->bind($rowArray);	
	if($type == 'title')
	{
		return array( 'data'=>$item->title);
	}
	$text = '';
	
	$text = $item->display;

	return array( 'data'=>$text);
	
}

So, putting it all together, your extra field class should look like this:

class ARKContextsMyCCKTextarea extends ARKContextsBase
{

	public function __construct($id)
	{
		JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_mycck/tables'); 
		
		list($item_id,$id) =  explode('_',$id);
		
		$this->table = 	JTable::getInstance('fields','MyCCK');

		$this->table->load($id);
		$this->table->item_id = $item_id;
		$db = JFactory::getDBO();
		$query = $db->getQuery(true);
		$query->select('value')
			->from('#__mycck_fields_item')
			->where('field_id = '.(int)$id)
			->where('item_id = '.(int)$item_id);
		$db->setQuery($query);	
		$value = $db->loadResult();
		
		$this->table->text = $value;
		$this->table->title = '';
		$this->item = JTable::getInstance('items','MyCCK');
		$this->item->load($item_id);
		
		parent::__construct($id);		
	}

	public function get()
	{
		if($this->id == null)
			return parent::get();	

		$this->table->articletext = $this->table->text;

		return parent::get();	
	}

	public function triggerContentPlugins($rawText)
	{
		
		$item = new stdclass;
					
		$item->text = '';
		if(isset($rawText))
		{
			$item->text = $rawText;
			$item->file_id = $this->id;
			$item->item_id = $this->item_id;
			$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.textarea', &$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['articletext'] = base64_decode($data['text']);	
		}
		else	
		{
			$data['articletext'] = strip_tags($data['title']); 
		}

		
		//update data into link table
		$db = JFactory::getDBO();	
		$query = $db->getQuery(true);
		$query->update($db->quoteName('#__flexicontent_fields_item'))->set($db->quoteName('value').' = '. $db->quote($data['articletext']))->where('field_id = '. (int) $this->id)
			->where('item_id'.' = '. (int)$this->id);
		$db->setQuery($query);
		$db->query();
		
		//Let's save version manually as we cannot use JTableObserverContenthistory in this case!
		$typeAlias = 'com_mycck.textarea';	
		$contenthistoryHelper = new JHelperContenthistory($typeAlias);			
		//Set description field so that is displayed in Joomla's version Manager preview screen
		$this->table->description = $data['articletext'];
		$contenthistoryHelper->store($this->table);
		
		//We need to process data as we are sending it back to the client
		$item = new stdclass;
		$item->text = $data['articletext'];
		$item->file_id = $this->id;
		$item->item_id = $this->item_id;
		$params = new JObject;
		$params->set('inline',false); //set this so that we don't trigger the inline content plugins
			
		//let's detect if any plugin tags are being used 
		//if so let's inform the system to warn the user
		$message = $this->detectPluginTags($item->text);
		
		$dispatcher	= JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('content');
		$dispatcher->trigger('onContentPrepare', array ('com_mycck.textarea', &$item, &$params, 0));
		
		return array( 'title'=>$item->text,'data'=>$item->text,'message'=>$message);
	}


	public function version($versionId,$type)
	{
				
		$historyTable = JTable::getInstance('Contenthistory');
		$historyTable->load($versionId);
		$rowArray = JArrayHelper::fromObject(json_decode($historyTable->version_data));
			
		$item = $this->table;

		$item->bind($rowArray);	
		if($type == 'title')
		{
			return array( 'data'=>$item->title);
		}
		$text = '';
		
		$text = $item->display;

		return array( 'data'=>$text);
		
	}
}

Read more: Chapter 7: Adding Extra Fields [Adding Read and Update functionality for your extra field]

  • Hits: 62

Chapter 7: Adding Extra Fields [Modifying the ARKExtension class]

Chapter 7: Adding Extra Fields [Modifying the ARKExtension class]

If you modified your component directly or used Joomla’s template override to add your editable region, please see the section below.                   

Firstly, you will need to change the contexts array to include the context for your extra field in the constructor method.

So, in our mycck.php file, in our ARKExtensionsMyCCK class we must change this line:

$this->inline_allowed_contexts = array('com_mycck.item','com_mycck.category');

To

$this->inline_allowed_contexts = array('com_mycck.item','com_mycck.category','com_mycck.textarea');

Next, we must update our class to check for that context.

So, if we are in that context, only, then we will add an editable region for the Textarea type.

if($this->context == 'com_mycck.textarea')
{	
	
	//Permisson Check
		
	//Set Asset number 
	$this->id = $this->item->item_id;
	$asset = 'com_mycck.item.'.$this->id;
	$createdBy = $this->item->created_by;
	
	$user = JFactory::getUser();		
	//can user edit item if not then bail
	if (!($user->authorise('core.edit', $asset) || ($user->authorise('core.edit.own', $asset) && $user->id == $createdBy)) )
	{
		return false;
	}		
	
				
	//need to override base class here for following check for categories
	/*filter article to see if it is being used to load a module if so skip it
	[widgetkit]
	{loadmodule}
	{loadposition}
	{module}
	{modulepos}
	{modulepos}
	{component}
	{article(s)}
	*/
		
	$text = $this->item->value[0];
	
	$test = preg_match('/\{(?:loadmodule|loadposition|module|modulepos|component|articles?)\s+(.*?)\}/i',$text);

	if(!$test)
		$test = preg_match('/\[widgetkit\s+(.*?)\]/i',$article->text);
	
	if($test)
	{	
		return false;
	}


	$this->type = 'textarea';

	$dispatcher = JEventDispatcher::getInstance();
	JPluginHelper::importPlugin('inline');
	$dispatcher->trigger('editable',array(&$this->item->text, array('id'=>$this->id.'_'.$this->item->field_id,'context'=>$this->dataContext,'itemtype'=>$this->type)));

	return true;

}
elseif(isset($this->item->introtext))
{
	return false;
} ... // rest of code as before

In the code, above, you can see we added logic to the prepare method, similar to what we did for the main type, but, you can see, we manually fire the inline event to add the editor region for our textarea type. We do this because, as you see, we also have to check if the text content contains any plugin tags for pulling through any modules, etc. If this is the case, we bail out at that point.

In our case, the textarea type field in our component fires off only the onContentPrepare event, and not onContentAfterDisplay. So, we are not able to rely on the base class checking this for us because we are too early in the process of rendering our textarea type.

If it is the case that your component fires off the onContentAfterDisplay for your extra field type, then you can do something similar to the following in the display method:

if($this->context == 'com_mycck.textarea')
{	
	
	//Permisson Check
		
	//Set Asset number 
	$this->id = $this->item->item_id.'_'.$this->item->field_id; //set the id 
	$asset = 'com_mycck.item.'.$this->item->item_id;
	$createdBy = $this->item->created_by;
	
	$user = JFactory::getUser();		
	//can user edit item if not then bail
	if (!($user->authorise('core.edit', $asset) || ($user->authorise('core.edit.own', $asset) && $user->id == $createdBy)) )
	{
		return false;
	}		
}
else
{
	... // if we get here then we assume we are the main item type
}
return parent::prepare();

One thing to pay special attention is that, here, we concatenate the ID of the field type and the item type. This is done because we need both references for later as the value for the extra field is stored in a link table, more about that later.

Read more: Chapter 7: Adding Extra Fields [Modifying the ARKExtension class]

  • Hits: 34

Chapter 7: Adding Extra Fields

Chapter 7: Adding Extra Fields

This section is for those who have a component that has more than one or two types, that they want to make editable during inline editing.

We briefly touched on this subject in the versioning chapter of this documentation. If you have not read that section yet, we strongly recommend you read that first before you continue here.

So in the versioning section, above, we mentioned in our Content Construction Kit, that we had an extra textarea field that we wanted to include in inline editing.

We have two options to do this; we chose the option in the following section.

Read more: Chapter 7: Adding Extra Fields

  • Hits: 40

Chapter 7: Adding Extra Fields [Modifying component layout or template layout override]

Chapter 7: Adding Extra Fields [Modifying component layout or template layout override]

Okay, what we do in this section is similar to what we did in the Component Override and Template Override section, previous. If you require a detailed explanation of the parameters passed to the inline plugin event, please see those sections for a full breakdown.

Now, all you to have to do is fire off the inline event passing in the field value you want to make inline editable. That is it.

In our case, we did the following for our, simple, Content Construction Kit:

<?php foreach ($this->item->fields as $field) : ?>
<div class="mycck field-body field-margin">
	<?php 
		$dispatcher->trigger('editable',array(&$field->text, array('id'=>.$this->item->item_id.'_'.$field->field_id,'context'=>'mycck','itemtype'=>$field->type)));
		echo $field->text;
	?>	
</div>
<?php endforeach;?>

Note: Since we only have one extra field, we did no checks to check the field type in the above example.

Okay, we are not finished yet; Now, we have to add the functions to allow the editor to update or save our data during inline editing in the following section.

Read more: Chapter 7: Adding Extra Fields [Modifying component layout or template layout override]

  • Hits: 48

Chapter 6: Creating the Package

Chapter 6: Creating the Package

Okay, if you have been following this tutorial, you should have created similar files as follows:

+files_inlinemycck   [FILES_INLINE + COMPONENT NAME]
|
------+extensions
 	|
---mycck.php   [COMPONENT NAME]
|
------+contexts
	|
	---+mycck	[COMPONENT NAME]
         |
	    --------category.php   	[TYPE NAME as explained in XML]
	   |
	    ----------item.php        [TYPE NAME as explained in XML]
	   |
	    -----------blog.php       [TYPE NAME as explained in XML]
|
index.html
|
inlinemyck.xml  [INLINE +  COMPONENT NAME].xml


This will differ according to your component, but, in general, it should be similar as in our component.

Note: You may or may not have the extensions folder in your package. It all depends if you went with the plugin override or the component/template override method as discussed in Chapter 2: Approach 1 [Plugin override] , Approach 2 [Component override] and Approach 3 [Template override].

 

Your full XML for the inline editing app extension should look like this:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="file" method="upgrade">
	<name>files_mycck</name>
	<author>WebxSolution Ltd</author>
	<creationDate>March 2015</creationDate>
	<copyright>>Copyright (C) 2015 All rights reserved</copyright>
	<license>GNU General Public License version 2</license>
	<authorEmail>This email address is being protected from spambots. You need JavaScript enabled to view it.</authorEmail>
	<authorUrl>http://www.arkextensions.com</authorUrl>
	<version>1.0</version>
	<description>This plugin provides an extension for ARK inline editing to add support for MyCCK</description>
	
	
	<!-- set up data for  inline lookup table     //-->

	<arkeditor>	
		<extensionName>com_mycck</extensionName>
		<!-- allowable views for inline editing //-->
		<views>
			<view>item</view>
			<view>category</view>
		</views>
		
		<!-- add context element if context is different to extension Name //-->
	
		<!-- extension types to be used for inline editing //-->
		<types>
			<type>category</type>
			<type>item</type>
			<type>blog</type>
		</types>
		
		<!-- details for Joomla versioning system //-->
	
	</arkeditor>
	
	<fileset>
		
		<!-- location for MyCCK main inline editing extension type file //--> 
	
		<files folder="extensions" target="plugins/content/arkcontent/extensions">
			<file>mycck.php</file>
		</files>
	
		<!-- location for context types for MyCCK  inline editing extension //-->
	
		<files folder="contexts/mycck" target="plugins/ajax/inlinecontent/contexts/mycck">
			<file>category.php</file>
			<file>item.php</file>
			<file>blog.php</file>
		</files>
		
	</fileset>	
	
	<!-- details for Joomla versioning system //-->
		
	<versioning>
		<versions>
			<version>
				<dbtable>#__items</dbtable>
				<type>item</type>
				<prefix>MyCCKTable</prefix>	
				<formFile>administrator/components/com_flexicontent/models/forms/item.xml</formFile>
				<fields>
					<field>id</field>
					<field>title</field>
					<field>introtext</field>
					<field>fulltext</field>
				</fields>
			</version>
		</versions>
		<catdbtable>#__categories</catdbtable>
		<cattype>category</cattype>
		<catprefix>MyCKKTable</catprefix>	
		<catformFile>administrator/components/com_flexicontent/models/forms/category.xml</catformFile>
		<catfields>
			<field>id</field>
			<field>title</field>
			<field>description</field>
		</catfields>
	</versioning>
	
</extension>

Now, zip all your files, basically, zip up the root folder that contains your files and folders you created. So, you will create a zip file like [FILES_INLINE + COMPONENT NAME].zip such as files_inlinemyck.zip in our case.

Okay, now, we will create a Joomla package file, so that we can easily install and manage our inline editing app using Joomla’s Extension Manager.

Joomla package zipped file should contain the following:

+pkg_inlinemycck	[PKG + COMPONENT NAME]
|
--------+packages
	|
	---------files_inlinemycck.php(Zip file you created above.)
|
index.html
|
pkg_inlinemycck.xml		[PKG_INLINE + COMPONENT NAME].xml

The [PKG_INLINE_ + COMPONENT Name].xml should have similar content to our

Pkg_inlinemycck.xml file:

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="package" method="upgrade">
	<name>Package - Inline MyCCK Editing for Ark Editor</name>
	<author>WebxSolution Ltd</author>
	<creationDate>July 2015</creationDate>
	<packagename>inlinemycck</packagename>
	<version>1.0</version>
	<url>http://www.arkextensions.com</url>
	<packager>Webxsolution</packager>
	<packagerurl>http://www.arkextensions.com</packagerurl>
	<description>This package provides an extension for ArK inline editing, adding support for MyCCK</description>
	<license>GNU/GPLv2</license>

	<files folder="packages">
		<file type="file" id="inlinemycck">files_inlinemycck.zip</file>
	</files>
</extension>

So, zip up those files to create the inline editing package, when you are ready to install your inline editing app.

Okay, that is it, you should be good to go!

Read more: Chapter 6: Creating the Package

  • Hits: 39