Moving support for "Element" versions in workspaces.
authorKasper Skårhøj <kasper@typo3.org>
Wed, 29 Aug 2007 15:52:38 +0000 (15:52 +0000)
committerKasper Skårhøj <kasper@typo3.org>
Wed, 29 Aug 2007 15:52:38 +0000 (15:52 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@2470 709f56b5-9817-0410-a4d7-c38de5d9e867

26 files changed:
ChangeLog
t3lib/class.t3lib_befunc.php
t3lib/class.t3lib_browsetree.php
t3lib/class.t3lib_iconworks.php
t3lib/class.t3lib_page.php
t3lib/class.t3lib_positionmap.php
t3lib/class.t3lib_tceforms.php
t3lib/class.t3lib_tcemain.php
t3lib/class.t3lib_treeview.php
t3lib/class.t3lib_userauthgroup.php
t3lib/config_default.php
t3lib/stddb/tables.php
t3lib/stddb/tables.sql
typo3/class.db_list_extra.inc
typo3/gfx/i/shadow_moveto_plh.png [new file with mode: 0644]
typo3/gfx/i/shadow_moveto_pointer.png [new file with mode: 0644]
typo3/mod/user/ws/class.wslib_gui.php
typo3/mod/user/ws/index.php
typo3/sysext/cms/ext_tables.php
typo3/sysext/cms/ext_tables.sql
typo3/sysext/cms/layout/class.tx_cms_layout.php
typo3/sysext/cms/layout/db_layout.php
typo3/sysext/cms/tslib/class.tslib_content.php
typo3/sysext/cms/web_info/class.tx_cms_webinfo_lang.php
typo3/sysext/lowlevel/clmods/class.versions.php
typo3/sysext/wizard_crpages/class.tx_wizardcrpages_webfunc_2.php

index 2137c65..5c5c8d3 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,18 @@
 
 2007-08-28  Kasper Skaarhoj  <kasper2007@typo3.com>
 
+       * Moving in workspaces + collateral
+               - Implemented moving for elements ("Element" versions) in workspaces. Updated "Inside TYPO3" and "TYPO3 Core API". GENEROUS DONATIONS TO FINANCE THIS WORK ARE WELCOME since many of you need this feature!
+               - Workspace "swapping" for "New"-placeholders and "Deleted"-Markers is now supported. Previously, both types would be published, not swapped. The change also means that effectively the difference between the value of "t3ver_state" being 1 or 2 is only cosmetic and the semantic depends on whether the field is set for a record being online or offline. TYPO3 core API is updated on the issue.
+               - Refactored function for moving elements (t3lib_tcemain::moveRecord())
+               - t3lib_BEfunc::workspaceOL() may now set the input variable $row (which is passed by reference) to false. The consequence is that code calling workspaceOL() should check if $row is still an array after calling the function. False is used if a version overlay with the move-id pointer is found in which case we would like a backend preview.
+               - Added switch in TYPO3_CONF_VARS['BE']['elementVersioningOnly'] which allows to completely turn off page and branch versioning (which are depricated for TYPO3 4.2+)
+               - Added more tests for version integrity (centering around moving)
+               - Added checkboxes and an action selector in the Workspace module for batch processing of elements.
+               - Added "flush" command to TCEmain api for versions so versions can be completely deleted and not only released from a workspace.
+
+2007-08-28 Kasper Skaarhoj <kasper2007@typo3.com>
+
        * Improvements as announced in June on the core list (except workspace moving)
                - Dual-preview for workspaces are only used now if the checkbox "Frontend Preview" is not checked.
                - Whole workspaces can be previewed now for users with no backend login by a simple link you can email. Same functionality as the preview link for individual pages available from the Web>Versioning module. The function is found in User>Workspace (Workspace manager)
index 4bf4f98..7b12e6f 100755 (executable)
@@ -565,9 +565,11 @@ class t3lib_BEfunc {
                        }
                        if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
                                if($workspaceOL)        t3lib_BEfunc::workspaceOL('pages',$row);
-                               t3lib_BEfunc::fixVersioningPid('pages',$row);
-                               $uid = $row['pid'];
-                               $theRowArray[] = $row;
+                               if (is_array($row))     {
+                                       t3lib_BEfunc::fixVersioningPid('pages',$row);
+                                       $uid = $row['pid'];
+                                       $theRowArray[] = $row;
+                               } else break;
                        } else {
                                break;
                        }
@@ -665,14 +667,16 @@ class t3lib_BEfunc        {
                                        );
                        if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
                                t3lib_BEfunc::workspaceOL('pages',$row);
-                               t3lib_BEfunc::fixVersioningPid('pages',$row);
+                               if (is_array($row))     {
+                                       t3lib_BEfunc::fixVersioningPid('pages',$row);
 
-                               if ($row['_ORIG_pid'] && $row['t3ver_swapmode']>0)      {       // Branch points
-                                       $output = ' [#VEP#]'.$output;           // Adding visual token - Versioning Entry Point - that tells that THIS position was where the versionized branch got connected to the main tree. I will have to find a better name or something...
-                               }
-                               $uid = $row['pid'];
-                               $output = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$titleLimit).$output;
-                               if ($fullTitleLimit)    $fullOutput = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$fullTitleLimit).$fullOutput;
+                                       if ($row['_ORIG_pid'] && $row['t3ver_swapmode']>0)      {       // Branch points
+                                               $output = ' [#VEP#]'.$output;           // Adding visual token - Versioning Entry Point - that tells that THIS position was where the versionized branch got connected to the main tree. I will have to find a better name or something...
+                                       }
+                                       $uid = $row['pid'];
+                                       $output = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$titleLimit).$output;
+                                       if ($fullTitleLimit)    $fullOutput = '/'.t3lib_div::fixed_lgd_cs(strip_tags($row['title']),$fullTitleLimit).$fullOutput;
+                               } else break;
                        } else {
                                break;
                        }
@@ -831,9 +835,11 @@ class t3lib_BEfunc {
                                $pageinfo = t3lib_BEfunc::getRecord('pages',$id,'*',($perms_clause ? ' AND '.$perms_clause : ''));
                                if ($pageinfo['uid'] && $GLOBALS['BE_USER']->isInWebMount($id,$perms_clause))   {
                                        t3lib_BEfunc::workspaceOL('pages', $pageinfo);
-                                       t3lib_BEfunc::fixVersioningPid('pages', $pageinfo);
-                                       list($pageinfo['_thePath'],$pageinfo['_thePathFull']) = t3lib_BEfunc::getRecordPath(intval($pageinfo['uid']), $perms_clause, 15, 1000);
-                                       return $pageinfo;
+                                       if (is_array($pageinfo))        {
+                                               t3lib_BEfunc::fixVersioningPid('pages', $pageinfo);
+                                               list($pageinfo['_thePath'],$pageinfo['_thePathFull']) = t3lib_BEfunc::getRecordPath(intval($pageinfo['uid']), $perms_clause, 15, 1000);
+                                               return $pageinfo;
+                                       }
                                }
                        }
                }
@@ -1678,8 +1684,24 @@ class t3lib_BEfunc       {
                $parts[] = 'id='.$row['uid'];
                if ($row['alias'])      $parts[]=$LANG->sL($TCA['pages']['columns']['alias']['label']).' '.$row['alias'];
                if ($row['pid']<0)      $parts[] = 'v#1.'.$row['t3ver_id'];
-               if ($row['t3ver_state']==1)     $parts[] = 'PLH WSID#'.$row['t3ver_wsid'];
-               if ($row['t3ver_state']==-1)    $parts[] = 'New element!';
+
+               switch($row['t3ver_state'])     {
+                       case 1:
+                               $parts[] = 'PLH WSID#'.$row['t3ver_wsid'];
+                       break;
+                       case 2:
+                               $parts[] = 'Deleted element!';
+                       break;
+                       case 3:
+                               $parts[] = 'NEW LOCATION (PLH) WSID#'.$row['t3ver_wsid'];
+                       break;
+                       case 4:
+                               $parts[] = 'OLD LOCATION (PNT) WSID#'.$row['t3ver_wsid'];
+                       break;
+                       case -1:
+                               $parts[] = 'New element!';
+                       break;
+               }
 
                if ($row['doktype']=='3')       {
                        $parts[]=$LANG->sL($TCA['pages']['columns']['url']['label']).' '.$row['url'];
@@ -1752,8 +1774,23 @@ class t3lib_BEfunc       {
                                $out.=' - v#1.'.$row['t3ver_id'];
                        }
                        if ($GLOBALS['TCA'][$table]['ctrl']['versioningWS'])    {
-                               if ($row['t3ver_state']==1)     $out.= ' - PLH WSID#'.$row['t3ver_wsid'];
-                               if ($row['t3ver_state']==-1)    $out.= ' - New element!';
+                               switch($row['t3ver_state'])     {
+                                       case 1:
+                                               $out.= ' - PLH WSID#'.$row['t3ver_wsid'];
+                                       break;
+                                       case 2:
+                                               $out.= ' - Deleted element!';
+                                       break;
+                                       case 3:
+                                               $out.= ' - NEW LOCATION (PLH) WSID#'.$row['t3ver_wsid'];
+                                       break;
+                                       case 4:
+                                               $out.= ' - OLD LOCATION (PNT)  WSID#'.$row['t3ver_wsid'];
+                                       break;
+                                       case -1:
+                                               $out.= ' - New element!';
+                                       break;
+                               }
                        }
 
                        if ($ctrl['disabled'])  {               // Hidden ...
@@ -3370,18 +3407,47 @@ class t3lib_BEfunc      {
         * @return      void            (Passed by ref).
         * @see fixVersioningPid()
         */
-       function workspaceOL($table,&$row,$wsid=-99)    {
+       function workspaceOL($table,&$row,$wsid=-99,$unsetMovePointers=FALSE)   {
+               global $TCA;
+               
+               $previewMovePlaceholders = TRUE;                // If this is false the placeholder is shown raw in the backend. I don't know if this move can be useful for users to toggle. Technically it can help debugging...
 
                        // Initialize workspace ID:
                if ($wsid == -99)       $wsid = $GLOBALS['BE_USER']->workspace;
 
                        // Check if workspace is different from zero and record is set:
                if ($wsid!==0 && is_array($row))        {
+                       
+                               // Check if input record is a move-placeholder and if so, find the pointed-to live record:
+                       if ($previewMovePlaceholders)   {
+                               $orig_uid = $row['uid'];
+                               $orig_pid = $row['pid'];
+                               $movePldSwap = t3lib_BEfunc::movePlhOL($table,$row);
+       #                       if (!is_array($row)) return;
+                       }
+
                        $wsAlt = t3lib_BEfunc::getWorkspaceVersionOfRecord($wsid, $table, $row['uid'], implode(',',array_keys($row)));
 
                                // If version was found, swap the default record with that one.
                        if (is_array($wsAlt))   {
 
+                                       // Check if this is in move-state:
+                               if ($previewMovePlaceholders && !$movePldSwap && ($table=='pages' || (int)$TCA[$table]['ctrl']['versioningWS']>=2) && $unsetMovePointers)       {       // Only for WS ver 2... (moving)
+
+                                               // If t3ver_state is not found, then find it... (but we like best if it is here...)
+                                       if (!isset($wsAlt['t3ver_state']))      {
+                                               $stateRec = t3lib_BEfunc::getRecord($table,$wsAlt['uid'],'t3ver_state');
+                                               $state = $stateRec['t3ver_state'];
+                                       } else {
+                                               $state = $wsAlt['t3ver_state'];
+                                       }
+                                       if ((int)$state===4)    {
+                                                       // TODO: Same problem as frontend in versionOL(). See TODO point there.
+                                               $row = FALSE;
+                                               return;
+                                       }
+                               }
+
                                        // Always correct PID from -1 to what it should be:
                                if (isset($wsAlt['pid']))       {
                                        $wsAlt['_ORIG_pid'] = $wsAlt['pid'];    // Keep the old (-1) - indicates it was a version...
@@ -3406,9 +3472,51 @@ class t3lib_BEfunc       {
                                        // Changing input record to the workspace version alternative:
                                $row = $wsAlt;
                        }
+                       
+                               // If the original record was a move placeholder, the uid and pid of that is preserved here: 
+                       if ($movePldSwap)       {
+                               $row['_MOVE_PLH']=TRUE;
+                               $row['_MOVE_PLH_uid'] = $orig_uid;
+                               $row['_MOVE_PLH_pid'] = $orig_pid;
+                               $row['t3ver_state'] = 3;        // For display; To make the icon right for the placeholder vs. the original
+                       }
                }
        }
+       
+       /**
+        * Checks if record is a move-placeholder (t3ver_state==3) and if so it will set $row to be the pointed-to live record (and return TRUE)
+        *
+        * @param       string          Table name
+        * @param       array           Row (passed by reference) - must be online record!
+        * @return      boolean         True if overlay is made.
+        * @see t3lib_page::movePlhOl()
+        */
+       function movePlhOL($table,&$row)        {
+               global $TCA;
+
+               if ($table=='pages' || (int)$TCA[$table]['ctrl']['versioningWS']>=2)    {       // Only for WS ver 2... (moving)
+
+                               // If t3ver_move_id or t3ver_state is not found, then find it... (but we like best if it is here...)
+                       if (!isset($row['t3ver_move_id']) || !isset($row['t3ver_state']))       {
+                               $moveIDRec = t3lib_BEfunc::getRecord($table,$row['uid'],'t3ver_move_id,t3ver_state');
+                               $moveID = $moveIDRec['t3ver_move_id'];
+                               $state = $moveIDRec['t3ver_state'];
+                       } else {
+                               $moveID = $row['t3ver_move_id'];
+                               $state = $row['t3ver_state'];
+                       }
 
+                               // Find pointed-to record.
+                       if ((int)$state===3 && $moveID) {
+                               if ($origRow = t3lib_BEfunc::getRecord($table,$moveID, implode(',',array_keys($row))))  {
+                                       $row = $origRow;
+                                       return TRUE;
+                               }
+                       }
+               }
+               return FALSE;
+       }
+       
        /**
         * Select the workspace version of a record, if exists
         *
@@ -3487,14 +3595,14 @@ class t3lib_BEfunc      {
        }
 
        /**
-        * Will return where clause de-selecting new-versions from other workspaces.
+        * Will return where clause de-selecting new(/deleted)-versions from other workspaces.
         *
         * @param       string          Table name
         * @return      string          Where clause if applicable.
         */
        function versioningPlaceholderClause($table)    {
                if ($GLOBALS['BE_USER']->workspace!==0 && $GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['versioningWS'])   {
-                       return ' AND ('.$table.'.t3ver_state!=1 OR '.$table.'.t3ver_wsid='.intval($GLOBALS['BE_USER']->workspace).')';
+                       return ' AND ('.$table.'.t3ver_state<=0 OR '.$table.'.t3ver_wsid='.intval($GLOBALS['BE_USER']->workspace).')';
                }
        }
 
@@ -3549,7 +3657,36 @@ class t3lib_BEfunc       {
                }
        }
 
+       /**
+        * Returns move placeholder of online (live) version
+        *
+        * @param       string          Table name
+        * @param       integer         Record UID of online version
+        * @param       string          Field list, default is *
+        * @return      array           If found, the record, otherwise nothing.
+        */
+       function getMovePlaceholder($table,$uid,$fields='*')    {
+               global $TCA;
+               
+               $workspace = $GLOBALS['BE_USER']->workspace;
+               if ($workspace!==0 && $TCA[$table] && (int)$TCA[$table]['ctrl']['versioningWS']>=2)     {
 
+                               // Select workspace version of record:
+                       $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                               $fields,
+                               $table,
+                               'pid!=-1 AND
+                                t3ver_state=3 AND
+                                t3ver_move_id='.intval($uid).' AND
+                                t3ver_wsid='.intval($workspace).
+                                       t3lib_BEfunc::deleteClause($table)
+                       );
+
+                       if (is_array($rows[0])) return $rows[0];
+               }
+
+               return FALSE;
+       }
 
 
 
index bef3d78..47a2908 100755 (executable)
@@ -106,7 +106,7 @@ class t3lib_browseTree extends t3lib_treeView {
                        $this->MOUNTS = array_diff($this->MOUNTS,$hideList);
                }
 
-               $this->fieldArray = array_merge($this->fieldArray,array('doktype','php_tree_stop','t3ver_id','t3ver_state','t3ver_wsid','t3ver_swapmode'));
+               $this->fieldArray = array_merge($this->fieldArray,array('doktype','php_tree_stop','t3ver_id','t3ver_state','t3ver_wsid','t3ver_swapmode','t3ver_state','t3ver_move_id'));
                if (t3lib_extMgm::isLoaded('cms'))      {
                        $this->fieldArray = array_merge($this->fieldArray,array('hidden','starttime','endtime','fe_group','module','extendToSubpages', 'is_siteroot'));
                }
index 2b35b41..18fc035 100755 (executable)
@@ -123,11 +123,21 @@ class t3lib_iconWorks     {
                $doNotRenderUserGroupNumber = TRUE;     // If set, then the usergroup number will NOT be printed unto the icon. NOTICE. the icon is generated only if a default icon for groups is not found... So effectively this is ineffective...
 
                        // Shadow:
-               if ($TCA[$table]['ctrl']['versioningWS'] && (int)$row['t3ver_state']===1)       {
-                       return 'gfx/i/shadow_hide.png';
-               }
-               if ($TCA[$table]['ctrl']['versioningWS'] && (int)$row['t3ver_state']===2)       {
-                       return 'gfx/i/shadow_delete.png';
+               if ($TCA[$table]['ctrl']['versioningWS'])       {
+                       switch((int)$row['t3ver_state'])        {
+                               case 1:
+                                       return 'gfx/i/shadow_hide.png';
+                               break;
+                               case 2:
+                                       return 'gfx/i/shadow_delete.png';
+                               break;
+                               case 3:
+                                       return 'gfx/i/shadow_moveto_plh.png';
+                               break;
+                               case 4:
+                                       return 'gfx/i/shadow_moveto_pointer.png';
+                               break;
+                       }
                }
 
                        // First, find the icon file name. This can depend on configuration in TCA, field values and more:
index 4c2f5ac..0b22419 100755 (executable)
@@ -139,9 +139,9 @@ class t3lib_pageSelect {
                }
                $this->where_hid_del.= 'AND (pages.starttime<='.$GLOBALS['SIM_EXEC_TIME'].') AND (pages.endtime=0 OR pages.endtime>'.$GLOBALS['SIM_EXEC_TIME'].') ';
 
-                       // Filter out new place-holder pages in case we are NOT in a versioning preview (that means we are online!)
+                       // Filter out new/deleted place-holder pages in case we are NOT in a versioning preview (that means we are online!)
                if (!$this->versioningPreview)  {
-                       $this->where_hid_del.= ' AND NOT(pages.t3ver_state=1)';
+                       $this->where_hid_del.= ' AND NOT(pages.t3ver_state>0)';
                } else {
                                // For version previewing, make sure that enable-fields are not de-selecting hidden pages - we need versionOL() to unset them only if the overlay record instructs us to.
                        $this->versioningPreview_where_hid_del = $this->where_hid_del;  // Copy where_hid_del to other variable (used in relation to versionOL())
@@ -415,8 +415,7 @@ class t3lib_pageSelect {
                $output = Array();
                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, 'pages', 'pid='.intval($uid).$this->where_hid_del.$this->where_groupAccess.' '.$addWhere, '', $sortField);
                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
-                       $this->versionOL('pages',$row);
-
+                       $this->versionOL('pages',$row,TRUE);
                        if (is_array($row))     {
                                        // Keep mount point:
                                $origUid = $row['uid'];
@@ -954,7 +953,7 @@ class t3lib_pageSelect {
 
                                // Filter out new place-holder records in case we are NOT in a versioning preview (that means we are online!)
                        if ($ctrl['versioningWS'] && !$this->versioningPreview) {
-                               $query.=' AND '.$table.'.t3ver_state!=1';       // Shadow state for new items MUST be ignored!
+                               $query.=' AND '.$table.'.t3ver_state<=0';       // Shadow state for new items MUST be ignored!
                        }
 
                                // Enable fields:
@@ -1081,6 +1080,11 @@ class t3lib_pageSelect {
                                }
                        }
                }
+               
+                       // changing PID in case of moving pointer:
+               if ($movePlhRec = $this->getMovePlaceholder($table,$rr['uid'],'pid'))   {
+                       $rr['pid'] = $movePlhRec['pid'];
+               }
        }
 
        /**
@@ -1091,13 +1095,15 @@ class t3lib_pageSelect {
         *
         * @param       string          Table name
         * @param       array           Record array passed by reference. As minimum, the "uid", "pid" and "t3ver_state" fields must exist! The record MAY be set to FALSE in which case the calling function should act as if the record is forbidden to access!
+        * @param       boolean         If set, the $row is cleared in case it is a move-pointer. This is only for preview of moved records (to remove the record from the original location so it appears only in the new location)
         * @return      void            (Passed by ref).
         * @see fixVersioningPid(), t3lib_BEfunc::workspaceOL()
         */
-       function versionOL($table,&$row       {
+       function versionOL($table,&$row,$unsetMovePointers=FALSE)       {
                global $TCA;
-
+               
                if ($this->versioningPreview && is_array($row)) {
+                       $movePldSwap = $this->movePlhOL($table,$row);   // will overlay any movePlhOL found with the real record, which in turn will be overlaid with its workspace version if any. 
                        if ($wsAlt = $this->getWorkspaceVersionOfRecord($this->versioningWorkspaceId, $table, $row['uid'], implode(',',array_keys($row))))      {       // implode(',',array_keys($row)) = Using fields from original record to make sure no additional fields are selected. This is best for eg. getPageOverlay()
                                if (is_array($wsAlt))   {
 
@@ -1125,20 +1131,93 @@ class t3lib_pageSelect {
                                                // Changing input record to the workspace version alternative:
                                        $row = $wsAlt;
 
-                                               // Check if it is deleted in workspace:
-                                       if ((int)$row['t3ver_state']===2)       {
+                                               // Check if it is deleted/new
+                                       if ((int)$row['t3ver_state']===1 || (int)$row['t3ver_state']===2)       {
+                                               $row = FALSE;   // Unset record if it turned out to be deleted in workspace
+                                       }
+
+                                               // Check if move-pointer in workspace (unless if a move-placeholder is the reason why it appears!):
+                                               // You have to specifically set $unsetMovePointers in order to clear these because it is normally a display issue if it should be shown or not.
+                                       if ((int)$row['t3ver_state']===4 && !$movePldSwap && $unsetMovePointers)        {
                                                $row = FALSE;   // Unset record if it turned out to be deleted in workspace
                                        }
                                } else {
                                                // No version found, then check if t3ver_state =1 (online version is dummy-representation)
-                                       if ($wsAlt==-1 || (int)$row['t3ver_state']===1) {
+                                       if ($wsAlt==-1 || (int)$row['t3ver_state']>0)   {
                                                $row = FALSE;   // Unset record if it turned out to be "hidden"
                                        }
                                }
                        }
                }
        }
+       
+       /**
+        * Checks if record is a move-placeholder (t3ver_state==3) and if so it will set $row to be the pointed-to live record (and return TRUE)
+        * Used from versionOL
+        *
+        * @param       string          Table name
+        * @param       array           Row (passed by reference) - only online records...
+        * @return      boolean         True if overlay is made.
+        * @see t3lib_BEfunc::movePlhOl()
+        */
+       function movePlhOL($table,&$row)        {
+               global $TCA;
 
+               if (($table=='pages' || (int)$TCA[$table]['ctrl']['versioningWS']>=2) && (int)$row['t3ver_state']===3)  {       // Only for WS ver 2... (moving)
+
+                               // If t3ver_move_id is not found, then find it... (but we like best if it is here...)
+                       if (!isset($row['t3ver_move_id']))      {
+                               $moveIDRec = $this->getRawRecord($table,$row['uid'],'t3ver_move_id',TRUE);
+                               $moveID = $moveIDRec['t3ver_move_id'];
+                       } else {
+                               $moveID = $row['t3ver_move_id'];
+                       }
+               
+                               // Find pointed-to record.
+                       if ($moveID)    {
+                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(implode(',',array_keys($row)), $table, 'uid='.intval($moveID).$this->enableFields($table));
+                               if ($origRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))     {
+                                       $row = $origRow;
+                                       return TRUE;
+                               }
+                       }
+               }
+               return FALSE;
+       }
+
+       /**
+        * Returns move placeholder of online (live) version
+        *
+        * @param       string          Table name
+        * @param       integer         Record UID of online version
+        * @param       string          Field list, default is *
+        * @return      array           If found, the record, otherwise nothing.
+        * @see t3lib_BEfunc::getMovePlaceholder()
+        */
+       function getMovePlaceholder($table,$uid,$fields='*')    {
+               global $TCA;
+
+               if ($this->versioningPreview)   {
+                       $workspace = (int)$this->versioningWorkspaceId;
+                       if (($table=='pages' || (int)$TCA[$table]['ctrl']['versioningWS']>=2) && $workspace!==0)        {
+
+                                       // Select workspace version of record:
+                               $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                                       $fields,
+                                       $table,
+                                       'pid!=-1 AND
+                                        t3ver_state=3 AND
+                                        t3ver_move_id='.intval($uid).' AND
+                                        t3ver_wsid='.intval($workspace).
+                                               $this->deleteClause($table)
+                               );
+
+                               if (is_array($rows[0])) return $rows[0];
+                       }
+               }
+               return FALSE;
+       }
+       
        /**
         * Select the version of a record for a workspace
         *
index 4b5632b..56f98b5 100755 (executable)
@@ -424,8 +424,10 @@ class t3lib_positionMap {
                        $lines[$kk][]=$this->insertPositionIcon('',$vv,$kk,$moveUid,$pid);
                        while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))               {
                                t3lib_BEfunc::workspaceOL('tt_content',$row);
-                               $lines[$kk][]=$this->wrapRecordHeader($this->getRecordHeader($row),$row);
-                               $lines[$kk][]=$this->insertPositionIcon($row,$vv,$kk,$moveUid,$pid);
+                               if (is_array($row))     {
+                                       $lines[$kk][]=$this->wrapRecordHeader($this->getRecordHeader($row),$row);
+                                       $lines[$kk][]=$this->insertPositionIcon($row,$vv,$kk,$moveUid,$pid);
+                               }
                        }
                        $GLOBALS['TYPO3_DB']->sql_free_result($res);
                }
index fd54ffe..51c47e3 100755 (executable)
@@ -4184,20 +4184,23 @@ class t3lib_TCEforms    {
                        // Traverse the selected rows to add them:
                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
                        t3lib_BEfunc::workspaceOL($f_table, $row);
-                               // Prepare the icon if available:
-                       if ($iField && $iPath && $row[$iField]) {
-                               $iParts = t3lib_div::trimExplode(',',$row[$iField],1);
-                               $icon = '../'.$iPath.'/'.trim($iParts[0]);
-                       } elseif (t3lib_div::inList('singlebox,checkbox',$fieldValue['config']['renderMode'])) {
-                               $icon = '../'.TYPO3_mainDir.t3lib_iconWorks::skinImg($this->backPath,t3lib_iconWorks::getIcon($f_table, $row),'',1);
-                       } else $icon = '';
-
-                               // Add the item:
-                       $items[] = array(
-                               $lPrefix.strip_tags(t3lib_BEfunc::getRecordTitle($f_table,$row)),
-                               $uidPre.$row['uid'],
-                               $icon
-                       );
+                       
+                       if (is_array($row))     {
+                                       // Prepare the icon if available:
+                               if ($iField && $iPath && $row[$iField]) {
+                                       $iParts = t3lib_div::trimExplode(',',$row[$iField],1);
+                                       $icon = '../'.$iPath.'/'.trim($iParts[0]);
+                               } elseif (t3lib_div::inList('singlebox,checkbox',$fieldValue['config']['renderMode'])) {
+                                       $icon = '../'.TYPO3_mainDir.t3lib_iconWorks::skinImg($this->backPath,t3lib_iconWorks::getIcon($f_table, $row),'',1);
+                               } else $icon = '';
+
+                                       // Add the item:
+                               $items[] = array(
+                                       $lPrefix.strip_tags(t3lib_BEfunc::getRecordTitle($f_table,$row)),
+                                       $uidPre.$row['uid'],
+                                       $icon
+                               );
+                       }
                }
                return $items;
        }
index e1a3bdd..93a74ea 100755 (executable)
@@ -787,9 +787,9 @@ class t3lib_TCEmain {
                                                                                                        foreach ($origIdArray as $origId => $newId) {
                                                                                                                $this->uploadedFileArray[$origTable][$newId] = $this->uploadedFileArray[$origTable][$origId];
                                                                                                                $this->autoVersionIdMap[$origTable][$origId] = $newId;
-                                                                                                               $this->RTEmagic_copyIndex = t3lib_div::array_merge_recursive_overrule($this->RTEmagic_copyIndex, $tce->RTEmagic_copyIndex);             // See where RTEmagic_copyIndex is used inside fillInFieldArray() for more information...
                                                                                                        }
                                                                                                }
+                                                                                               $this->RTEmagic_copyIndex = t3lib_div::array_merge_recursive_overrule($this->RTEmagic_copyIndex, $tce->RTEmagic_copyIndex);             // See where RTEmagic_copyIndex is used inside fillInFieldArray() for more information...
 
                                                                                                        // Update registerDBList, that holds the copied relations to child records:
                                                                                                $registerDBList = array_merge($registerDBList, $tce->registerDBList);
@@ -931,7 +931,7 @@ class t3lib_TCEmain {
 
                t3lib_div::loadTCA($table);
                if ($liveRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$id,'*'))    {
-                       if ((int)$liveRec['t3ver_state']===1)   {
+                       if ((int)$liveRec['t3ver_state']>0)     {
                                $justStoredRecord = t3lib_BEfunc::getRecord($table,$id);
                                $newRecord = array();
 
@@ -2349,7 +2349,7 @@ class t3lib_TCEmain       {
                                $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
                        }
                }
-
+#debug($this->cmdmap);
                        // Traverse command map:
                reset($this->cmdmap);
                while(list($table,) = each($this->cmdmap))      {
@@ -2428,6 +2428,9 @@ class t3lib_TCEmain       {
                                                                        case 'clearWSID':
                                                                                $this->version_clearWSID($table,$id);
                                                                        break;
+                                                                       case 'flush':
+                                                                               $this->version_clearWSID($table,$id,TRUE);
+                                                                       break;
                                                                        case 'setStage':
                                                                                $idList = $elementList[$table] = t3lib_div::trimExplode(',',$id,1);
                                                                                $setStageMode = $GLOBALS['BE_USER']->getTSConfigVal('options.workspaces.changeStageMode');
@@ -3144,30 +3147,17 @@ class t3lib_TCEmain     {
         * @return      void
         */
        function moveRecord($table,$uid,$destPid)       {
-               global $TCA, $TYPO3_CONF_VARS;
+               global $TCA;
 
                if ($TCA[$table])       {
 
-                               // Prepare user defined objects (if any) for hooks which extend this function:
-                       $hookObjectsArr = array();
-                       if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['moveRecordClass'])) {
-                               foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['moveRecordClass'] as $classRef) {
-                                       $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
-                               }
-                       }
-
                                // In case the record to be moved turns out to be an offline version, we have to find the live version and work on that one (this case happens for pages with "branch" versioning type)
                        if ($lookForLiveVersion = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))      {
                                $uid = $lookForLiveVersion['uid'];
                        }
 
-                               // Get workspace version of the source record, if any:
-                       $WSversion = t3lib_BEfunc::getWorkspaceVersionOfRecord($this->BE_USER->workspace, $table, $uid, 'uid,t3ver_oid');
-
                                // Initialize:
-                       $sortRow = $TCA[$table]['ctrl']['sortby'];
                        $destPid = intval($destPid);
-                       $origDestPid = $destPid;
 
                        $propArr = $this->getRecordProperties($table,$uid);     // Get this before we change the pid (for logging)
                        $moveRec = $this->getRecordProperties($table,$uid,TRUE);
@@ -3188,143 +3178,249 @@ class t3lib_TCEmain   {
                                $mayInsertAccess = $this->checkRecordUpdateAccess($table,$uid);
                        }
 
-                               // Check workspace permissions:
-                       $workspaceAccessBlocked = array();
-                       $recIsNewVersion = !strcmp($moveRec['_ORIG_pid'],'') && (int)$moveRec['t3ver_state']==1;        // Element was an online version AND it was in "New state" so it can be moved...
-                       $destRes = $this->BE_USER->workspaceAllowLiveRecordsInPID($resolvedPid,$table);
-                               // Workspace source check:
-                       if ($errorCode = $this->BE_USER->workspaceCannotEditRecord($table, $WSversion['uid'] ? $WSversion['uid'] : $uid))       {
-                               $workspaceAccessBlocked['src1']='Record could not be edited in workspace: '.$errorCode.' ';
-                       } else {
-                               if (!$recIsNewVersion && $this->BE_USER->workspaceAllowLiveRecordsInPID($moveRec['pid'],$table)<=0)     {
-                                       $workspaceAccessBlocked['src2']='Could not remove record from table "'.$table.'" from its page "'.$moveRec['pid'].'" ';
+                               // If moving is allowed, begin the processing:
+                       if ($mayMoveAccess)     {
+                               if ($mayInsertAccess)   {
+
+                                       if ($this->BE_USER->workspace!==0)      {       // Draft workspace...:
+                                                       // Get workspace version of the source record, if any:
+                                               $WSversion = t3lib_BEfunc::getWorkspaceVersionOfRecord($this->BE_USER->workspace, $table, $uid, 'uid,t3ver_oid');
+
+                                                       // If no version exists and versioningWS is in version 2, a new placeholder is made automatically:
+                                               if (!$WSversion['uid'] && (int)$TCA[$table]['ctrl']['versioningWS']>=2 && (int)$moveRec['t3ver_state']!=3)      {
+                                                       $this->versionizeRecord($table,$uid,'Placeholder version for moving record');
+                                                       $WSversion = t3lib_BEfunc::getWorkspaceVersionOfRecord($this->BE_USER->workspace, $table, $uid, 'uid,t3ver_oid');       // Will not create new versions in live workspace though...
+                                               }
+
+                                                       // Check workspace permissions:
+                                               $workspaceAccessBlocked = array();
+                                               $recIsNewVersion = (int)$moveRec['t3ver_state']>0;      // Element was in "New/Deleted/Moved" so it can be moved...
+                                               $destRes = $this->BE_USER->workspaceAllowLiveRecordsInPID($resolvedPid,$table);
+                                               $canMoveRecord = $recIsNewVersion || (int)$TCA[$table]['ctrl']['versioningWS']>=2;
+
+                                                       // Workspace source check:
+                                               if (!$recIsNewVersion)  {
+                                                       if ($errorCode = $this->BE_USER->workspaceCannotEditRecord($table, $WSversion['uid'] ? $WSversion['uid'] : $uid))       {
+                                                               $workspaceAccessBlocked['src1']='Record could not be edited in workspace: '.$errorCode.' ';
+                                                       } else {
+                                                               if (!$canMoveRecord && $this->BE_USER->workspaceAllowLiveRecordsInPID($moveRec['pid'],$table)<=0)       {
+                                                                       $workspaceAccessBlocked['src2']='Could not remove record from table "'.$table.'" from its page "'.$moveRec['pid'].'" ';
+                                                               }
+                                                       }
+                                               }
+                                       
+                                                       // Workspace destination check:
+                                               if (!($destRes>0 || ($canMoveRecord && !$destRes)))     {       // All records can be inserted if $destRes is greater than zero. Only new versions can be inserted if $destRes is false. NO RECORDS can be inserted if $destRes is negative which indicates a stage not allowed for use. If "versioningWS" is version 2, moving can take place of versions.
+                                                       $workspaceAccessBlocked['dest1']='Could not insert record from table "'.$table.'" in destination PID "'.$resolvedPid.'" ';
+                                               } elseif ($destRes==1 && $WSversion['uid'])     {
+                                                       $workspaceAccessBlocked['dest2']='Could not insert other versions in destination PID ';
+                                               }
+
+                                               if (!count($workspaceAccessBlocked))    {
+                                                       if ($WSversion['uid'] && !$recIsNewVersion && (int)$TCA[$table]['ctrl']['versioningWS']>=2)     { // If the move operation is done on a versioned record, which is NOT new/deletd placeholder and versioningWS is in version 2, then...
+                                                               $this->moveRecord_wsPlaceholders($table,$uid,$destPid,$WSversion['uid']);
+                                                       } else {
+                                                               $this->moveRecord_raw($table,$uid,$destPid);
+                                                       }
+                                               } else {
+                                                       $this->newlog("Move attempt failed due to workspace restrictions: ".implode(' // ',$workspaceAccessBlocked),1);
+                                               }
+                                       } else {        // Live workspace - move it!
+                                               $this->moveRecord_raw($table,$uid,$destPid);
+                                       }
+                               } else {
+                                       $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) without having permissions to insert",14,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
                                }
+                       } else {
+                               $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) without having permissions to do so",14,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
                        }
-                               // Workspace destination check:
-                       if (!($destRes>0 || ($recIsNewVersion && !$destRes)))   {       // All records can be inserted if $destRes is greater than zero. Only new versions can be inserted if $destRes is false. NO RECORDS can be inserted if $destRes is negative which indicates a stage not allowed for use.
-                               $workspaceAccessBlocked['dest1']='Could not insert record from table "'.$table.'" in destination PID "'.$resolvedPid.'" ';
-                       } elseif ($destRes==1 && $WSversion['uid'])     {
-                               $workspaceAccessBlocked['dest2']='Could not insert other versions in destination PID ';
-                       }
+               }
+       }
 
-                               // Checking if the pid is negative, but no sorting row is defined. In that case, find the correct pid. Basically this check make the error message 4-13 meaning less... But you can always remove this check if you prefer the error instead of a no-good action (which is to move the record to its own page...)
-                       if (($destPid<0 && !$sortRow) || $destPid>=0)   {       // $destPid>=0 because we must correct pid in case of versioning "page" types.
-                               $destPid = $resolvedPid;
+       /**
+        * Creates a move placeholder for workspaces.
+        * USE ONLY INTERNALLY 
+        * Moving placeholder: Can be done because the system sees it as a placeholder for NEW elements like t3ver_state=1
+        * Moving original: Will either create the placeholder if it doesn't exist or move existing placeholder in workspace.
+        *
+        * @param       string          Table name to move
+        * @param       integer         Record uid to move (online record)
+        * @param       integer         Position to move to: $destPid: >=0 then it points to a page-id on which to insert the record (as the first element). <0 then it points to a uid from its own table after which to insert it (works if
+        * @param       integer         UID of offline version of online record 
+        * @return      void
+        * @see moveRecord()
+        */
+       function moveRecord_wsPlaceholders($table,$uid,$destPid,$wsUid) {
+               global $TCA;
+
+               if ($plh = t3lib_BEfunc::getMovePlaceholder($table,$uid,'uid')) {
+                               // If already a placeholder exists, move it:
+                       $this->moveRecord_raw($table,$plh['uid'],$destPid);
+               } else {
+                               // First, we create a placeholder record in the Live workspace that represents the position to where the record is eventually moved to.
+                       $newVersion_placeholderFieldArray = array();
+                       if ($TCA[$table]['ctrl']['crdate'])     {
+                               $newVersion_placeholderFieldArray[$TCA[$table]['ctrl']['crdate']] = time();
+                       }
+                       if ($TCA[$table]['ctrl']['cruser_id'])  {
+                               $newVersion_placeholderFieldArray[$TCA[$table]['ctrl']['cruser_id']] = $this->userid;
                        }
+                       if ($TCA[$table]['ctrl']['tstamp'] && count($fieldArray))       {
+                               $newVersion_placeholderFieldArray[$TCA[$table]['ctrl']['tstamp']] = time();
+                       }
+
+                       $newVersion_placeholderFieldArray['t3ver_label'] = 'MOVE-TO PLACEHOLDER for #'.$uid;
+                       $newVersion_placeholderFieldArray['t3ver_move_id'] = $uid;
+                       $newVersion_placeholderFieldArray['t3ver_state'] = 3;   // Setting placeholder state value for temporary record
+                       $newVersion_placeholderFieldArray['t3ver_wsid'] = $this->BE_USER->workspace;    // Setting workspace - only so display of place holders can filter out those from other workspaces.
+                       $newVersion_placeholderFieldArray[$TCA[$table]['ctrl']['label']] = '[MOVE-TO PLACEHOLDER for #'.$uid.', WS#'.$this->BE_USER->workspace.']';
 
-                               // Timestamp field:
+                       $newVersion_placeholderFieldArray['pid'] = 0;   // Initially, create at root level.
+                       $id = 'NEW_MOVE_PLH';
+                       $this->insertDB($table,$id,$newVersion_placeholderFieldArray,FALSE);    // Saving placeholder as 'original'
+
+                               // Move the new placeholder from temporary root-level to location:
+                       $this->moveRecord_raw($table,$this->substNEWwithIDs[$id],$destPid);
+
+                               // Move the workspace-version of the original to be the version of the move-to-placeholder:
                        $updateFields = array();
-                       if ($TCA[$table]['ctrl']['tstamp'])     {
-                               $updateFields[$TCA[$table]['ctrl']['tstamp']] = time();
-                       }
+                       $updateFields['t3ver_state'] = 4;       // Setting placeholder state value for version (so it can know it is currently a new version...)
+                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($wsUid), $updateFields);
+               }
+       }
 
-                                       // If moving is allowed, begin the processing:
-                       if (!count($workspaceAccessBlocked))    {
-                               if ($mayMoveAccess)     {
-                                       if ($destPid>=0)        {       // insert as first element on page (where uid = $destPid)
-                                               if ($mayInsertAccess)   {
-                                                       if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid)) {
-                                                               $this->clear_cache($table,$uid);        // clear cache before moving
+       /**
+        * Moves a record without checking security of any sort.
+        * USE ONLY INTERNALLY 
+        *
+        * @param       string          Table name to move
+        * @param       integer         Record uid to move
+        * @param       integer         Position to move to: $destPid: >=0 then it points to a page-id on which to insert the record (as the first element). <0 then it points to a uid from its own table after which to insert it (works if
+        * @return      void
+        * @see moveRecord()
+        */
+       function moveRecord_raw($table,$uid,$destPid)   {
+               global $TCA, $TYPO3_CONF_VARS;
 
-                                                               $updateFields['pid'] = $destPid;        // Setting PID
+               $sortRow = $TCA[$table]['ctrl']['sortby'];
+               $origDestPid = $destPid;
+               $resolvedPid = $this->resolvePid($table,$destPid);      // This is the actual pid of the moving to destination
 
-                                                                       // table is sorted by 'sortby'
-                                                               if ($sortRow)   {
-                                                                       $sortNumber = $this->getSortNumber($table,$uid,$destPid);
-                                                                       $updateFields[$sortRow] = $sortNumber;
-                                                               }
+                       // Checking if the pid is negative, but no sorting row is defined. In that case, find the correct pid. Basically this check make the error message 4-13 meaning less... But you can always remove this check if you prefer the error instead of a no-good action (which is to move the record to its own page...)
+               if (($destPid<0 && !$sortRow) || $destPid>=0)   {       // $destPid>=0 because we must correct pid in case of versioning "page" types.
+                       $destPid = $resolvedPid;
+               }
 
-                                                                       // check for child records that have also to be moved
-                                                               $this->moveRecord_procFields($table,$uid,$destPid);
-                                                                       // Create query for update:
-                                                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
+               $propArr = $this->getRecordProperties($table,$uid);     // Get this before we change the pid (for logging)
+               $moveRec = $this->getRecordProperties($table,$uid,TRUE);
 
-                                                                       // Call post processing hooks:
-                                                               foreach($hookObjectsArr as $hookObj) {
-                                                                       if (method_exists($hookObj, 'moveRecord_firstElementPostProcess')) {
-                                                                               $hookObj->moveRecord_firstElementPostProcess($table, $uid, $destPid, $moveRec, $updateFields, $this);
-                                                                       }
-                                                               }
+                       // Prepare user defined objects (if any) for hooks which extend this function:
+               $hookObjectsArr = array();
+               if (is_array ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['moveRecordClass'])) {
+                       foreach ($TYPO3_CONF_VARS['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['moveRecordClass'] as $classRef) {
+                               $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
+                       }
+               }
+               
+                       // Timestamp field:
+               $updateFields = array();
+               if ($TCA[$table]['ctrl']['tstamp'])     {
+                       $updateFields[$TCA[$table]['ctrl']['tstamp']] = time();
+               }
 
-                                                                       // Logging...
-                                                               $newPropArr = $this->getRecordProperties($table,$uid);
-                                                               $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
-                                                               $newpagePropArr = $this->getRecordProperties('pages',$destPid);
+               if ($destPid>=0)        {       // insert as first element on page (where uid = $destPid)
+                       if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid)) {
+                               $this->clear_cache($table,$uid);        // clear cache before moving
 
-                                                               if ($destPid!=$propArr['pid'])  {
-                                                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);     // Logged to old page
-                                                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);     // Logged to new page
-                                                               } else {
-                                                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);       // Logged to new page
-                                                               }
-                                                               $this->clear_cache($table,$uid);        // clear cache after moving
-                                                               $this->fixUniqueInPid($table,$uid);
-                                                                       // fixCopyAfterDuplFields
-                                                               if ($origDestPid<0)     {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);}       // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before.
-                                                       } else {
-                                                               $destPropArr = $this->getRecordProperties('pages',$destPid);
-                                                               $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
-                                                       }
-                                               }
-                                       } else {        // Put after another record
-                                               if ($sortRow)   {       // table is being sorted
-                                                       $sortInfo = $this->getSortNumber($table,$uid,$destPid);
-                                                       $destPid = $sortInfo['pid'];    // Setting the destPid to the new pid of the record.
-                                                       if (is_array($sortInfo))        {       // If not an array, there was an error (which is already logged)
-                                                               if ($mayInsertAccess)   {
-                                                                       if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid)) {
-                                                                               $this->clear_cache($table,$uid);        // clear cache before moving
-
-                                                                                       // We now update the pid and sortnumber
-                                                                               $updateFields['pid'] = $destPid;
-                                                                               $updateFields[$sortRow] = $sortInfo['sortNumber'];
-
-                                                                                       // check for child records that have also to be moved
-                                                                               $this->moveRecord_procFields($table,$uid,$destPid);
-                                                                                       // Create query for update:
-                                                                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
-
-                                                                                       // Call post processing hooks:
-                                                                               foreach($hookObjectsArr as $hookObj) {
-                                                                                       if (method_exists($hookObj, 'moveRecord_afterAnotherElementPostProcess')) {
-                                                                                               $hookObj->moveRecord_afterAnotherElementPostProcess($table, $uid, $destPid, $origDestPid, $moveRec, $updateFields, $this);
-                                                                                       }
-                                                                               }
+                               $updateFields['pid'] = $destPid;        // Setting PID
 
-                                                                                       // Logging...
-                                                                               $newPropArr = $this->getRecordProperties($table,$uid);
-                                                                               $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
-                                                                               if ($destPid!=$propArr['pid'])  {
-                                                                                       $newpagePropArr = $this->getRecordProperties('pages',$destPid);
-                                                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);    // Logged to old page
-                                                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);    // Logged to new page
-                                                                               } else {
-                                                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);      // Logged to new page
-                                                                               }
+                                       // table is sorted by 'sortby'
+                               if ($sortRow)   {
+                                       $sortNumber = $this->getSortNumber($table,$uid,$destPid);
+                                       $updateFields[$sortRow] = $sortNumber;
+                               }
 
-                                                                                       // clear cache after moving
-                                                                               $this->clear_cache($table,$uid);
+                                       // check for child records that have also to be moved
+                               $this->moveRecord_procFields($table,$uid,$destPid);
+                                       // Create query for update:
+                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
 
-                                                                                       // fixUniqueInPid
-                                                                               $this->fixUniqueInPid($table,$uid);
+                                       // Call post processing hooks:
+                               foreach($hookObjectsArr as $hookObj) {
+                                       if (method_exists($hookObj, 'moveRecord_firstElementPostProcess')) {
+                                               $hookObj->moveRecord_firstElementPostProcess($table, $uid, $destPid, $moveRec, $updateFields, $this);
+                                       }
+                               }
 
-                                                                                       // fixCopyAfterDuplFields
-                                                                               if ($origDestPid<0)     {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);}
-                                                                       } else {
-                                                                               $destPropArr = $this->getRecordProperties('pages',$destPid);
-                                                                               $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
-                                                                       }
-                                                               }
+                                       // Logging...
+                               $newPropArr = $this->getRecordProperties($table,$uid);
+                               $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
+                               $newpagePropArr = $this->getRecordProperties('pages',$destPid);
+
+                               if ($destPid!=$propArr['pid'])  {
+                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);     // Logged to old page
+                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);     // Logged to new page
+                               } else {
+                                       $this->log($table,$uid,4,$destPid,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);       // Logged to new page
+                               }
+                               $this->clear_cache($table,$uid);        // clear cache after moving
+                               $this->fixUniqueInPid($table,$uid);
+                                       // fixCopyAfterDuplFields
+                               if ($origDestPid<0)     {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);}       // origDestPid is retrieve before it may possibly be converted to resolvePid if the table is not sorted anyway. In this way, copying records to after another records which are not sorted still lets you use this function in order to copy fields from the one before.
+                       } else {
+                               $destPropArr = $this->getRecordProperties('pages',$destPid);
+                               $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
+                       }
+               } else {        // Put after another record
+                       if ($sortRow)   {       // table is being sorted
+                               $sortInfo = $this->getSortNumber($table,$uid,$destPid);
+                               $destPid = $sortInfo['pid'];    // Setting the destPid to the new pid of the record.
+                               if (is_array($sortInfo))        {       // If not an array, there was an error (which is already logged)
+                                       if ($table!='pages' || $this->destNotInsideSelf($destPid,$uid)) {
+                                               $this->clear_cache($table,$uid);        // clear cache before moving
+
+                                                       // We now update the pid and sortnumber
+                                               $updateFields['pid'] = $destPid;
+                                               $updateFields[$sortRow] = $sortInfo['sortNumber'];
+
+                                                       // check for child records that have also to be moved
+                                               $this->moveRecord_procFields($table,$uid,$destPid);
+                                                       // Create query for update:
+                                               $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields);
+
+                                                       // Call post processing hooks:
+                                               foreach($hookObjectsArr as $hookObj) {
+                                                       if (method_exists($hookObj, 'moveRecord_afterAnotherElementPostProcess')) {
+                                                               $hookObj->moveRecord_afterAnotherElementPostProcess($table, $uid, $destPid, $origDestPid, $moveRec, $updateFields, $this);
                                                        }
+                                               }
+
+                                                       // Logging...
+                                               $newPropArr = $this->getRecordProperties($table,$uid);
+                                               $oldpagePropArr = $this->getRecordProperties('pages',$propArr['pid']);
+                                               if ($destPid!=$propArr['pid'])  {
+                                                       $newpagePropArr = $this->getRecordProperties('pages',$destPid);
+                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) to page '%s' (%s)",2,array($propArr['header'],$table.':'.$uid, $newpagePropArr['header'], $newPropArr['pid']),$propArr['pid']);    // Logged to old page
+                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) from page '%s' (%s)",3,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);    // Logged to new page
                                                } else {
-                                                       $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.",13,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
+                                                       $this->log($table,$uid,4,0,0,"Moved record '%s' (%s) on page '%s' (%s)",4,array($propArr['header'],$table.':'.$uid, $oldpagePropArr['header'], $propArr['pid']),$destPid);      // Logged to new page
                                                }
+
+                                                       // clear cache after moving
+                                               $this->clear_cache($table,$uid);
+
+                                                       // fixUniqueInPid
+                                               $this->fixUniqueInPid($table,$uid);
+
+                                                       // fixCopyAfterDuplFields
+                                               if ($origDestPid<0)     {$this->fixCopyAfterDuplFields($table,$uid,abs($origDestPid),1);}
+                                       } else {
+                                               $destPropArr = $this->getRecordProperties('pages',$destPid);
+                                               $this->log($table,$uid,4,0,1,"Attempt to move page '%s' (%s) to inside of its own rootline (at page '%s' (%s))",10,array($propArr['header'],$uid, $destPropArr['header'], $destPid),$propArr['pid']);
                                        }
-                               } else {
-                                       $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) without having permissions to do so",14,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
                                }
                        } else {
-                               $this->newlog("Move attempt failed due to workspace restrictions: ".implode(' / ',$workspaceAccessBlocked),1);
+                               $this->log($table,$uid,4,0,1,"Attempt to move record '%s' (%s) to after another record, although the table has no sorting row.",13,array($propArr['header'],$table.':'.$uid),$propArr['event_pid']);
                        }
                }
        }
@@ -3336,14 +3432,16 @@ class t3lib_TCEmain     {
         * @param       string          $table: Record Table
         * @param       string          $uid: Record UID
         * @param       string          $destPid: Position to move to
-        * @return      [type]          ...
+        * @return      void
         */
        function moveRecord_procFields($table,$uid,$destPid) {
                t3lib_div::loadTCA($table);
                $conf = $GLOBALS['TCA'][$table]['columns'];
                $row = t3lib_BEfunc::getRecordWSOL($table,$uid);
-               foreach ($row as $field => $value) {
-                       $this->moveRecord_procBasedOnFieldType($table,$uid,$destPid,$field,$value,$conf[$field]['config']);
+               if (is_array($row))     {
+                       foreach ($row as $field => $value) {
+                               $this->moveRecord_procBasedOnFieldType($table,$uid,$destPid,$field,$value,$conf[$field]['config']);
+                       }
                }
        }
 
@@ -3526,9 +3624,9 @@ class t3lib_TCEmain       {
                                        if ($this->BE_USER->workspace==0 || (int)$delRec['t3ver_wsid']==$this->BE_USER->workspace)      {       // In Live workspace, delete any. In other workspaces there must be match.
                                                $liveRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$id,'uid,t3ver_state');
 
-                                               if ($delRec['t3ver_wsid']==0 || (int)$liveRec['t3ver_state']!==1)       {       // Delete those in WS 0 + if their live records state was not "Placeholder".
+                                               if ($delRec['t3ver_wsid']==0 || (int)$liveRec['t3ver_state']<=0)        {       // Delete those in WS 0 + if their live records state was not "Placeholder".
                                                        $this->deleteEl($table, $id);
-                                               } else {        // If live record was placeholder, rather clear it from workspace (because it clears both version and placeholder).
+                                               } else {        // If live record was placeholder (new/deleted), rather clear it from workspace (because it clears both version and placeholder).
                                                        $this->version_clearWSID($table,$id);
                                                }
                                        } else $this->newlog('Tried to delete record from another workspace',1);
@@ -3537,8 +3635,18 @@ class t3lib_TCEmain      {
                                if ($res>0)     {
                                        $this->deleteEl($table, $id);
                                } else $this->newlog('Stage of root point did not allow for deletion',1);
+                       } elseif ((int)$delRec['t3ver_state']===3) {    // Placeholders for moving operations are deletable directly.
+                               
+                                       // Get record which its a placeholder for and reset the t3ver_state of that:
+                               if ($wsRec = t3lib_BEfunc::getWorkspaceVersionOfRecord($delRec['t3ver_wsid'], $table, $delRec['t3ver_move_id'], 'uid')) {
+                                               // clear the state flag of the workspace version of the 
+                                       $updateFields = array();
+                                       $updateFields['t3ver_state'] = 0;       // Setting placeholder state value for version (so it can know it is currently a new version...)
+                                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($wsRec['uid']), $updateFields);
+                               }
+                               $this->deleteEl($table, $id);
                        } else {
-                               // Otherwise, try to delete by versionization:
+                               // Otherwise, try to delete by versioning:
                                $this->versionizeRecord($table,$id,'DELETED!',TRUE);
                        }
                }
@@ -3942,57 +4050,59 @@ class t3lib_TCEmain     {
                                if ($this->BE_USER->workspaceVersioningTypeAccess($versionizeTree))     {
 
                                                // Select main record:
-                                       $row = $this->recordInfo($table,$id,'pid,t3ver_id');
+                                       $row = $this->recordInfo($table,$id,'pid,t3ver_id,t3ver_state');
                                        if (is_array($row))     {
                                                if ($row['pid']>=0)     {       // record must be online record
-                                                       if (!$delete || !$this->cannotDeleteRecord($table,$id)) {
-
-                                                                       // Look for next version number:
-                                                               $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
-                                                                       't3ver_id',
-                                                                       $table,
-                                                                       '(t3ver_oid='.$id.' OR uid='.$id.')'.$this->deleteClause($table),
-                                                                       '',
-                                                                       't3ver_id DESC',
-                                                                       '1'
-                                                               );
-                                                               list($highestVerNumber) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
-                                                               $GLOBALS['TYPO3_DB']->sql_free_result($res);
-
-                                                                       // Look for version number of the current:
-                                                               $subVer = $row['t3ver_id'].'.'.($highestVerNumber+1);
-
-                                                                       // Set up the values to override when making a raw-copy:
-                                                               $overrideArray = array(
-                                                                       't3ver_id' => $highestVerNumber+1,
-                                                                       't3ver_oid' => $id,
-                                                                       't3ver_label' => ($label ? $label : $subVer.' / '.date('d-m-Y H:m:s')),
-                                                                       't3ver_wsid' => $this->BE_USER->workspace,
-                                                                       't3ver_state' => $delete ? 2 : 0,
-                                                                       't3ver_count' => 0,
-                                                                       't3ver_stage' => 0,
-                                                                       't3ver_tstamp' => 0
-                                                               );
-                                                               if ($TCA[$table]['ctrl']['editlock'])   {
-                                                                       $overrideArray[$TCA[$table]['ctrl']['editlock']] = 0;
-                                                               }
-                                                               if ($table==='pages')   {
-                                                                       $overrideArray['t3ver_swapmode'] = $versionizeTree;
-                                                               }
+                                                       if ($row['t3ver_state']!=3)     {       // record must not be placeholder for moving.
+                                                               if (!$delete || !$this->cannotDeleteRecord($table,$id)) {
 
-                                                                       // Checking if the record already has a version in the current workspace of the backend user
-                                                               $workspaceCheck = TRUE;
-                                                               if ($this->BE_USER->workspace!==0)      {
-                                                                               // Look for version already in workspace:
-                                                                       $workspaceCheck = t3lib_BEfunc::getWorkspaceVersionOfRecord($this->BE_USER->workspace,$table,$id,'uid') ? FALSE : TRUE;
-                                                               }
+                                                                               // Look for next version number:
+                                                                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+                                                                               't3ver_id',
+                                                                               $table,
+                                                                               '((pid=-1 && t3ver_oid='.$id.') OR uid='.$id.')'.$this->deleteClause($table),
+                                                                               '',
+                                                                               't3ver_id DESC',
+                                                                               '1'
+                                                                       );
+                                                                       list($highestVerNumber) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
+                                                                       $GLOBALS['TYPO3_DB']->sql_free_result($res);
+
+                                                                               // Look for version number of the current:
+                                                                       $subVer = $row['t3ver_id'].'.'.($highestVerNumber+1);
+
+                                                                               // Set up the values to override when making a raw-copy:
+                                                                       $overrideArray = array(
+                                                                               't3ver_id' => $highestVerNumber+1,
+                                                                               't3ver_oid' => $id,
+                                                                               't3ver_label' => ($label ? $label : $subVer.' / '.date('d-m-Y H:m:s')),
+                                                                               't3ver_wsid' => $this->BE_USER->workspace,
+                                                                               't3ver_state' => $delete ? 2 : 0,
+                                                                               't3ver_count' => 0,
+                                                                               't3ver_stage' => 0,
+                                                                               't3ver_tstamp' => 0
+                                                                       );
+                                                                       if ($TCA[$table]['ctrl']['editlock'])   {
+                                                                               $overrideArray[$TCA[$table]['ctrl']['editlock']] = 0;
+                                                                       }
+                                                                       if ($table==='pages')   {
+                                                                               $overrideArray['t3ver_swapmode'] = $versionizeTree;
+                                                                       }
 
-                                                               if ($workspaceCheck)    {
+                                                                               // Checking if the record already has a version in the current workspace of the backend user
+                                                                       $workspaceCheck = TRUE;
+                                                                       if ($this->BE_USER->workspace!==0)      {
+                                                                                       // Look for version already in workspace:
+                                                                               $workspaceCheck = t3lib_BEfunc::getWorkspaceVersionOfRecord($this->BE_USER->workspace,$table,$id,'uid') ? FALSE : TRUE;
+                                                                       }
+
+                                                                       if ($workspaceCheck)    {
 
-                                                                               // Create raw-copy and return result:
-                                                                       return $this->copyRecord_raw($table,$id,-1,$overrideArray);
-                                                               } else $this->newlog('Record "'.$table.':'.$id.'" you wanted to versionize was already a version in the workspace (wsid='.$this->BE_USER->workspace.')!',1);
-                                                       } else $this->newlog('Record cannot be deleted: '.$this->cannotDeleteRecord($table,$id),1);
+                                                                                       // Create raw-copy and return result:
+                                                                               return $this->copyRecord_raw($table,$id,-1,$overrideArray);
+                                                                       } else $this->newlog('Record "'.$table.':'.$id.'" you wanted to versionize was already a version in the workspace (wsid='.$this->BE_USER->workspace.')!',1);
+                                                               } else $this->newlog('Record cannot be deleted: '.$this->cannotDeleteRecord($table,$id),1);
+                                                       } else $this->newlog('Record cannot be versioned because it is a placeholder for a moving operation',1);
                                                } else $this->newlog('Record "'.$table.':'.$id.'" you wanted to versionize was already a version in archive (pid=-1)!',1);
                                        } else $this->newlog('Record "'.$table.':'.$id.'" you wanted to versionize did not exist!',1);
                                } else $this->newlog('The versioning type '.$versionizeTree.' mode you requested was not allowed',1);
