<?php
namespace Croogo\Core\Model\Behavior;
use Cake\Log\Log;
use Cake\ORM\Behavior;
use Croogo\Core\Status;
use InvalidArgumentException;
/**
* BulkProcess Behavior
*
* Utility Behavior to allow easy bulk processing.
*
* Behavior options:
* - fields:
* map of field and its physical names
* - actions:
* map of action and its method. By default, delete, publish, and
* unpublish are supported. You can add or override the default methods
* by implementing it in the model. These methods needs to accept one
* argument, containing an array of IDs.
*
* @package Croogo.Croogo.Model.Behavior
* @since 2.0
* @author Rachman Chavik <rchavik@xintesa.com>
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
* @link http://www.croogo.org
*
*/
class BulkProcessBehavior extends Behavior
{
protected $_defaultConfig = [
'fields' => [
'status' => 'status',
'promote' => 'promote',
],
'actionsMap' => [
'delete' => 'bulkDelete',
'publish' => 'bulkPublish',
'promote' => false,
'unpublish' => 'bulkUnpublish',
'unpromote' => false,
'copy' => 'bulkCopy',
],
];
/**
* Bulk process using $action for each $ids
*
* @param $action string actionToPerfom
* @param $ids array nodes ids to perform action upon
* @return bool True when successful, false otherwise
* @throws InvalidArgumentException
*/
public function processAction($action, $ids)
{
$table = $this->_table;
$actionsMap = $this->getConfig('actionsMap');
if (empty($actionsMap[$action])) {
throw new InvalidArgumentException(__d('croogo', 'Invalid action to perform'));
}
if (empty($ids)) {
throw new InvalidArgumentException(__d('croogo', 'No target to process action upon'));
}
$mappedAction = $actionsMap[$action];
if ($mappedAction === false) {
throw new InvalidArgumentException(__d('croogo', 'Action %s is disabled'), $action);
}
if (in_array($mappedAction, get_class_methods($table))) {
return $table->{$mappedAction}($ids);
}
return $this->{$mappedAction}($ids);
}
/**
* Internal helper method to save status fields
*
* @param array $ids Array of IDs
* @param string $field Field to update
* @param mixed $status Value to update
* @return bool True on success, false on failure
*/
protected function _saveStatus($ids, $field, $status)
{
foreach ($ids as $id) {
$entity = $this->_table->get($id);
$entity->{$field} = $status;
if (!$this->_table->save($entity)) {
return false;
}
}
return true;
}
/**
* Bulk Publish
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkPublish($ids)
{
$field = $this->getConfig('fields.status');
return $this->_saveStatus($ids, $field, Status::PUBLISHED);
}
/**
* Bulk Publish
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkUnpublish($ids)
{
$field = $this->getConfig('fields.status');
return $this->_saveStatus($ids, $field, Status::UNPUBLISHED);
}
/**
* Bulk Promote
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkPromote($ids)
{
$field = $this->config('fields.promote');
return $this->_saveStatus($ids, $field, Status::PROMOTED);
}
/**
* Bulk Unpromote
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkUnpromote($ids)
{
$field = $this->config('fields.promote');
return $this->_saveStatus($ids, $field, Status::UNPROMOTED);
}
/**
* Bulk Delete
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkDelete($ids)
{
try {
return $this->_table->getConnection()->transactional(function () use ($ids) {
$nodes = $this->_table
->find()
->where([
$this->_table->aliasField('id') . ' IN' => $ids
])
->toArray();
foreach ($nodes as $node) {
if (!$this->_table->delete($node)) {
return false;
}
}
return true;
});
} catch (\Exception $exception) {
Log::critical(__FUNCTION__ . ': ' . $exception->getMessage());
throw $exception;
return false;
}
}
/**
* Bulk Copy
*
* @param array $ids Array of IDs
* @return bool True on success, false on failure
*/
public function bulkCopy($ids)
{
if (!$this->_table->hasBehavior('Copyable')) {
$this->_table->addBehavior('Croogo/Core.Copyable');
}
foreach ($ids as $id) {
if (!$this->_table->copy($id)) {
return false;
}
}
return true;
}
}