<?php
namespace Croogo\Core\Controller\Component;
use Cake\Controller\Component;
use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\ORM\Table;
use Cake\Utility\Hash;
use Cake\Utility\Inflector;
use Croogo\Core\Croogo;
/**
* BulkProcess Component
*
* @category Component
* @package Croogo.Croogo.Controller.Component
* @version 1.0
* @author Rachman Chavik
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
* @link http://www.croogo.org
*/
class BulkProcessComponent extends Component
{
public $components = [
'Flash'
];
/**
* controller
*
* @var Controller
*/
protected $_controller = null;
/**
* beforeFilter
*/
public function beforeFilter(Event $event)
{
$this->_controller = $event->getSubject();
if ($this->_controller->request->getParam('action') == 'process') {
$this->_controller->Security->setConfig('validatePost', false);
}
}
/**
* Get variables used for bulk processing
*
* @param string $model Model alias
* @param string $primaryKey Primary key
* @return array Array with 2 elements. First element is action name, second is
* array of model IDs
*/
public function getRequestVars($model, $primaryKey = 'id')
{
$data = $this->_controller->request->getData($model);
$action = $this->_controller->request->getData('action');
$ids = [];
foreach ($data as $id => $value) {
if (is_array($value) && !empty($value[$primaryKey])) {
$ids[] = $id;
}
}
return [$action, $ids];
}
/**
* Convenience method to check for selection count and redirect request
*
* @param bool $condition True will redirect request to $options['redirect']
* @param array $options Options array as passed to process()
* @return bool True if selection is valid
*/
protected function _validateSelection($condition, $options, $messageName)
{
$messageMap = $options['messageMap'];
$message = $messageMap[$messageName];
if ($condition === true) {
$this->Flash->error($message);
$this->_controller->redirect($options['redirect']);
}
return !$condition;
}
/**
* Process Bulk Request
*
* Operates on $Model object and assumes that bulk processing will be delegated
* to BulkProcessBehavior
*
* Options:
* - redirect URL to redirect in array format
* - messageMap Map of error name and its message
*
* @param Table $table Table instance
* @param string $action Action name to process
* @param array $ids Array of IDs
* @param array $options Options
* @return void
*/
public function process(Table $table, $action, $ids, $options = [])
{
$Controller = $this->_controller;
$emptyMessage = __d('croogo', 'No item selected');
$noMultipleMessage = __d('croogo', 'Please choose only one item for this operation');
$options = Hash::merge([
'multiple' => [],
'redirect' => [
'action' => 'index',
],
'messageMap' => [
'empty' => $emptyMessage,
'noMultiple' => $noMultipleMessage,
],
], $options);
$messageMap = $options['messageMap'];
$itemCount = count($ids);
$noItems = $itemCount === 0 || $action == null;
$valid = $this->_validateSelection($noItems, $options, 'empty');
if (!$valid) {
return;
}
$tooMany = isset($options['multiple'][$action]) && $options['multiple'][$action] === false && $itemCount > 1;
$valid = $this->_validateSelection($tooMany, $options, 'noMultiple');
if (!$valid) {
return false;
}
if (!$table->hasBehavior('BulkProcess')) {
$table->addBehavior('Croogo/Core.BulkProcess');
}
try {
$processed = $table->processAction($action, $ids);
} catch (\Exception $e) {
$message = $e->getMessage();
}
if (isset($processed)) {
$eventName = 'Controller.' . $Controller->getName() . '.after' . ucfirst($action);
if (!empty($messageMap[$action])) {
$message = $messageMap[$action];
} else {
$message = __d('croogo', '%s processed', Inflector::humanize($table->alias()));
}
$flashMethod = 'success';
Croogo::dispatchEvent($eventName, $Controller, compact($ids));
} else {
$message = $message ?: __d('croogo', 'An error occured');
$flashMethod = 'error';
}
$this->Flash->{$flashMethod}($message);
return $Controller->redirect($options['redirect']);
}
}