@@ -4075,35 +4185,14 @@ class t3lib_TCEmain     {
        function version_swap($table,$id,$swapWith,$swapIntoWS=0)       {
                global $TCA;
 
-               /*
-               Version ID swapping principles:
-                       - Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also
-
-                       uid             pid                     uid             t3ver_oid       pid
-               1:      13              123      -->    -13             247                     123             (Original has negated UID, and sets t3ver_oid to the final UID (which is nice to know for recovery). PID is unchanged at this point)
-               2:      247             -1       -->    13              13                      123             (Swap version gets original UID, correct t3ver_oid (not required for online version) and is moved to the final PID (123))
-               3:      -13             123      -->    247             13                      -1              (Original gets the swap versions old UID, has t3ver_oid set correctly (important) and the ver. repository PID set right.)
-
-                       13 is online UID,
-                       247 is specific versions UID
-                       123 is the PID of the original record
-                       -1 is the versioning repository PID
-
-                       Recovery Process:
-                               Search for negative UID (here "-13"):
-                                       YES: Step 1 completed, but at least step 3 didn't.
-                                               Search for the negativ UIDs positive (here: "13")
-                                                       YES: Step 2 completed: Rollback: "t3ver_oid" of the -uid record shows the original UID of the swap record. Use that to change back UID and pid to -1. After that, proceed with recovery for step 1 (see below)
-                                                       NO: Only Step 1 completed! Rollback: Just change uid "-13" to "13" and "t3ver_oid" to "13" (not important)
-                                       NO: No problems.
-               */
-
                        // First, check if we may actually edit the online record
                if ($this->checkRecordUpdateAccess($table,$id)) {
 
                                // Select the two versions:
                        $curVersion = t3lib_BEfunc::getRecord($table,$id,'*');
                        $swapVersion = t3lib_BEfunc::getRecord($table,$swapWith,'*');
+                       $movePlh = array();
+                       $movePlhID = 0;
 
                        if (is_array($curVersion) && is_array($swapVersion))    {
                                if ($this->BE_USER->workspacePublishAccess($swapVersion['t3ver_wsid'])) {
@@ -4149,10 +4238,28 @@ class t3lib_TCEmain     {
                                                                                        // Modify offline version to become online:
                                                                                $tmp_wsid = $swapVersion['t3ver_wsid'];
                                                                                $swapVersion['pid'] = intval($curVersion['pid']);       // Set pid for ONLINE
-                                                                               $swapVersion['t3ver_oid'] = intval($id);
-                                                                               $swapVersion['t3ver_wsid'] = $swapIntoWS ? intval($curVersion['t3ver_wsid']) : 0;
+                                                                               $swapVersion['t3ver_oid'] = 0;  // We clear this because t3ver_oid only make sense for offline versions and we want to prevent unintentional misuse of this value for online records.
+                                                                               $swapVersion['t3ver_wsid'] = $swapIntoWS ? ($t3ver_state['swapVersion']>0 ? $this->BE_USER->workspace : intval($curVersion['t3ver_wsid'])) : 0; // In case of swapping and the offline record has a state (like 2 or 4 for deleting or move-pointer) we set the current workspace ID so the record is not deselected in the interface by t3lib_BEfunc::versioningPlaceholderClause()
                                                                                $swapVersion['t3ver_tstamp'] = time();
-                                                                               $swapVersion['t3ver_stage'] = $swapVersion['t3ver_state'] = 0;
+                                                                               $swapVersion['t3ver_stage'] = 0;
+                                                                               if (!$swapIntoWS)       $swapVersion['t3ver_state'] = 0;
+
+                                                                                       // Moving element.
+                                                                               if ((int)$TCA[$table]['ctrl']['versioningWS']>=2)       {               //  && $t3ver_state['swapVersion']==4   // Maybe we don't need this? 
+                                                                                       if ($plhRec = t3lib_BEfunc::getMovePlaceholder($table,$id,'t3ver_state,pid,uid'.($TCA[$table]['ctrl']['sortby']?','.$TCA[$table]['ctrl']['sortby']:'')))        {
+                                                                                               $movePlhID = $plhRec['uid'];
+                                                                                               $movePlh['pid'] = $swapVersion['pid'];
+                                                                                               $swapVersion['pid'] = intval($plhRec['pid']);
+
+                                                                                               $curVersion['t3ver_state'] = intval($swapVersion['t3ver_state']);
+                                                                                               $swapVersion['t3ver_state'] = 0;
+
+                                                                                               if ($TCA[$table]['ctrl']['sortby'])     {
+                                                                                                       $movePlh[$TCA[$table]['ctrl']['sortby']] = $swapVersion[$TCA[$table]['ctrl']['sortby']];        // sortby is a "keepFields" which is why this will work...
+                                                                                                       $swapVersion[$TCA[$table]['ctrl']['sortby']] = $plhRec[$TCA[$table]['ctrl']['sortby']];
+                                                                                               }
+                                                                                       }
+                                                                               }
 
                                                                                        // Take care of relations in each field (e.g. IRRE):
                                                                                if (is_array($GLOBALS['TCA'][$table]['columns'])) {
@@ -4171,7 +4278,8 @@ class t3lib_TCEmain       {
                                                                                $curVersion['t3ver_wsid'] = $swapIntoWS ? intval($tmp_wsid) : 0;
                                                                                $curVersion['t3ver_tstamp'] = time();
                                                                                $curVersion['t3ver_count'] = $curVersion['t3ver_count']+1;      // Increment lifecycle counter
-                                                                               $curVersion['t3ver_stage'] = $curVersion['t3ver_state'] = 0;
+                                                                               $curVersion['t3ver_stage'] = 0;
+                                                                               if (!$swapIntoWS)       $curVersion['t3ver_state'] = 0;
 
                                                                                if ($table==='pages') {         // Keeping the swapmode state
                                                                                                $curVersion['t3ver_swapmode'] = $swapVersion['t3ver_swapmode'];
@@ -4190,11 +4298,22 @@ class t3lib_TCEmain     {
                                                                                                unlink($lockFileName);
                                                                                        }
                                                                                }
+                                                                               
 
                                                                                if (!count($sqlErrors)) {
+                                                                                       
+                                                                                               // If a moving operation took place...:
+                                                                                       if ($movePlhID) {
+                                                                                               if (!$swapIntoWS)       {       // Remove, if normal publishing:
+                                                                                                       $this->deleteEl($table, $movePlhID, TRUE, TRUE);        // For delete + completely delete!
+                                                                                               } else {        // Otherwise update the movePlaceholder:
+                                                                                                       $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($movePlhID),$movePlh);
+                                                                                                       $this->updateRefIndex($table,$movePlhID);
+                                                                                               }
+                                                                                       }
 
                                                                                                // Checking for delete:
-                                                                                       if ($t3ver_state['swapVersion']==2)     {
+                                                                                       if (!$swapIntoWS && ((int)$t3ver_state['swapVersion']===1 || (int)$t3ver_state['swapVersion']===2))     {       // Delete only if new/deleted placeholders are there.
                                                                                                $this->deleteEl($table,$id,TRUE);       // Force delete
                                                                                        }
 
@@ -4231,7 +4350,7 @@ class t3lib_TCEmain       {
                                                                                        $this->clear_cache($table,$id);
 
                                                                                                // Checking for "new-placeholder" and if found, delete it (BUT FIRST after swapping!):
-                                                                                       if ($t3ver_state['curVersion']==1)      {
+                                                                                       if (!$swapIntoWS && $t3ver_state['curVersion']>0)       {
                                                                                                $this->deleteEl($table, $swapWith, TRUE, TRUE);         // For delete + completely delete!
                                                                                        }
                                                                                } else $this->newlog('During Swapping: SQL errors happend: '.implode('; ',$sqlErrors),2);
@@ -4250,9 +4369,12 @@ class t3lib_TCEmain      {
         *
         * @param       string          Table name
         * @param       integer         Record UID
+        * @param       boolean         If set, will completely delete element
         * @return      void
         */
-       function version_clearWSID($table,$id)  {
+       function version_clearWSID($table,$id,$flush=FALSE)     {
+               global $TCA;
+               
                if ($errorCode = $this->BE_USER->workspaceCannotEditOfflineVersion($table, $id))        {
                        $this->newlog('Attempt to reset workspace for record failed: '.$errorCode,1);
                } elseif ($this->checkRecordUpdateAccess($table,$id)) {
@@ -4263,16 +4385,23 @@ class t3lib_TCEmain     {
                                $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($id),$sArray);
 
                                        // Clear workspace ID for live version AND DELETE IT as well because it is a new record!
-                               if ((int)$liveRec['t3ver_state']===1)   {
+                               if ((int)$liveRec['t3ver_state']==1 || (int)$liveRec['t3ver_state']==2) {
                                        $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($liveRec['uid']),$sArray);
                                        $this->deleteEl($table, $liveRec['uid'], TRUE); // THIS assumes that the record was placeholder ONLY for ONE record (namely $id)
                                }
 
                                        // If "deleted" flag is set for the version that got released it doesn't make sense to keep that "placeholder" anymore and we delete it completly.
                                $wsRec = t3lib_BEfunc::getRecord($table,$id);
-                               if ((int)$wsRec['t3ver_state']===2)     {
+                               if ($flush || ((int)$wsRec['t3ver_state']==1 || (int)$wsRec['t3ver_state']==2)) {
                                        $this->deleteEl($table, $id, TRUE, TRUE);
                                }
+                               
+                                       // Remove the move-placeholder if found for live record.
+                               if ((int)$TCA[$table]['ctrl']['versioningWS']>=2)       {
+                                       if ($plhRec = t3lib_BEfunc::getMovePlaceholder($table,$liveRec['uid'],'uid'))   {
+                                               $this->deleteEl($table, $plhRec['uid'], TRUE, TRUE);
+                                       }
+                               }
                        }
                } else $this->newlog('Attempt to reset workspace for record failed because you do not have edit access',1);
        }
index 430f012..57b0e6c 100755 (executable)
@@ -968,8 +968,10 @@ class t3lib_treeView {
                        }
                        return $row;
                } else {
-                       $row = @$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
-                       t3lib_BEfunc::workspaceOL($this->table, $row, $this->BE_USER->workspace);
+                       while($row = @$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
+                               t3lib_BEfunc::workspaceOL($this->table, $row, $this->BE_USER->workspace, TRUE);
+                               if (is_array($row))     break;
+                       }
 
                                // Passing on default <td> class for subelements:
                        if (is_array($row) && $subCSSclass!=='')        {
index 26f77c9..c9da044 100755 (executable)
@@ -860,11 +860,17 @@ class t3lib_userAuthGroup extends t3lib_userAuth {
        function workspaceVersioningTypeAccess($type)   {
                $retVal = FALSE;
 
+               $type = t3lib_div::intInRange($type,-1);
+               
+                       // Check if only element versioning is allowed:
+               if ($GLOBALS['TYPO3_CONF_VARS']['BE']['elementVersioningOnly'] && $type!=-1)    {
+                       return FALSE;
+               }
+               
                if ($this->workspace>0 && !$this->isAdmin())    {
                        $stat = $this->checkWorkspaceCurrent();
                        if ($stat['_ACCESS']!=='owner') {
 
-                               $type = t3lib_div::intInRange($type,-1);
                                switch((int)$type)      {
                                        case -1:
                                                $retVal = $this->workspaceRec['vtypes']&1 ? FALSE : TRUE;
index 7c0ec2d..5bb5c38 100755 (executable)
@@ -169,6 +169,7 @@ $TYPO3_CONF_VARS = Array(
                'XCLASS' => Array(),                                    // See 'Inside TYPO3' document for more information.
                'niceFlexFormXMLtags' => TRUE,                  // If set, the flexform XML will be stored with meaningful tags which can be validated with DTD/schema. If you rely on custom reading of the XML from pre-4.0 versions you should set this to false if you don't like to change your reader code (internally it is insignificant since t3lib_div::xml2array() doesn't care for the tags if the index-attribute value is set)
                'compactFlexFormXML' => 0,                              // If set, the flexform XML will not contain indentation spaces making XML more compact
+               'elementVersioningOnly' => FALSE,               // If true, only element versioning is allowed in the backend. This is recommended for new installations of TYPO3 4.2+ since "page" and "branch" versioning types are known for the drawbacks of loosing ids and "element" type versions supports moving now.
        ),
        'FE' => Array(                  // Configuration for the TypoScript frontend (FE). Nothing here relates to the administration backend!
                'png_to_gif' => 0,                                              // Boolean. Enables conversion back to gif of all png-files generated in the frontend libraries. Notice that this leaves an increased number of temporary files in typo3temp/
index b5fb154..507f59a 100755 (executable)
@@ -140,7 +140,7 @@ $TCA['pages'] = Array (
                'sortby' => 'sorting',
                'title' => 'LLL:EXT:lang/locallang_tca.php:pages',
                'type' => 'doktype',
-               'versioningWS' => TRUE,
+               'versioningWS' => 2,
                'origUid' => 't3_origuid',
                'delete' => 'deleted',
                'crdate' => 'crdate',
index ef3a04d..2ef9a80 100755 (executable)
@@ -157,6 +157,7 @@ CREATE TABLE pages (
   t3ver_count int(11) DEFAULT '0' NOT NULL,
   t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
   t3ver_swapmode tinyint(4) DEFAULT '0' NOT NULL,
+  t3ver_move_id int(11) DEFAULT '0' NOT NULL,
   t3_origuid int(11) DEFAULT '0' NOT NULL,
   tstamp int(11) unsigned DEFAULT '0' NOT NULL,
   sorting int(11) unsigned DEFAULT '0' NOT NULL,
index f20ccaa..686e7e6 100755 (executable)
@@ -460,16 +460,22 @@ class localRecordList extends recordList {
                                $prevPrevUid = 0;
                                $accRows = array();     // Accumulate rows here
                                while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))    {
-                                       $accRows[] = $row;
-                                       $currentIdList[] = $row['uid'];
-                                       if ($doSort)    {
-                                               if ($prevUid)   {
-                                                       $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
-                                                       $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
-                                                       $this->currentTable['prevUid'][$row['uid']] = $prevUid;
+                                       
+                                               // In offline workspace, look for alternative record:
+                                       t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace, TRUE);
+                                       
+                                       if (is_array($row))     {
+                                               $accRows[] = $row;
+                                               $currentIdList[] = $row['uid'];
+                                               if ($doSort)    {
+                                                       if ($prevUid)   {
+                                                               $this->currentTable['prev'][$row['uid']] = $prevPrevUid;
+                                                               $this->currentTable['next'][$prevUid] = '-'.$row['uid'];
+                                                               $this->currentTable['prevUid'][$row['uid']] = $prevUid;
+                                                       }
+                                                       $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
+                                                       $prevUid=$row['uid'];
                                                }
-                                               $prevPrevUid = isset($this->currentTable['prev'][$row['uid']]) ? -$prevUid : $row['pid'];
-                                               $prevUid=$row['uid'];
                                        }
                                }
                                $GLOBALS['TYPO3_DB']->sql_free_result($result);
@@ -512,7 +518,10 @@ class localRecordList extends recordList {
                                                                // For each available translation, render the record:
                                                        if (is_array($translations)) {
                                                                foreach($translations as $lRow) {
-                                                                       if ($GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']]))     {
+                                                                               // In offline workspace, look for alternative record:
+                                                                       t3lib_BEfunc::workspaceOL($table, $lRow, $GLOBALS['BE_USER']->workspace);
+                                                                       
+                                                                       if (is_array($lRow) && $GLOBALS['BE_USER']->checkLanguageAccess($lRow[$TCA[$table]['ctrl']['languageField']]))  {
                                                                                $currentIdList[] = $lRow['uid'];
                                                                                $iOut.=$this->renderListRow($table,$lRow,$cc,$titleCol,$thumbsCol,18);
                                                                        }
@@ -573,72 +582,72 @@ class localRecordList extends recordList {
                        $this->id = $row['pid'];
                }
 
-                       // In offline workspace, look for alternative record:
-               t3lib_BEfunc::workspaceOL($table, $row, $GLOBALS['BE_USER']->workspace);
+               if (is_array($row))     {
 
-                       // Background color, if any:
-               $row_bgColor=
-                       $this->alternateBgColors ?
-                       (($cc%2)?'' :' class="db_list_alt"') :
-                       '';
+                               // Background color, if any:
+                       $row_bgColor=
+                               $this->alternateBgColors ?
+                               (($cc%2)?'' :' class="db_list_alt"') :
+                               '';
 
-                       // Overriding with versions background color if any:
-               $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
+                               // Overriding with versions background color if any:
+                       $row_bgColor = $row['_CSSCLASS'] ? ' class="'.$row['_CSSCLASS'].'"' : $row_bgColor;
 
-                       // Incr. counter.
-               $this->counter++;
+                               // Incr. counter.
+                       $this->counter++;
 
-                       // The icon with link
-               $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
-               $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
-               $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
+                               // The icon with link
+                       $alttext = t3lib_BEfunc::getRecordIconAltText($row,$table);
+                       $iconImg = t3lib_iconWorks::getIconImage($table,$row,$this->backPath,'title="'.htmlspecialchars($alttext).'"'.($indent ? ' style="margin-left: '.$indent.'px;"' : ''));
+                       $theIcon = $this->clickMenuEnabled ? $GLOBALS['SOBE']->doc->wrapClickMenuOnIcon($iconImg,$table,$row['uid']) : $iconImg;
 
-                       // Preparing and getting the data-array
-               $theData = Array();
-               foreach($this->fieldArray as $fCol)     {
-                       if ($fCol==$titleCol)   {
-                               $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
-                               $theData[$fCol] = $this->linkWrapItems($table,$row['uid'],$recTitle,$row);
-                       } elseif ($fCol=='pid') {
-                               $theData[$fCol]=$row[$fCol];
-                       } elseif ($fCol=='_PATH_') {
-                               $theData[$fCol]=$this->recPath($row['pid']);
-                       } elseif ($fCol=='_REF_') {
-                               $theData[$fCol]=$this->makeRef($table,$row['uid']);
-                       } elseif ($fCol=='_CONTROL_') {
-                               $theData[$fCol]=$this->makeControl($table,$row);
-                       } elseif ($fCol=='_CLIPBOARD_') {
-                               $theData[$fCol]=$this->makeClip($table,$row);
-#                              $t3lib_transl8tools = new t3lib_transl8tools;
-#                              $theData[$fCol].=t3lib_div::view_array($t3lib_transl8tools->translationInfo($table,$row['uid']));
-                       } elseif ($fCol=='_LOCALIZATION_') {
-                               list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
-                               $theData[$fCol] = $lC1;
-                               $theData[$fCol.'b'] = $lC2;
-                       } elseif ($fCol=='_LOCALIZATION_b') {
-                               // Do nothing, has been done above.
-                       } else {
-                               $theData[$fCol] = $this->linkUrlMail(htmlspecialchars(t3lib_BEfunc::getProcessedValueExtra($table,$fCol,$row[$fCol],100,$row['uid'])),$row[$fCol]);
+                               // Preparing and getting the data-array
+                       $theData = Array();
+                       foreach($this->fieldArray as $fCol)     {
+                               if ($fCol==$titleCol)   {
+                                       $recTitle = t3lib_BEfunc::getRecordTitle($table,$row,FALSE,TRUE);
+                                       $theData[$fCol] = $this->linkWrapItems($table,$row['uid'],$recTitle,$row);
+                               } elseif ($fCol=='pid') {
+                                       $theData[$fCol]=$row[$fCol];
+                               } elseif ($fCol=='_PATH_') {
+                                       $theData[$fCol]=$this->recPath($row['pid']);
+                               } elseif ($fCol=='_REF_') {
+                                       $theData[$fCol]=$this->makeRef($table,$row['uid']);
+                               } elseif ($fCol=='_CONTROL_') {
+                                       $theData[$fCol]=$this->makeControl($table,$row);
+                               } elseif ($fCol=='_CLIPBOARD_') {
+                                       $theData[$fCol]=$this->makeClip($table,$row);
+       #                               $t3lib_transl8tools = new t3lib_transl8tools;
+       #                               $theData[$fCol].=t3lib_div::view_array($t3lib_transl8tools->translationInfo($table,$row['uid']));
+                               } elseif ($fCol=='_LOCALIZATION_') {
+                                       list($lC1, $lC2) = $this->makeLocalizationPanel($table,$row);
+                                       $theData[$fCol] = $lC1;
+                                       $theData[$fCol.'b'] = $lC2;
+                               } elseif ($fCol=='_LOCALIZATION_b') {
+                                       // Do nothing, has been done above.
+                               } else {
+                                       $theData[$fCol] = $this->linkUrlMail(htmlspecialchars(t3lib_BEfunc::getProcessedValueExtra($table,$fCol,$row[$fCol],100,$row['uid'])),$row[$fCol]);
+                               }
                        }
-               }
 
-               if (strlen($this->searchString))        {       // Reset the ID if it was overwritten
-                       $this->id = $id_orig;
-               }
+                       if (strlen($this->searchString))        {       // Reset the ID if it was overwritten
+                               $this->id = $id_orig;
+                       }
 
-                       // Add row to CSV list:
-               if ($this->csvOutput) $this->addToCSV($row,$table);
+                               // Add row to CSV list:
+                       if ($this->csvOutput) $this->addToCSV($row,$table);
 
-                       // Create element in table cells:
-               $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
+                               // Create element in table cells:
+                       $iOut.=$this->addelement(1,$theIcon,$theData,$row_bgColor);
 
-                       // Render thumbsnails if a thumbnail column exists and there is content in it:
-               if ($this->thumbs && trim($row[$thumbsCol]))    {
-                       $iOut.=$this->addelement(4,'', Array($titleCol=>$this->thumbCode($row,$table,$thumbsCol)),$row_bgColor);
-               }
+                               // Render thumbsnails if a thumbnail column exists and there is content in it:
+                       if ($this->thumbs && trim($row[$thumbsCol]))    {
+                               $iOut.=$this->addelement(4,'', Array($titleCol=>$this->thumbCode($row,$table,$thumbsCol)),$row_bgColor);
+                       }
 
-                       // Finally, return table row element:
-               return $iOut;
+                               // Finally, return table row element:
+                       return $iOut;
+               }
        }
 
        /**
@@ -885,7 +894,7 @@ class localRecordList extends recordList {
                                                ($table=='pages' && ($this->calcPerms&8))               // For pages, must have permission to create new pages here.
                                                )       {
                                                if ($this->showNewRecLink($table))      {
-                                                       $params='&edit['.$table.']['.(-$row['uid']).']=new';
+                                                       $params='&edit['.$table.']['.(-($row['_MOVE_PLH']?$row['_MOVE_PLH_uid']:$row['uid'])).']=new';
                                                        $cells[]='<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath,-1)).'">'.
                                                                        '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/new_'.($table=='pages'?'page':'el').'.gif','width="'.($table=='pages'?13:11).'" height="12"').' title="'.$LANG->getLL('new'.($table=='pages'?'Page':'Record'),1).'" alt="" />'.
                                                                        '</a>';
diff --git a/typo3/gfx/i/shadow_moveto_plh.png b/typo3/gfx/i/shadow_moveto_plh.png
new file mode 100644 (file)
index 0000000..dc0c02c
Binary files /dev/null and b/typo3/gfx/i/shadow_moveto_plh.png differ
diff --git a/typo3/gfx/i/shadow_moveto_pointer.png b/typo3/gfx/i/shadow_moveto_pointer.png
new file mode 100644 (file)
index 0000000..d683bac
Binary files /dev/null and b/typo3/gfx/i/shadow_moveto_pointer.png differ
index d97889c..0ac21b5 100644 (file)
@@ -195,6 +195,17 @@ class wslib_gui {
                                        <td nowrap="nowrap" colspan="2">' . $LANG->getLL('label_draft_versions') . '</td>
                                        <td nowrap="nowrap">' . $LANG->getLL('label_stage') . '</td>
                                        <td nowrap="nowrap">' . $LANG->getLL('label_publish') . '</td>
+                                       <td><select name="_with_selected_do" onchange="if (confirm(\'Sure you want to perform this action with selected elements?\')) {document.forms[0].submit();}">
+                                               <option value="_">Do:</option>
+                                               <option value="publish">Publish</option>
+                                               <option value="swap">Swap</option>
+                                               <option value="release">Release</option>
+                                               <option value="stage_-1">Stage: Reject</option>
+                                               <option value="stage_0">Stage: Editing</option>
+                                               <option value="stage_1">Stage: Review</option>
+                                               <option value="stage_10">Stage: Publish</option>
+                                               <option value="flush">Flush (Delete)</option>
+                                       </select></td>
                                        <td>' . $LANG->getLL('label_lifecycle') . '</td>
                                        '.($this->showWorkspaceCol ? '<td>' . $LANG->getLL('label_workspace') . '</td>' : '').'
                                </tr>';
@@ -330,7 +341,7 @@ class wslib_gui {
                global $TCA, $LANG;
 
                // Initialize:
-               $fullColSpan = $this->showWorkspaceCol ? 9 : 8;
+               $fullColSpan = $this->showWorkspaceCol ? 10 : 9;
 
                // Traverse $pArray
                if (is_array($pArray))  {
@@ -424,6 +435,10 @@ class wslib_gui {
                                                                                } elseif ($rec_off['t3ver_state']==2)   {
                                                                                        $diffCode.= $this->doc->icons(2).'Deleted element<br/>';
                                                                                        $diffCode.= $this->doc->icons(2).$LANG->getLL('label_deletedrecord').'<br/>';
+                                                                               } elseif ($rec_on['t3ver_state']==3)    {
+                                                                                       $diffCode.= $this->doc->icons(1).'Move-to placeholder (destination)<br/>';
+                                                                               } elseif ($rec_off['t3ver_state']==4)   {
+                                                                                       $diffCode.= $this->doc->icons(1).'Move-to pointer (source)<br/>';
                                                                                } else {
                                                                                        $diffCode.= ($diffPct<0 ? 'N/A' : ($diffPct ? $diffPct.'% change:' : ''));
                                                                                        $diffCode.= ($diffPct<0 ? $LANG->getLL('label_notapplicable') : ($diffPct ? sprintf($LANG->getLL('label_percentchange'), $diffPct) : ''));
@@ -497,6 +512,7 @@ class wslib_gui {
                                                                        $this->displayWorkspaceOverview_commandLinks($table,$rec_on,$rec_off,$vType).
                                                                        htmlspecialchars($swapLabel).
                                                                        '</td>
+                                                                                       <td nowrap="nowrap" align="center"><input type="checkbox" name="items['.$table.':'.$rec_off['uid'].']" id="items['.$table.':'.$rec_off['uid'].']" value="1"/></td>
                                                                                        <td nowrap="nowrap">'.htmlspecialchars($this->formatCount($rec_off['t3ver_count'])).'</td>'.            // Lifecycle
                                                                        ($this->showWorkspaceCol ? '
                                                                                        <td nowrap="nowrap">'.htmlspecialchars($this->formatWorkspace($rec_off['t3ver_wsid'])).'</td>' : '').'
index f914def..2299136 100755 (executable)
@@ -172,6 +172,72 @@ class SC_mod_user_ws_index extends t3lib_SCbase {
                        // CLEANSE SETTINGS
                $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name'], 'ses');
        }
+       
+       /**
+        * Executes action for selected elements, if any is sent:
+        */
+       function execute()      {
+               $post = t3lib_div::_POST();
+
+#              debug($post);
+
+               if ($post['_with_selected_do']) {
+                       if (is_array($post['items']) && count($post['items']))  {
+                               $cmdArray = array();
+                               
+                               foreach($post['items'] as $item => $v)  {
+                                       list($table,$uid) = explode(':',$item,2);
+                                       
+                                       if ($GLOBALS['TCA'][$table] && t3lib_div::testInt($uid))        {
+                                               switch($post['_with_selected_do'])      {
+                                                       case "stage_-1":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'setStage';
+                                                               $cmdArray[$table][$uid]['version']['stageId'] = -1;
+                                                       break;
+                                                       case "stage_0":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'setStage';
+                                                               $cmdArray[$table][$uid]['version']['stageId'] = 0;
+                                                       break;
+                                                       case "stage_1":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'setStage';
+                                                               $cmdArray[$table][$uid]['version']['stageId'] = 1;
+                                                       break;
+                                                       case "stage_10":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'setStage';
+                                                               $cmdArray[$table][$uid]['version']['stageId'] = 10;
+                                                       break;
+                                                       case "publish":
+                                                               if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))       {
+                                                                       $cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
+                                                                       $cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
+                                                               }
+                                                       break;
+                                                       case "swap":
+                                                       if ($onlineRec = t3lib_BEfunc::getLiveVersionOfRecord($table,$uid,'uid'))       {
+                                                               $cmdArray[$table][$onlineRec['uid']]['version']['action'] = 'swap';
+                                                               $cmdArray[$table][$onlineRec['uid']]['version']['swapWith'] = $uid;
+                                                               $cmdArray[$table][$onlineRec['uid']]['version']['swapIntoWS'] = 1;
+                                                       }
+                                                       break;
+                                                       case "release":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'clearWSID';
+                                                       break;
+                                                       case "flush":
+                                                               $cmdArray[$table][$uid]['version']['action'] = 'flush';
+                                                       break;
+                                               }
+                                       }
+                               }
+
+               #               debug($cmdArray);
+
+                               $tce = t3lib_div::makeInstance('t3lib_TCEmain');
+                               $tce->stripslashes_values = 0;
+                               $tce->start(array(), $cmdArray);
+                               $tce->process_cmdmap();
+                       }
+               }
+       }
 
        /**
         * Standard init function of a module.
@@ -1034,6 +1100,7 @@ if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/u
 
 // Make instance:
 $SOBE = t3lib_div::makeInstance('SC_mod_user_ws_index');
+$SOBE->execute();
 $SOBE->init();
 $SOBE->main();
 $SOBE->printContent();
index b0318ac..a425e9b 100755 (executable)
@@ -507,7 +507,7 @@ $TCA['tt_content'] = Array (
                'tstamp' => 'tstamp',
                'title' => 'LLL:EXT:cms/locallang_tca.php:tt_content',
                'delete' => 'deleted',
-               'versioningWS' => TRUE,
+               'versioningWS' => 2,
                'versioning_followPages' => TRUE,
                'origUid' => 't3_origuid',
                'type' => 'CType',
index 80ba545..d51002d 100755 (executable)
@@ -297,6 +297,7 @@ CREATE TABLE tt_content (
   t3ver_stage tinyint(4) DEFAULT '0' NOT NULL,
   t3ver_count int(11) DEFAULT '0' NOT NULL,
   t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
+  t3ver_move_id int(11) DEFAULT '0' NOT NULL,
   t3_origuid int(11) DEFAULT '0' NOT NULL,
   tstamp int(11) unsigned DEFAULT '0' NOT NULL,
   hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
index 068b8c4..8c9b80a 100755 (executable)
@@ -440,9 +440,8 @@ class tx_cms_layout extends recordList {
                                        $rowArr = $this->getResult($result);
 
                                        foreach($rowArr as $rKey => $row)       {
-                                               t3lib_BEfunc::workspaceOL('tt_content', $row);
 
-                                               if ((int)$row['t3ver_state']!=2)        {
+                                               if (is_array($row) && (int)$row['t3ver_state']!=2)      {
                                                        $singleElementHTML = '';
                                                        if (!$lP) $defLanguageCount[$key][] = $row['uid'];
 
@@ -646,9 +645,8 @@ class tx_cms_layout extends recordList {
 
                                                // Traverse any selected elements:
                                        foreach($rowArr as $rKey => $row)       {
-                                               t3lib_BEfunc::workspaceOL('tt_content', $row);
 
-                                               if ((int)$row['t3ver_state']!=2)        {
+                                               if (is_array($row) && (int)$row['t3ver_state']!=2)      {
 
                                                        $c++;
                                                        $editUidList.=$row['uid'].',';
@@ -821,36 +819,38 @@ class tx_cms_layout extends recordList {
                                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))   {
                                        t3lib_BEfunc::workspaceOL('sys_note', $row);
 
-                                       list($flag,$code) = $this->fwd_rwd_nav();
-                                       $out.=$code;
-                                       if ($flag)      {
-                                               $color = Array (
-                                                       0 => '',                // No category
-                                                       1 => ' class="bgColor4"',               // Instructions
-                                                       2 => ' class="bgColor2"',               // Template
-                                                       3 => '',                // Notes
-                                                       4 => ' class="bgColor5"'                // To-do
-                                               );
-                                               $tdparams = $color[$row['category']];
-                                               $info = Array();;
-                                               $theData = Array();
-                                               $this->getProcessedValue('sys_note','subject,category,author,email,personal',$row,$info);
-                                               $cont=implode('<br />',$info);
-                                               $head = '<b>Page:</b> '.t3lib_BEfunc::getRecordPath($row['pid'],$perms_clause,10).'<br />';
-
-                                               $theData['__cmds__']= $this->getIcon('sys_note',$row);
-                                               $theData['info'] = $head.$cont;
-                                               $theData['note'] = nl2br($row['message']);
-
-                                               $out.=$this->addelement(1,'',$theData,$tdparams,20);
-
-
-                                                       // half line is drawn
-                                               $theData = Array();
-                                               $theData['info'] = $this->widthGif;
-                                               $out.=$this->addelement(0,'',$theData);
+                                       if (is_array($row))     {
+                                               list($flag,$code) = $this->fwd_rwd_nav();
+                                               $out.=$code;
+                                               if ($flag)      {
+                                                       $color = Array (
+                                                               0 => '',                // No category
+                                                               1 => ' class="bgColor4"',               // Instructions
+                                                               2 => ' class="bgColor2"',               // Template
+                                                               3 => '',                // Notes
+                                                               4 => ' class="bgColor5"'                // To-do
+                                                       );
+                                                       $tdparams = $color[$row['category']];
+                                                       $info = Array();;
+                                                       $theData = Array();
+                                                       $this->getProcessedValue('sys_note','subject,category,author,email,personal',$row,$info);
+                                                       $cont=implode('<br />',$info);
+                                                       $head = '<b>Page:</b> '.t3lib_BEfunc::getRecordPath($row['pid'],$perms_clause,10).'<br />';
+
+                                                       $theData['__cmds__']= $this->getIcon('sys_note',$row);
+                                                       $theData['info'] = $head.$cont;
+                                                       $theData['note'] = nl2br($row['message']);
+
+                                                       $out.=$this->addelement(1,'',$theData,$tdparams,20);
+
+
+                                                               // half line is drawn
+                                                       $theData = Array();
+                                                       $theData['info'] = $this->widthGif;
+                                                       $out.=$this->addelement(0,'',$theData);
+                                               }
+                                               $this->eCounter++;
                                        }
-                                       $this->eCounter++;
                                }
 
                                        // Wrap it all in a table:
@@ -916,23 +916,25 @@ class tx_cms_layout extends recordList {
                        while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))   {
                                t3lib_BEfunc::workspaceOL('tt_board', $row);
 
-                               list($flag,$code) = $this->fwd_rwd_nav();
-                               $out.=$code;
+                               if (is_array($row))     {
+                                       list($flag,$code) = $this->fwd_rwd_nav();
+                                       $out.=$code;
 
-                               if ($flag)      {
+                                       if ($flag)      {
 
-                                       $theRows = Array();
-                                       $theRows = $this->tt_board_getTree ($theRows,$row['uid'],$id,$delClause,'');
-                                       $out.=$this->tt_board_drawItem('tt_board',$row,count($theRows));
+                                               $theRows = Array();
+                                               $theRows = $this->tt_board_getTree ($theRows,$row['uid'],$id,$delClause,'');
+                                               $out.=$this->tt_board_drawItem('tt_board',$row,count($theRows));
 
-                                       if ($GLOBALS['SOBE']->MOD_SETTINGS['tt_board']=='expand')       {
-                                               reset($theRows);
-                                               while(list($n,$sRow)=each($theRows))    {
-                                                       $out.=$this->tt_board_drawItem('tt_board',$sRow,0);
+                                               if ($GLOBALS['SOBE']->MOD_SETTINGS['tt_board']=='expand')       {
+                                                       reset($theRows);
+                                                       while(list($n,$sRow)=each($theRows))    {
+                                                               $out.=$this->tt_board_drawItem('tt_board',$sRow,0);
+                                                       }
                                                }
                                        }
+                                       $this->eCounter++;
                                }
-                               $this->eCounter++;
                        }
 
                                // Wrap it all in a table:
@@ -1177,30 +1179,32 @@ class tx_cms_layout extends recordList {
                        while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))   {
                                t3lib_BEfunc::workspaceOL($table, $row);
 
-                               list($flag,$code) = $this->fwd_rwd_nav();
-                               $out.= $code;
-                               if ($flag)      {
-                                       $params = '&edit['.$table.']['.$row['uid'].']=edit';
-                                       $Nrow = array();
+                               if (is_array($row))     {
+                                       list($flag,$code) = $this->fwd_rwd_nav();
+                                       $out.= $code;
+                                       if ($flag)      {
+                                               $params = '&edit['.$table.']['.$row['uid'].']=edit';
+                                               $Nrow = array();
 
-                                               // Setting icons/edit links:
-                                       if ($icon)      {
-                                               $Nrow['__cmds__']= $this->getIcon($table,$row);
-                                       }
-                                       if ($this->doEdit)      {
-                                               $Nrow['__cmds__'].= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath)).'">'.
-                                                                               '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$GLOBALS['LANG']->getLL('edit',1).'" alt="" />'.
-                                                                               '</a>';
-                                       } else {
-                                               $Nrow['__cmds__'].= $this->noEditIcon();
-                                       }
+                                                       // Setting icons/edit links:
+                                               if ($icon)      {
+                                                       $Nrow['__cmds__']= $this->getIcon($table,$row);
+                                               }
+                                               if ($this->doEdit)      {
+                                                       $Nrow['__cmds__'].= '<a href="#" onclick="'.htmlspecialchars(t3lib_BEfunc::editOnClick($params,$this->backPath)).'">'.
+                                                                                       '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/edit2.gif','width="11" height="12"').' title="'.$GLOBALS['LANG']->getLL('edit',1).'" alt="" />'.
+                                                                                       '</a>';
+                                               } else {
+                                                       $Nrow['__cmds__'].= $this->noEditIcon();
+                                               }
 
-                                               // Get values:
-                                       $Nrow = $this->dataFields($this->fieldArray,$table,$row,$Nrow);
-                                       $tdparams = $this->eCounter%2 ? ' class="bgColor4"' : ' class="bgColor4-20"';
-                                       $out.= $this->addelement(1,'',$Nrow,$tdparams);
+                                                       // Get values:
+                                               $Nrow = $this->dataFields($this->fieldArray,$table,$row,$Nrow);
+                                               $tdparams = $this->eCounter%2 ? ' class="bgColor4"' : ' class="bgColor4-20"';
+                                               $out.= $this->addelement(1,'',$Nrow,$tdparams);
+                                       }
+                                       $this->eCounter++;
                                }
-                               $this->eCounter++;
                        }
 
                                // Wrap it all in a table:
@@ -1327,13 +1331,15 @@ class tx_cms_layout extends recordList {
                        $rc = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
                        while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
                                t3lib_BEfunc::workspaceOL('pages', $row);
-                               $c++;
-                               $row['treeIcons'] = $treeIcons.'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/join'.($rc==$c?'bottom':'').'.gif','width="18" height="16"').' alt="" />';
-                               $theRows[]=$row;
-
-                                       // Get the branch
-                               $spaceOutIcons = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($rc==$c?'blank.gif':'line.gif'),'width="18" height="16"').' alt="" />';
-                               $theRows = $this->pages_getTree($theRows,$row['uid'],$qWhere,$treeIcons.$spaceOutIcons,$row['php_tree_stop']?0:$depth);
+                               if (is_array($row))     {
+                                       $c++;
+                                       $row['treeIcons'] = $treeIcons.'<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/join'.($rc==$c?'bottom':'').'.gif','width="18" height="16"').' alt="" />';
+                                       $theRows[]=$row;
+
+                                               // Get the branch
+                                       $spaceOutIcons = '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/ol/'.($rc==$c?'blank.gif':'line.gif'),'width="18" height="16"').' alt="" />';
+                                       $theRows = $this->pages_getTree($theRows,$row['uid'],$qWhere,$treeIcons.$spaceOutIcons,$row['php_tree_stop']?0:$depth);
+                               }
                        }
                } else {
                        $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', 'pages', 'pid='.intval($pid).$qWhere);
@@ -1967,9 +1973,10 @@ class tx_cms_layout extends recordList {
         * Traverse the result pointer given, adding each record to array and setting some internal values at the same time.
         *
         * @param       pointer         SQL result pointer for select query.
+        * @param       string          Table name defaulting to tt_content
         * @return      array           The selected rows returned in this array.
         */
-       function getResult($result)     {
+       function getResult($result,$table='tt_content') {
 
                        // Initialize:
                $editUidList='';
@@ -1981,29 +1988,33 @@ class tx_cms_layout extends recordList {
                        // Traverse the result:
                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))   {
 
-                               // Add the row to the array:
-                       $output[]=$row;
+                       t3lib_BEfunc::workspaceOL($table, $row, -99, TRUE);
 
-                               // Set an internal register:
-                       $recs[$c]=$row['uid'];
+                       if ($row)       {
+                                       // Add the row to the array:
+                               $output[]=$row;
 
-                               // Create the list of the next three ids (for editing links...)
-                       for($a=0;$a<$nextTree;$a++)     {
-                               if(isset($recs[$c-$a])) {
-                                       $this->tt_contentData['nextThree'][$recs[$c-$a]].=$row['uid'].',';
+                                       // Set an internal register:
+                               $recs[$c]=$row['uid'];
+
+                                       // Create the list of the next three ids (for editing links...)
+                               for($a=0;$a<$nextTree;$a++)     {
+                                       if(isset($recs[$c-$a])) {
+                                               $this->tt_contentData['nextThree'][$recs[$c-$a]].=$row['uid'].',';
+                                       }
                                }
-                       }
 
-                               // Set next/previous ids:
-                       if (isset($recs[$c-1])) {
-                               if (isset($recs[$c-2])) {
-                                       $this->tt_contentData['prev'][$row['uid']]=-$recs[$c-2];
-                               } else {
-                                       $this->tt_contentData['prev'][$row['uid']]=$row['pid'];
+                                       // Set next/previous ids:
+                               if (isset($recs[$c-1])) {
+                                       if (isset($recs[$c-2])) {
+                                               $this->tt_contentData['prev'][$row['uid']]=-$recs[$c-2];
+                                       } else {
+                                               $this->tt_contentData['prev'][$row['uid']]=$row['pid'];
+                                       }
+                                       $this->tt_contentData['next'][$recs[$c-1]]=-$row['uid'];
                                }
-                               $this->tt_contentData['next'][$recs[$c-1]]=-$row['uid'];
+                               $c++;
                        }
-                       $c++;
                }
 
                        // Return selected records
index 98614fb..69b3a87 100755 (executable)
@@ -572,21 +572,24 @@ class SC_db_layout {
                $prev=$this->id;        // Page is the pid if no record to put this after.
                while($cRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
                        t3lib_BEfunc::workspaceOL('tt_content', $cRow);
-                       if ($first)     {
-                               if (!$edit_record)      {
-                                       $edit_record='tt_content:'.$cRow['uid'];
+                       
+                       if (is_array($cRow))    {
+                               if ($first)     {
+                                       if (!$edit_record)      {
+                                               $edit_record='tt_content:'.$cRow['uid'];
+                                       }
+                                       $first = 0;
                                }
-                               $first = 0;
-                       }
-                       if (strcmp($cRow['colPos'],$colPos))    {
-                               $colPos=$cRow['colPos'];
-                               $opt[]='<option value=""></option>';
-                               $opt[]='<option value="_EDIT_COL:'.$colPos.'">__'.$LANG->sL(t3lib_BEfunc::getLabelFromItemlist('tt_content','colPos',$colPos),1).':__</option>';
+                               if (strcmp($cRow['colPos'],$colPos))    {
+                                       $colPos=$cRow['colPos'];
+                                       $opt[]='<option value=""></option>';
+                                       $opt[]='<option value="_EDIT_COL:'.$colPos.'">__'.$LANG->sL(t3lib_BEfunc::getLabelFromItemlist('tt_content','colPos',$colPos),1).':__</option>';
+                               }
+                               $inValue = 'tt_content:'.$cRow['uid'];
+                               $is_selected+=intval($edit_record==$inValue);
+                               $opt[]='<option value="'.$inValue.'"'.($edit_record==$inValue?' selected="selected"':'').'>'.htmlspecialchars(t3lib_div::fixed_lgd_cs($cRow['header']?$cRow['header']:'['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.no_title').'] '.strip_tags($cRow['bodytext']),$BE_USER->uc['titleLen'])).'</option>';
+                               $prev=-$cRow['uid'];
                        }
-                       $inValue = 'tt_content:'.$cRow['uid'];
-                       $is_selected+=intval($edit_record==$inValue);
-                       $opt[]='<option value="'.$inValue.'"'.($edit_record==$inValue?' selected="selected"':'').'>'.htmlspecialchars(t3lib_div::fixed_lgd_cs($cRow['header']?$cRow['header']:'['.$LANG->sL('LLL:EXT:lang/locallang_core.php:labels.no_title').'] '.strip_tags($cRow['bodytext']),$BE_USER->uc['titleLen'])).'</option>';
-                       $prev=-$cRow['uid'];
                }
 
                        // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element:
index e1a1097..b1e1f8d 100755 (executable)
@@ -1203,7 +1203,7 @@ class tslib_cObj {
                                        while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
 
                                                        // Versioning preview:
-                                               $GLOBALS['TSFE']->sys_page->versionOL($conf['table'],$row);
+                                               $GLOBALS['TSFE']->sys_page->versionOL($conf['table'],$row,TRUE);
 
                                                        // Language Overlay:
                                                if (is_array($row) && $GLOBALS['TSFE']->sys_language_contentOL) {
@@ -6387,7 +6387,7 @@ class tslib_cObj {
                                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
                                        $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
 
-                                       if ($row['doktype']==255 || $row['doktype']==6 || $row['t3ver_state']==1)       { unset($row); }        // Doing this after the overlay to make sure changes in the overlay are respected.
+                                       if ($row['doktype']==255 || $row['doktype']==6 || $row['t3ver_state']>0)        { unset($row); }        // Doing this after the overlay to make sure changes in the overlay are respected.
 
                                        if (is_array($row))     {
                                                        // Find mount point if any:
@@ -6400,7 +6400,7 @@ class tslib_cObj {
                                                        $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res2);
                                                        $GLOBALS['TSFE']->sys_page->versionOL('pages',$row);
 
-                                                       if ($row['doktype']==255 || $row['doktype']==6 || $row['t3ver_state']==1)       { unset($row); }        // Doing this after the overlay to make sure changes in the overlay are respected.
+                                                       if ($row['doktype']==255 || $row['doktype']==6 || $row['t3ver_state']>0)        { unset($row); }        // Doing this after the overlay to make sure changes in the overlay are respected.
                                                }
                                                        // Add record:
                                                if (is_array($row) && ($dontCheckEnableFields || $GLOBALS['TSFE']->checkPagerecordForIncludeSection($row)))     {
index 135f1e4..d12d49d 100644 (file)
@@ -369,8 +369,8 @@ class tx_cms_webinfo_lang extends t3lib_extobjbase {
                );
 
                $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
+               t3lib_BEfunc::workspaceOL('pages_language_overlay',$row);
                if (is_array($row))     {
-                       t3lib_BEfunc::workspaceOL('pages_language_overlay',$row);
                        $row['_COUNT'] = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
                        $row['_HIDDEN'] = $row['hidden'] ||
                                                        (intval($row['endtime']) > 0 && intval($row['endtime']) < time()) ||
index ed8d49f..47e1a5b 100644 (file)
@@ -102,7 +102,10 @@ Automatic Repair:
                                'versions_liveWS' => array('All versions in Live workspace','This is all records that are offline versions in the Live workspace. You may wish to flush these if you only use workspaces for versioning since then you might find lots of versions piling up in the live workspace which have simply been disconnected from the workspace before they were published.',1),
                                'versions_lost_workspace' => array('Versions outside a workspace','Versions that has lost their connection to a workspace in TYPO3.',3),
                                'versions_inside_versioned_page' => array('Versions in versions','Versions inside an already versioned page. Something that is confusing to users and therefore should not happen but is technically possible.',2),
-                               'versions_unused_placeholders' => array('Unused placeholder records','Placeholder records which are not used anymore by offline versions.',2)
+                               'versions_unused_placeholders' => array('Unused placeholder records','Placeholder records which are not used anymore by offline versions.',2),
+                               'versions_move_placeholders_ok' => array('Move placeholders','Move-to placeholder records which has good integrity',0),
+                               'versions_move_placeholders_bad' => array('Move placeholders with bad integrity','Move-to placeholder records which has bad integrity',2),
+                               'versions_move_id_check' => array('Checking if t3ver_move_id is correct','t3ver_move_id must only be set with online records having t3ver_state=3.',2),
                        ),
                        'versions' => array(),
                );
@@ -130,6 +133,59 @@ Automatic Repair:
                        }
                }
 
+                       // Finding all move placeholders with inconsistencies:
+               $resultArray['versions_move_placeholders_ok'] = array(); 
+               $resultArray['versions_move_placeholders_bad'] = array(); 
+               foreach($GLOBALS['TCA'] as $table => $cfg)      {
+                       if ((int)$cfg['ctrl']['versioningWS']>=2)       {
+                               $placeHolders = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,pid,t3ver_move_id,t3ver_wsid,t3ver_state',$table,'t3ver_state=3 AND pid>=0'.t3lib_BEfunc::deleteClause($table));
+                               foreach($placeHolders as $phrec)        {
+                                       if ((int)$phrec['t3ver_wsid']!=0)       {
+                                               $phrecCopy = $phrec;
+                                               if (t3lib_BEfunc::movePlhOL($table,$phrec))     {
+                                                       if ($wsAlt = t3lib_BEfunc::getWorkspaceVersionOfRecord($phrecCopy['t3ver_wsid'], $table, $phrec['uid'], 'uid,pid,t3ver_state')) {
+                                                               if ($wsAlt['t3ver_state']!=4)   {
+                                                                       $resultArray['versions_move_placeholders_bad'][] = array($table.':'.$phrec['uid'],'State for version was not "4" as it should be!',$phrecCopy); 
+                                                               } else {
+                                                                       $resultArray['versions_move_placeholders_ok'][] = array(
+                                                                               $table.':'.$phrec['uid'],
+                                                                               'PLH' => $phrecCopy,
+                                                                               'online' => $phrec,
+                                                                               'PNT' => $wsAlt
+                                                                       ); 
+                                                               }
+                                                       } else {
+                                                               $resultArray['versions_move_placeholders_bad'][] = array($table.':'.$phrec['uid'],'No version was found for online record to be moved. A version must exist.',$phrecCopy); 
+                                                       }
+                                               } else {
+                                                       $resultArray['versions_move_placeholders_bad'][] = array($table.':'.$phrec['uid'],'Did not find online record for "t3ver_move_id" value '.$phrec['t3ver_move_id'],$phrec); 
+                                               }
+                                       } else {
+                                               $resultArray['versions_move_placeholders_bad'][] = array($table.':'.$phrec['uid'],'Placeholder was not assigned a workspace value in t3ver_wsid.',$phrec); 
+                                       }
+                               }
+                       }
+               }
+
+                       // Finding move_id_check inconsistencies:
+               $resultArray['versions_move_id_check'] = array(); 
+               foreach($GLOBALS['TCA'] as $table => $cfg)      {
+                       if ((int)$cfg['ctrl']['versioningWS']>=2)       {
+                               $placeHolders = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,pid,t3ver_move_id,t3ver_wsid,t3ver_state',$table,'t3ver_move_id!=0'.t3lib_BEfunc::deleteClause($table));
+                               foreach($placeHolders as $phrec)        {
+                                       if ((int)$phrec['t3ver_state']==3)      {
+                                               if ($phrec['pid']!=-1)  {
+                                                               // OK
+                                               } else {
+                                                       $resultArray['versions_move_id_check'][] = array($table.':'.$phrec['uid'],'Record was offline, must not be!',$phrec); 
+                                               }
+                                       } else {
+                                               $resultArray['versions_move_id_check'][] = array($table.':'.$phrec['uid'],'Record had t3ver_move_id set to "'.$phrec['t3ver_move_id'].'" while having t3ver_state='.$phrec['t3ver_state'],$phrec); 
+                                       }
+                               }
+                       }
+               }
+
                return $resultArray;
        }
 
index 10456dd..cdb5491 100755 (executable)
@@ -145,8 +145,10 @@ class tx_wizardcrpages_webfunc_2 extends t3lib_extobjbase {
                                $lines=array();
                                while(list(,$rec)=each($menuItems))     {
                                        t3lib_BEfunc::workspaceOL('pages',$rec);
-                                       $lines[]= '<nobr>'.t3lib_iconWorks::getIconImage('pages',$rec,$GLOBALS['BACK_PATH'],'align="top" '.t3lib_BEfunc::titleAttribForPages($rec)).
-                                               htmlspecialchars(t3lib_div::fixed_lgd_cs($rec['title'],$GLOBALS['BE_USER']->uc['titleLen'])).'</nobr>';
+                                       if (is_array($rec))     {
+                                               $lines[]= '<nobr>'.t3lib_iconWorks::getIconImage('pages',$rec,$GLOBALS['BACK_PATH'],'align="top" '.t3lib_BEfunc::titleAttribForPages($rec)).
+                                                       htmlspecialchars(t3lib_div::fixed_lgd_cs($rec['title'],$GLOBALS['BE_USER']->uc['titleLen'])).'</nobr>';
+                                       }
                                }
                                $theCode.= '<b>'.$LANG->getLL('wiz_newPages_currentMenu').':</b><br /><br />'.implode('<br />',$lines);
                        } else {