AtkExtendableShuttleRelation
The extendableShuttleRelation is a many-to-many relation which can be extended with so called controls. These controls are AJAX-components which can, for example, be used to show information about the current available/selected items or to filter these items.
The extendableShuttleRelation is based on the atkShuttleRelation: This implies that its core functionality is the same as the shuttleRelation and therefore can be a substitute for the ordinary shuttleRelation, and might, in time, completely replace the current shuttleRelation.
function atkExtendableShuttleRelation ($name, $link, $destination, $flags=0) String $name The name of the relation. String $link The full name of the node that is used as intermediairy node. String $destination The full name of the node that is the other end of the relation. int $flags Flags for the relation.
As said, the relation can be extended with controls, or more specific, filters. The difference between a control and a filter is that a control is readonly (e.g. a counter for selectable records) and a filter influences the entries in the shuttle lists (e.g. a filter which limits selectable records to records ending with '1'). Multiple filters can even depend on each other.
If you want to use a control or filter, you have to extend the atkShuttleControl class or the atkShuttleFilter class and at least implement the following function:
/**
* Renders the control. Returns a piece of HTML that is used in the shuttle
* to represent this control. If this control has input elements then the
* getFormName method can be used to retrieve the base name for the input
* elements. The getValue method can be used to retrieve this controls value(s)
* for the given record.
*
* @param array $record full record
* @param string $mode add/edit mode
* @param string $prefix field prefix
*
* @return string HTML string
*/
public abstract function render($record, $mode, $prefix);
For the atkShuttleFilter you need to implement one more function:
/**
* Returns a filter clause for this filter's current value.
* The current value can be retrieved from the record using
* the getValue function.
*
* @param array $record full record
*/
public abstract function getFilter($record);
Optionally, you can implement this function:
/**
* Called if a filter or selection event has occured. And allows the control to
* state if it needs to be refreshed based on the filter or selection changes.
*
* @param string $type type of event ('filter' or 'selection'
* @param array $record full record (see partial_filter, partial_selection for more information)
*
* @return boolean needs refresh?
*/
public function needsRefresh($type, $record)
Controls can be added to the relation as follows:
atkExtendableShuttleRelation::addControl($name, $section) String $name The name of the control String $section Either atkShuttleControl::AVAILABLE or atkShuttleControl::SELECTABLE. This tells the relation on which shuttle list you want to add the control.
Example:
userelation("atkextendableshuttlerelation");
atkimport("controls/class.selectedcountercontrol.inc");
atkimport("controls/class.searchfilter.inc");
class exampleNode extends atkNode
{
function exampleNode()
{
$this->atkNode("exampleNode");
$this->add(new atkAttribute("id",AF_AUTOKEY));
$this->add(new atkAttribute("name",AF_OBLIGATORY));
$relation = new atkExtendableShuttleRelation("shuttleExample","example.interm","example.node2");
$relation->addControl(new selectedCounterControl('selected'), atkShuttleControl::SELECTED);
$relation->addControl(new searchFilter('sfilter'), atkShuttleControl::AVAILABLE);
$this->add($relation);
$this->setOrder("name");
$this->setTable("example_table");
}
}
class searchFilter extends atkShuttleFilter
{
public function getFilter($record)
{
$filterValue = escapeSQL($this->getValue($record));
if ($filterValue!="")
{
$this->m_shuttle->addDestinationFilter("name LIKE '%{$filterValue}%'");
}
}
public function render($record, $mode, $prefix)
{
parent::render($record,$mode,$prefix);
return '
<div id="'.$this->getFormName($prefix).'">
<input type="text" name="'.$this->getFormName($prefix).'" onkeyup="'.$prefix.$this->getName().'_onChange(this)" value="'.$this->getValue($record).'" />
</div>
';
}
}
class selectedCounterControl extends atkShuttleControl
{
public function needsRefresh($type, $record)
{
if ($this->getValue($record)!==count($record[$this->m_shuttle->fieldName()]['selected']))
{
return true;
}
else
{
return false;
}
}
public function render($record, $mode, $prefix)
{
return '
<div id="'.$this->getFormName($prefix).'">'.$this->m_name.': '.count($record[$this->m_shuttle->fieldName()]['selected']).'</div>
';
}
}
This will result into:
