Skip to content

Commit

Permalink
Merge pull request joomla#26 from mbabker/master
Browse files Browse the repository at this point in the history
Add batch processing to framework (Feature Request #22590)
  • Loading branch information
LouisLandry committed Jun 19, 2011
2 parents 3b27c97 + 20cc865 commit 4696d91
Show file tree
Hide file tree
Showing 3 changed files with 408 additions and 0 deletions.
25 changes: 25 additions & 0 deletions libraries/joomla/application/component/controllerform.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,31 @@ protected function allowSave($data, $key = 'id')
}
}

/**
* Method to run batch operations.
*
* @param object $model The model of the component being processed.
*
* @return boolean True if successful, false otherwise and internal error is set.
* @since 11.1
*/
public function batch($model)
{
// Initialise variables.
$app = JFactory::getApplication();
$vars = JRequest::getVar('batch', array(), 'post', 'array');
$cid = JRequest::getVar('cid', array(), 'post', 'array');

// Attempt to run the batch operation.
if ($model->batch($vars, $cid)) {
$this->setMessage(JText::_('JLIB_APPLICATION_SUCCESS_BATCH'));
return true;
} else {
$this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_FAILED', $model->getError()));
return false;
}
}

/**
* Method to cancel an edit.
*
Expand Down
310 changes: 310 additions & 0 deletions libraries/joomla/application/component/modeladmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,285 @@ public function __construct($config = array())
}
}

/**
* Method to perform batch operations on an item or a set of items.
*
* @param array $commands An array of commands to perform.
* @param array $pks An array of item ids.
*
* @return boolean Returns true on success, false on failure.
* @since 11.1
*/
public function batch($commands, $pks)
{
// Sanitize user ids.
$pks = array_unique($pks);
JArrayHelper::toInteger($pks);

// Remove any values of zero.
if (array_search(0, $pks, true)) {
unset($pks[array_search(0, $pks, true)]);
}

if (empty($pks)) {
$this->setError(JText::_('JGLOBAL_NO_ITEM_SELECTED'));
return false;
}

$done = false;

if (!empty($commands['assetgroup_id'])) {
if (!$this->batchAccess($commands['assetgroup_id'], $pks)) {
return false;
}

$done = true;
}

if (!empty($commands['category_id'])) {
$cmd = JArrayHelper::getValue($commands, 'move_copy', 'c');

if ($cmd == 'c' && !$this->batchCopy($commands['category_id'], $pks)) {
return false;
} else if ($cmd == 'm' && !$this->batchMove($commands['category_id'], $pks)) {
return false;
}
$done = true;
}

if (!$done) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_INSUFFICIENT_BATCH_INFORMATION'));
return false;
}

// Clear the cache
$this->cleanCache();

return true;
}

/**
* Batch access level changes for a group of rows.
*
* @param integer $value The new value matching an Asset Group ID.
* @param array $pks An array of row IDs.
*
* @return booelan True if successful, false otherwise and internal error is set.
* @since 11.1
*/
protected function batchAccess($value, $pks)
{
// Check that user has edit permission for items
$extension = JRequest::getCmd('option');
$user = JFactory::getUser();
if (!$user->authorise('core.edit', $extension)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
return false;
}

$table = $this->getTable();

foreach ($pks as $pk) {
$table->reset();
$table->load($pk);
$table->access = (int) $value;

if (!$table->store()) {
$this->setError($table->getError());
return false;
}
}

// Clean the cache
$this->cleanCache();

return true;
}

