[ Index ]

PHP Cross Reference of Mambo 4.6.5

[ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

title

Body

[close]

/administrator/components/com_modules/ -> admin.modules.php (source)

   1  <?php
   2  /**
   3  * @package Mambo
   4  * @subpackage Modules
   5  * @author Mambo Foundation Inc see README.php
   6  * @copyright (C) 2000 - 2009 Mambo Foundation Inc.
   7  * See COPYRIGHT.php for copyright notices and details.
   8  * @license GNU/GPL Version 2, see LICENSE.php
   9  *
  10  * Redistributions of files must retain the above copyright notice.
  11  *
  12  * Mambo is free software; you can redistribute it and/or
  13  * modify it under the terms of the GNU General Public License
  14  * as published by the Free Software Foundation; version 2 of the License.
  15  */
  16  
  17  /** ensure this file is being included by a parent file */
  18  defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' );
  19  
  20  // ensure user has access to this function
  21  if (!($acl->acl_check( 'administration', 'edit', 'users', $my->usertype, 'modules', 'all' ) | $acl->acl_check( 'administration', 'install', 'users', $my->usertype, 'modules', 'all' ))) {
  22      mosRedirect( 'index2.php', T_('You are not authorized to view this resource.') );
  23  }
  24  
  25  require_once( $mainframe->getPath( 'admin_html' ) );
  26  
  27  $client     = mosGetParam( $_REQUEST, 'client', '' );
  28  $cid         = mosGetParam( $_POST, 'cid', array(0) );
  29  $moduleid     = mosGetParam( $_REQUEST, 'moduleid', null );
  30  if ($cid[0] == 0 && isset($moduleid) ) {
  31      $cid[0] = $moduleid;
  32  }
  33  
  34  switch ( $task ) {
  35      case 'copy':
  36          copyModule( $option, intval( $cid[0] ), $client );
  37          break;
  38  
  39      case 'new':
  40          editModule( $option, 0, $client );
  41          break;
  42  
  43      case 'edit':
  44          editModule( $option, $cid[0], $client );
  45          break;
  46  
  47      case 'editA':
  48          editModule( $option, $id, $client );
  49          break;
  50  
  51      case 'save':
  52      case 'apply':
  53          mosCache::cleanCache( 'com_content' );
  54          saveModule( $option, $client, $task );
  55          break;
  56  
  57      case 'remove':
  58          removeModule( $cid, $option, $client );
  59          break;
  60  
  61      case 'cancel':
  62          cancelModule( $option, $client );
  63          break;
  64  
  65      case 'publish':
  66      case 'unpublish':
  67          mosCache::cleanCache( 'com_content' );
  68          publishModule( $cid, ($task == 'publish' ? 1 : 0), $option, $client );
  69          break;
  70  
  71      case 'orderup':
  72      case 'orderdown':
  73          orderModule( $cid[0], ($task == 'orderup' ? -1 : 1), $option, $client );
  74          break;
  75  
  76      case 'accesspublic':
  77      case 'accessregistered':
  78      case 'accessspecial':
  79          accessMenu( $cid[0], $task, $option, $client );
  80          break;
  81  
  82      case 'saveorder':
  83          saveOrder( $cid, $client );
  84          break;
  85  
  86      default:
  87          viewModules( $option, $client );
  88          break;
  89  }
  90  
  91  /**
  92  * Compiles a list of installed or defined modules
  93  */
  94  function viewModules( $option, $client ) {
  95      global $database, $my, $mainframe, $mosConfig_list_limit, $mosConfig_absolute_path;
  96  
  97      $filter_position     = $mainframe->getUserStateFromRequest( "filter_position{$option}{$client}", 'filter_position', 0 );
  98      $filter_type         = $mainframe->getUserStateFromRequest( "filter_type{$option}{$client}", 'filter_type', 0 );
  99      $limit                 = $mainframe->getUserStateFromRequest( "viewlistlimit", 'limit', $mosConfig_list_limit );
 100      $limitstart         = $mainframe->getUserStateFromRequest( "view{$option}limitstart", 'limitstart', 0 );
 101      $search             = $mainframe->getUserStateFromRequest( "search{$option}{$client}", 'search', '' );
 102      $search             = $database->getEscaped( trim( strtolower( $search ) ) );
 103  
 104      if ($client == 'admin') {
 105          $where[] = "m.client_id = '1'";
 106          $client_id = 1;
 107      } else {
 108          $where[] = "m.client_id = '0'";
 109          $client_id = 0;
 110      }
 111  
 112      // used by filter
 113      if ( $filter_position ) {
 114          $where[] = "m.position = '$filter_position'";
 115      }
 116      if ( $filter_type ) {
 117          $where[] = "m.module = '$filter_type'";
 118      }
 119      if ( $search ) {
 120          $where[] = "LOWER( m.title ) LIKE '%$search%'";
 121      }
 122  
 123      // get the total number of records
 124      $query = "SELECT COUNT(*) FROM #__modules AS m ". ( count( $where ) ? "\n WHERE " . implode( ' AND ', $where ) : '' );
 125      $database->setQuery( $query );
 126      $total = $database->loadResult();
 127  
 128      require_once ( $mosConfig_absolute_path . '/administrator/includes/pageNavigation.php' );
 129      $pageNav = new mosPageNav( $total, $limitstart, $limit );
 130  
 131      $database->setQuery( "SELECT m.*, u.name AS editor, g.name AS groupname, MIN(mm.menuid) AS pages"
 132      . "\n FROM #__modules AS m"
 133      . "\n LEFT JOIN #__users AS u ON u.id = m.checked_out"
 134      . "\n LEFT JOIN #__groups AS g ON g.id = m.access"
 135      . "\n LEFT JOIN #__modules_menu AS mm ON mm.moduleid=m.id"
 136      . ( count( $where ) ? "\n WHERE " . implode( ' AND ', $where ) : '' )
 137      . "\n GROUP BY m.id"
 138      . "\n ORDER BY position ASC, ordering ASC"
 139      . "\n LIMIT $pageNav->limitstart,$pageNav->limit"
 140      );
 141      $rows = $database->loadObjectList();
 142      if ($rows) {
 143          foreach($rows as $row) {
 144              $row->title = htmlspecialchars( str_replace( '&amp;', '&', $row->title ) );
 145          }
 146      }
 147      if ($database->getErrorNum()) {
 148          echo $database->stderr();
 149          return false;
 150      }
 151  
 152      // get list of Positions for dropdown filter
 153      $query = "SELECT t.position AS value, t.position AS text"
 154      . "\n FROM #__template_positions as t"
 155      . "\n LEFT JOIN #__modules AS m ON m.position = t.position"
 156      . "\n WHERE m.client_id = '$client_id'"
 157      . "\n GROUP BY t.position"
 158      . "\n ORDER BY t.position"
 159      ;
 160      $positions[] = mosHTML::makeOption( '0', T_('- All Positions -') );
 161      $database->setQuery( $query );
 162      $positions = array_merge( $positions, $database->loadObjectList() );
 163      $lists['position']    = mosHTML::selectList( $positions, 'filter_position', 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', "$filter_position" );
 164  
 165      // get list of Positions for dropdown filter
 166      // @RawSQLUse, trivial_implementation, SELECT
 167      $query = "SELECT module AS value, module AS text"
 168      . "\n FROM #__modules"
 169      . "\n WHERE client_id = '$client_id'"
 170      . "\n GROUP BY module"
 171      . "\n ORDER BY module"
 172      ;
 173      $types[] = mosHTML::makeOption( '0', T_('- All Types -') );
 174      $database->setQuery( $query );
 175      $types = array_merge( $types, $database->loadObjectList() );
 176      $lists['type']    = mosHTML::selectList( $types, 'filter_type', 'class="inputbox" size="1" onchange="document.adminForm.submit( );"', 'value', 'text', "$filter_type" );
 177  
 178      HTML_modules::showModules( $rows, $my->id, $client, $pageNav, $option, $lists, $search );
 179  }
 180  
 181  /**
 182  * Compiles information to add or edit a module
 183  * @param string The current GET/POST option
 184  * @param integer The unique id of the record to edit
 185  */
 186  function copyModule( $option, $uid, $client ) {
 187      global $database, $my;
 188  
 189      $row = new mosModule( $database );
 190      // load the row from the db table
 191      $row->load( $uid );
 192      $row->title = 'Copy of '.$row->title;
 193      $row->id = 0;
 194      $row->iscore = 0;
 195      $row->published = 0;
 196  
 197      if (!$row->check()) {
 198          echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n";
 199          exit();
 200      }
 201      if (!$row->store()) {
 202          echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n";
 203          exit();
 204      }
 205      $row->checkin();
 206      if ($client == 'admin') {
 207          $where = "client_id='1'";
 208      } else {
 209          $where = "client_id='0'";
 210      }
 211      $row->updateOrder( "position='$row->position' AND ($where)" );
 212  
 213      // @RawSQLUse, trivial_implementation, SELECT
 214      $database->setQuery( "SELECT menuid FROM #__modules_menu WHERE moduleid='$uid'" );
 215      $rows = $database->loadResultArray();
 216  
 217      foreach($rows as $menuid) {
 218          // @RawSQLUse, trivial_implementation, INSERT
 219          $database->setQuery( "INSERT INTO #__modules_menu"
 220          . "\nSET moduleid='$row->id', menuid='$menuid'"
 221          );
 222          $database->query();
 223      }
 224  
 225      $msg = sprintf(T_('Module Copied [%s]'), $row->title);
 226      mosRedirect( 'index2.php?option='. $option .'&client='. $client, $msg );
 227  }
 228  
 229  /**
 230  * Saves the module after an edit form submit
 231  */
 232  function saveModule( $option, $client, $task ) {
 233      global $database;
 234  
 235      $params = mosGetParam( $_POST, 'params', '' , _MOS_ALLOWHTML);
 236      if (is_array( $params )) {
 237          $txt = array();
 238          foreach ($params as $k=>$v) {
 239              $txt[] = "$k=$v";
 240          }
 241          $_POST['params'] = mosParameters::textareaHandling( $txt );
 242      }
 243  
 244      $row = new mosModule( $database );
 245      if (!$row->bind( $_POST, 'selections' )) {
 246          echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n";
 247          exit();
 248      }
 249  
 250      // special access groups
 251      if (is_array($row->groups)) {
 252          $row->groups = implode(',',$row->groups);
 253      } else {
 254          $row->groups = '';
 255      }
 256  
 257      if (!$row->check()) {
 258          echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n";
 259          exit();
 260      }
 261      if (!$row->store()) {
 262          echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n";
 263          exit();
 264      }
 265      $row->checkin();
 266      if ($client == 'admin') {
 267          $where = "client_id='1'";
 268      } else {
 269          $where = "client_id='0'";
 270      }
 271      $row->updateOrder( "position='$row->position' AND ($where)" );
 272  
 273      $menus = mosGetParam( $_POST, 'selections', array() );
 274  
 275      // @RawSQLUse, trivial_implementation, DELETE
 276      $database->setQuery( "DELETE FROM #__modules_menu WHERE moduleid='$row->id'" );
 277      $database->query();
 278  
 279      foreach ($menus as $menuid){
 280          // this check for the blank spaces in the select box that have been added for cosmetic reasons
 281          if ( $menuid <> "-999" && $menuid <> "-998") {  
 282              // @RawSQLUse, trivial_implementation, INSERT 
 283              $query = "INSERT INTO #__modules_menu SET moduleid='$row->id', menuid='$menuid'";
 284              $database->setQuery( $query );
 285              $database->query();
 286          }
 287      }
 288  
 289  
 290      switch ( $task ) {
 291          case 'apply':
 292              $msg = sprintf(T_('Successfully Saved changes to Module: %s'), $row->title) ;
 293              mosRedirect( 'index2.php?option='. $option .'&client='. $client .'&task=editA&hidemainmenu=1&id='. $row->id, $msg );
 294              break;
 295  
 296          case 'save':
 297          default:
 298              $msg = sprintf(T_('Successfully Saved Module: %s'), $row->title);
 299              mosRedirect( 'index2.php?option='. $option .'&client='. $client, $msg );
 300              break;
 301      }
 302  }
 303  
 304  /**
 305  * Compiles information to add or edit a module
 306  * @param string The current GET/POST option
 307  * @param integer The unique id of the record to edit
 308  */
 309  function editModule( $option, $uid, $client ) {
 310      global $database, $my, $mainframe;
 311      global $mosConfig_absolute_path;
 312  
 313      $lists = array();
 314      $row = new mosModule( $database );
 315      // load the row from the db table
 316      $row->load( $uid );
 317      // fail if checked out not by 'me'
 318      if ( $row->checked_out && $row->checked_out <> $my->id ) {
 319          echo "<script>alert('".sprintf(T_('The module %s is currently being edited by another administrator'), $row->title)."'); document.location.href='index2.php?option=$option'</script>\n";
 320          exit(0);
 321      }
 322      
 323      $row->title = htmlspecialchars( str_replace( '&amp;', '&', $row->title ) );
 324      $row->content = htmlspecialchars( str_replace( '&amp;', '&', $row->content ) );
 325  
 326      if ( $uid ) {
 327          $row->checkout( $my->id );
 328      }
 329      // if a new record we must still prime the mosModule object with a default
 330      // position and the order; also add an extra item to the order list to
 331      // place the 'new' record in last position if desired
 332      if ($uid == 0) {
 333          $row->position = 'left';
 334          $row->showtitle = true;
 335          //$row->ordering = $l;
 336          $row->published = 1;
 337      }
 338  
 339  
 340      if ( $client == 'admin' ) {
 341          $where                 = "client_id='1'";
 342          $lists['client_id'] = 1;
 343          $path                = 'mod1_xml';
 344      } else {
 345          $where                 = "client_id='0'";
 346          $lists['client_id'] = 0;
 347          $path                = 'mod0_xml';
 348      }
 349  
 350      // @RawSQLUse, trivial_implementation, SELECT
 351      $query = "SELECT position, ordering, showtitle, title"
 352      . "\n FROM #__modules"
 353      . "\n WHERE ". $where
 354      . "\n ORDER BY ordering"
 355      ;
 356  
 357      $database->setQuery( $query );
 358      if ( !($orders = $database->loadObjectList()) ) {
 359          echo $database->stderr();
 360          return false;
 361      }
 362  
 363      // @RawSQLUse, trivial_implementation, SELECT
 364      $query = "SELECT position, description"
 365      . "\n FROM #__template_positions"
 366      . "\n WHERE position <> ''"
 367      ;
 368      $database->setQuery( $query );
 369      // hard code options for now
 370      $positions = $database->loadObjectList();
 371  
 372      $orders2 = array();
 373      $pos = array();
 374      foreach ($positions as $position) {
 375          $orders2[$position->position] = array();
 376          $pos[] = mosHTML::makeOption( $position->position, $position->description );
 377      }
 378  
 379      $l = 0;
 380      $r = 0;
 381      for ($i=0, $n=count( $orders ); $i < $n; $i++) {
 382          $ord = 0;
 383          if (array_key_exists( $orders[$i]->position, $orders2 )) {
 384              $ord =count( array_keys( $orders2[$orders[$i]->position] ) ) + 1;
 385          }
 386  
 387          $orders2[$orders[$i]->position][] = mosHTML::makeOption( $ord, $ord.'::'.addslashes( $orders[$i]->title ) );
 388      }
 389  
 390      // build the html select list
 391      $pos_select = 'onchange="changeDynaList(\'ordering\',orders,document.adminForm.position.options[document.adminForm.position.selectedIndex].value, originalPos, originalOrder)"';
 392      $active = ( $row->position ? $row->position : 'left' );
 393      $lists['position'] = mosHTML::selectList( $pos, 'position', 'class="inputbox" size="1" '. $pos_select, 'value', 'text', $active );
 394  
 395      // get selected pages for $lists['selections']
 396      if ( $uid ) {
 397          // @RawSQLUse, trivial_implementation, SELECT, CONCEPT
 398          $query = 'SELECT menuid AS value FROM #__modules_menu WHERE moduleid='. $row->id;
 399          $database->setQuery( $query );
 400          $lookup = $database->loadObjectList();
 401      } else {
 402          $lookup = array( mosHTML::makeOption( 0, 'All' ) );
 403      }
 404  
 405      if ( $row->access == 99 || $row->client_id == 1 || $lists['client_id'] ) {
 406          $lists['access']             = T_('Administrator').'<input type="hidden" name="access" value="99" />';
 407          $lists['showtitle']         = T_('N/A').' <input type="hidden" name="showtitle" value="1" />';
 408          $lists['selections']         = T_('N/A');
 409      } else {
 410          if ( $client == 'admin' ) {
 411              $lists['access']         = T_('N/A');
 412              $lists['selections']     = T_('N/A');
 413          } else {
 414              $lists['access']         = mosAdminMenus::Access( $row );
 415              $lists['groups']         = mosAdminMenus::groupAccess( $row );
 416              $lists['selections']     = mosAdminMenus::MenuLinks( $lookup, 1, 1 );
 417          }
 418          $lists['showtitle'] = mosHTML::yesnoRadioList( 'showtitle', 'class="inputbox"', $row->showtitle );
 419      }
 420  
 421      // build the html select list for published
 422      $lists['published']             = mosAdminMenus::Published( $row );
 423  
 424      // xml file for module
 425      $xmlfile = $mainframe->getPath( $path, $row->module );
 426      if ($xmlfile) {
 427          $xmlparser =& new mosXMLDescription ($xmlfile);
 428          $row->description = $xmlparser->getDescription('module');
 429      } else {
 430          $row->description = '';
 431      }
 432  
 433      // get params definitions
 434      $params =& new mosAdminParameters( $row->params, $xmlfile, 'module' );
 435  
 436      HTML_modules::editModule( $row, $orders2, $lists, $params, $option );
 437  }
 438  
 439  /**
 440  * Deletes one or more modules
 441  *
 442  * Also deletes associated entries in the #__module_menu table.
 443  * @param array An array of unique category id numbers
 444  */
 445  function removeModule( &$cid, $option, $client ) {
 446      global $database, $my;
 447  
 448      if (count( $cid ) < 1) {
 449          echo "<script> alert('".T_('Select a module to delete')."'); window.history.go(-1);</script>\n";
 450          exit;
 451      }
 452  
 453      $cids = implode( ',', $cid );
 454  
 455      // @RawSQLUse, trivial_implementation, SELECT, CONCEPT
 456      $database->setQuery( "SELECT id, module, title, iscore, params FROM #__modules WHERE id IN ($cids)" );
 457      if (!($rows = $database->loadObjectList())) {
 458          echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>\n";
 459          exit;
 460      }
 461  
 462      $err = array();
 463      $cid = array();
 464      foreach ($rows as $row) {
 465          if ($row->module == '' || $row->iscore == 0) {
 466              $cid[] = $row->id;
 467          } else {
 468              $err[] = $row->title;
 469          }
 470          // mod_mainmenu modules only deletable via Menu Manager
 471          if ( $row->module == 'mod_mainmenu' ) {
 472              if ( strstr( $row->params, 'mainmenu' ) ) {
 473                  echo "<script> alert('".T_('You cannot delete mod_mainmenu module that displays the "mainmenu" as it is a core Menu')."'); window.history.go(-1); </script>\n";
 474                  exit;
 475              }
 476          }
 477      }
 478  
 479      if (count( $cid )) {
 480          $cids = implode( ',', $cid );
 481          // @RawSQLUse, trivial_implementation, DELETE, CONCEPT
 482          $database->setQuery( "DELETE FROM #__modules WHERE id IN ($cids)" );
 483          if (!$database->query()) {
 484              echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>\n";
 485              exit;
 486          }
 487          // @RawSQLUse, trivial_implementation, DELETE, CONCEPT
 488          $database->setQuery( "DELETE from #__modules_menu WHERE moduleid IN ($cids)" );
 489          if (!$database->query()) {
 490              echo "<script> alert('".$database->getErrorMsg()."');</script>\n";
 491              exit;
 492          }
 493          $mod = new mosModule( $database );
 494          $mod->ordering = 0;
 495          $mod->updateOrder( "position='left'" );
 496          $mod->updateOrder( "position='right'" );
 497      }
 498  
 499      if (count( $err )) {
 500          $cids = addslashes( implode( "', '", $err ) );
 501          echo "<script>alert('".sprintf(T_('Module(s): "%s" cannot be deleted they can only be un-installed as they are Mambo modules.'), $cids)."');</script>\n";
 502      }
 503  
 504      mosRedirect( 'index2.php?option='. $option .'&client='. $client );
 505  }
 506  
 507  /**
 508  * Publishes or Unpublishes one or more modules
 509  * @param array An array of unique record id numbers
 510  * @param integer 0 if unpublishing, 1 if publishing
 511  */
 512  function publishModule( $cid=null, $publish=1, $option, $client ) {
 513      global $database, $my;
 514  
 515      if (count( $cid ) < 1) {
 516          $action = $publish ? T_('publish' ): T_('unpublish');
 517          echo "<script> alert('".sprintf(T_('Select a module to %s'), $action)."'); window.history.go(-1);</script>\n";
 518          exit;
 519      }
 520  
 521      $cids = implode( ',', $cid );
 522  
 523      $query = "UPDATE #__modules SET published='$publish'"
 524      . "\n WHERE id IN ($cids)"
 525      . "\n AND (checked_out=0 OR (checked_out='$my->id'))"
 526      ;
 527      $database->setQuery( $query );
 528      if (!$database->query()) {
 529          echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>\n";
 530          exit();
 531      }
 532  
 533      if (count( $cid ) == 1) {
 534          $row = new mosModule( $database );
 535          $row->checkin( $cid[0] );
 536      }
 537  
 538      mosRedirect( 'index2.php?option='. $option .'&client='. $client );
 539  }
 540  
 541  /**
 542  * Cancels an edit operation
 543  */
 544  function cancelModule( $option, $client ) {
 545      global $database;
 546  
 547      $row = new mosModule( $database );
 548      // ignore array elements
 549      $row->bind( $_POST, 'selections params' );
 550      // sanitize
 551      $row->id = intval($row->id);
 552      $row->checkin();
 553  
 554      mosRedirect( 'index2.php?option='. $option .'&client='. $client );
 555  }
 556  
 557  /**
 558  * Moves the order of a record
 559  * @param integer The unique id of record
 560  * @param integer The increment to reorder by
 561  */
 562  function orderModule( $uid, $inc, $option ) {
 563      global $database;
 564  
 565      $client = mosGetParam( $_POST, 'client', '' );
 566  
 567      $row = new mosModule( $database );
 568      $row->load( $uid );
 569      if ($client == 'admin') {
 570          $where = "client_id='1'";
 571      } else {
 572          $where = "client_id='0'";
 573      }
 574  
 575      $row->move( $inc, "position='$row->position' AND ($where)"  );
 576      if ( $client ) {
 577          $client = '&client=admin' ;
 578      } else {
 579          $client = '';
 580      }
 581  
 582      mosRedirect( 'index2.php?option='. $option .'&client='. $client );
 583  }
 584  
 585  /**
 586  * changes the access level of a record
 587  * @param integer The increment to reorder by
 588  */
 589  function accessMenu( $uid, $access, $option, $client ) {
 590      global $database;
 591  
 592      switch ( $access ) {
 593          case 'accesspublic':
 594              $access = 0;
 595              break;
 596  
 597          case 'accessregistered':
 598              $access = 1;
 599              break;
 600  
 601          case 'accessspecial':
 602              $access = 2;
 603              break;
 604      }
 605  
 606      $row = new mosModule( $database );
 607      $row->load( $uid );
 608      $row->access = $access;
 609  
 610      if ( !$row->check() ) {
 611          return $row->getError();
 612      }
 613      if ( !$row->store() ) {
 614          return $row->getError();
 615      }
 616  
 617      mosRedirect( 'index2.php?option='. $option .'&client='. $client );
 618  }
 619  
 620  function saveOrder( &$cid, $client ) {
 621      global $database;
 622      $order         = mosGetParam( $_POST, 'order', array(0) );
 623      $row        = new mosModule( $database );
 624      $positions = array();
 625      // update ordering values
 626      foreach ($cid as $i=>$ciditem) {
 627          $row->load( $ciditem );
 628          if ($row->ordering != $order[$i]) {
 629              $row->ordering = $order[$i];
 630              if (!$row->store()) {
 631                  echo "<script> alert('".$database->getErrorMsg()."'); window.history.go(-1); </script>\n";
 632                  exit();
 633              }
 634              // remember to updateOrder this group
 635              $positions[$row->position][$row->client_id] = $row->id;
 636          }
 637      }
 638      // execute updateOrder for each group
 639      foreach ($positions as $position=>$clients) {
 640          foreach ($clients as $client=>$rowid) {
 641              $row->updateOrder("position = '$position' AND client_id = '$client'");
 642          }
 643      } // foreach
 644  
 645      $msg     = T_('New ordering saved');
 646      mosRedirect( 'index2.php?option=com_modules&client='. $client, $msg );
 647  } // saveOrder
 648  ?>