The mass action system included in HikaShop lets a developer add the filters and the actions a shop needs, and even the data a mass action can work on. This page gives the basis of such a plugin: a filter, an action, and a table of your own. Each of them is written once, as a class, and HikaShop takes care of the rest: the edit form, the counter of the filters, the triggers, the scheduler, the HTTP endpoints and the MCP tool all use the same class.
Start by creating a HikaShop plugin as explained in this tutorial, then add the functions below to it. The mass action plugins which come with HikaShop, and the classes under administrator/components/com_hikashop/helpers/massaction, are complete examples of everything described here.
A filter
A filter is a class registered under the name a saved mass action stores. The following one keeps the products which have no image. apply() is called in two situations: with no elements, when the mass action runs from a query (the Process button, the scheduler, an HTTP endpoint), where it adds a condition to the query; and with elements, when a trigger such as the creation of a product hands them over, where it removes the ones which do not match.
// Register the filter
function onMassactionTypeLoad(&$types) {
if(!class_exists('hikashopMassactionFilterBaseHelper'))
include_once(rtrim(HIKASHOP_HELPER, DS).DS.'massaction'.DS.'filter'.DS.'base.php');
include_once(__DIR__.DS.'noimage.php');
$types['productNoImage'] = new plgHikashopMyMassactionNoImage();
}
// noimage.php class plgHikashopMyMassactionNoImage extends hikashopMassactionFilterBaseHelper { // Only offered on the tables naming it in their "types" public function universal() { return false; } public function label($origin, $name) { return 'Products without an image'; } public function apply($origin, &$elements, &$query, $filter, $num) { $db = \Joomla\CMS\Factory::getDBO(); $images = 'SELECT file_ref_id FROM '.hikashop_table('file').' WHERE file_type = '.$db->quote('product'); if(count($elements)) { $db->setQuery($images); $withImage = $db->loadColumn(); foreach($elements as $k => $element) { if(in_array($element->product_id, $withImage)) unset($elements[$k]); } return; } $query->where[] = 'hk_product.product_id NOT IN ('.$images.')'; } // What the edit form says next to the filter public function count($origin, &$query, $filter, $num) { $elements = array(); $this->apply($origin, $elements, $query, $filter, $num); return $this->countElements($origin, $query); } }
A filter which is not universal is offered by the tables naming it. To offer this one on the products, add it to the types of the product table. Do it in onMassactionRelationLoad, which is triggered once every table has been declared, whatever the order the plugins run in:
function onMassactionRelationLoad(&$links, $tables) {
if(isset($tables['product']))
$tables['product']->types['productNoImage'] = 'productNoImage';
}
A filter which needs settings in the edit form also gives defaults(), the settings of a new filter, and getHtml(), the fields displayed once it is selected, named filter[table][key][name][setting]. What the merchant entered comes back in $filter.
An action
An action is registered the same way, through onMassactionActionLoad, and runs in act() on the elements the filters kept. It can return a sentence for the report of the mass action.
function onMassactionActionLoad(&$actions) {
if(!class_exists('hikashopMassactionActionBaseHelper'))
include_once(rtrim(HIKASHOP_HELPER, DS).DS.'massaction'.DS.'action'.DS.'base.php');
include_once(__DIR__.DS.'publish.php');
$actions['publishProducts'] = new plgHikashopMyMassactionPublish();
}
// publish.php
class plgHikashopMyMassactionPublish extends hikashopMassactionActionBaseHelper {
public function universal() { return false; }
public function label($origin, $name) { return 'Publish the products'; }
public function act($origin, &$elements, $action, $k) {
$productClass = hikashop_get('class.product');
foreach($elements as $element) {
$product = new stdClass();
$product->product_id = (int)$element->product_id;
$product->product_published = 1;
$productClass->save($product);
}
return count($elements).' products published';
}
}
As for a filter, an action which is not universal is offered by the tables naming it, in their actions: $tables['product']->actions[] = 'publishProducts'; in the same onMassactionRelationLoad.
A table of your own
To run mass actions on data of your own, for example the discounts, declare the table. component tells HikaShop where the table lives (#__hikashop_discount here) and id its key. filters offers a filter on the columns of the table, which HikaShop runs itself when it says apply.
function onMassactionTableLoad(&$tables) {
$obj = new stdClass();
$obj->table = 'discount';
$obj->value = 'discount';
$obj->text = \Joomla\CMS\Language\Text::_('DISCOUNT');
$obj->component = 'hikashop';
$obj->id = 'discount_id';
$obj->date_columns = array('discount_start', 'discount_end');
$obj->filters = array(
'discountColumn' => array('label' => 'DISCOUNT', 'table' => 'discount', 'apply' => 'column'),
);
// Offer the import from a CSV file, finding a discount by its code
$obj->types = array('csvImport' => 'csvImport');
$obj->import = array('key' => 'discount_code');
$tables[] = $obj;
}
With import, the "Import from a CSV file" filter is offered too: a file whose first line names columns of the table, one of them the key, selects the rows it names, and with "Save" writes its columns to them. The actions every table has, such as updating a column, deleting the elements, sending an email or exporting them, are then offered on it. The developer documentation lists the other keys a table can carry, the links to the tables it reaches, and the events a filter or an action nobody registered is still sent to.