/**
* Batch copy items to a new category or current.
*
* @param integer $value The new category.
* @param array $pks An array of row IDs.
*
* @return boolean True if successful, false otherwise and internal error is set.
* @since 11.1
*/
protected function batchCopy($value, $pks)
{
$categoryId = (int) $value;

$table = $this->getTable();
$db = $this->getDbo();

// Check that the category exists
if ($categoryId) {
$categoryTable = JTable::getInstance('Category');
if (!$categoryTable->load($categoryId)) {
if ($error = $categoryTable->getError()) {
// Fatal error
$this->setError($error);
return false;
} else {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
return false;
}
}
}

if (empty($categoryId)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
return false;
}

// Check that the user has create permission for the component
$extension = JRequest::getCmd('option');
$user = JFactory::getUser();
if (!$user->authorise('core.create', $extension)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
return false;
}

// Parent exists so we let's proceed
while (!empty($pks))
{
// Pop the first ID off the stack
$pk = array_shift($pks);

$table->reset();

// Check that the row actually exists
if (!$table->load($pk)) {
if ($error = $table->getError()) {
// Fatal error
$this->setError($error);
return false;
} else {
// Not fatal error
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
continue;
}
}

// Alter the title & alias
$data = $this->generateNewTitle($categoryId, $table->alias, $table->title);
$table->title = $data['0'];
$table->alias = $data['1'];

// Reset the ID because we are making a copy
$table->id = 0;

// New category ID
$table->catid = $categoryId;

// TODO: Deal with ordering?
//$table->ordering = 1;

// Check the row
if (!$table->check()) {
$this->setError($table->getError());
return false;
}

// Store the row
if (!$table->store()) {
$this->setError($table->getError());
return false;
}
}

// Clean the cache
$this->cleanCache();

return true;
}

/**
* Batch move articles to a new category
*
* @param integer $value The new category ID.
* @param array $pks An array of row IDs.
*
* @return booelan True if successful, false otherwise and internal error is set.
* @since 11.1
*/
protected function batchMove($value, $pks)
{
$categoryId = (int) $value;

$table = $this->getTable();
$db = $this->getDbo();

// Check that the category exists
if ($categoryId) {
$categoryTable = JTable::getInstance('Category');
if (!$categoryTable->load($categoryId)) {
if ($error = $categoryTable->getError()) {
// Fatal error
$this->setError($error);
return false;
} else {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
return false;
}
}
}

if (empty($categoryId)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_MOVE_CATEGORY_NOT_FOUND'));
return false;
}

// Check that user has create and edit permission for the component
$extension = JRequest::getCmd('option');
$user = JFactory::getUser();
if (!$user->authorise('core.create', $extension)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE'));
return false;
}

if (!$user->authorise('core.edit', $extension)) {
$this->setError(JText::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT'));
return false;
}

// Parent exists so we let's proceed
foreach ($pks as $pk) {
// Check that the row actually exists
if (!$table->load($pk)) {
if ($error = $table->getError()) {
// Fatal error
$this->setError($error);
return false;
} else {
// Not fatal error
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_BATCH_MOVE_ROW_NOT_FOUND', $pk));
continue;
}
}

// Set the new category ID
$table->catid = $categoryId;

// Check the row
if (!$table->check()) {
$this->setError($table->getError());
return false;
}

// Store the row
if (!$table->store()) {
$this->setError($table->getError());
return false;
}
}

// Clean the cache
$this->cleanCache();

return true;
}

/**
* Method to test whether a record can be deleted.
*
Expand Down Expand Up @@ -260,6 +539,37 @@ public function delete(&$pks)
return true;
}

/**
* Method to change the title & alias.
*
* @param integer $category_id The id of the category.
* @param string $alias The alias.
* @param string $title The title.
*
* @return array Contains the modified title and alias.
* @since 11.1
*/
protected function generateNewTitle($category_id, $alias, $title)
{
// Alter the title & alias
$table = $this->getTable();
while ($table->load(array('alias'=>$alias, 'catid'=>$category_id))) {
$m = null;
if (preg_match('#-(\d+)$#', $alias, $m)) {
$alias = preg_replace('#-(\d+)$#', '-'.($m[1] + 1).'', $alias);
} else {
$alias .= '-2';
}
if (preg_match('#\((\d+)\)$#', $title, $m)) {
$title = preg_replace('#\(\d+\)$#', '('.($m[1] + 1).')', $title);
} else {
$title .= ' (2)';
}
}

return array($title, $alias);
}

/**
* Method to get a single record.
*
Expand Down
Loading

0 comments on commit 4696d91

Please sign in to comment.