TYPO3 API  SVNRelease
class.versions.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Cleaner module: Versions of records
00029  * User function called from tx_lowlevel_cleaner_core configured in ext_localconf.php
00030  *
00031  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00032  */
00033 /**
00034  * [CLASS/FUNCTION INDEX of SCRIPT]
00035  *
00036  *
00037  *
00038  *   56: class tx_lowlevel_versions extends tx_lowlevel_cleaner_core
00039  *   63:     function tx_lowlevel_versions()
00040  *   88:     function main()
00041  *  122:     function main_autoFix($resultArray)
00042  *
00043  * TOTAL FUNCTIONS: 3
00044  * (This index is automatically created/updated by the extension "extdeveval")
00045  *
00046  */
00047 
00048 
00049 /**
00050  * Looking for versions of records
00051  *
00052  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00053  * @package TYPO3
00054  * @subpackage tx_lowlevel
00055  */
00056 class tx_lowlevel_versions extends tx_lowlevel_cleaner_core {
00057 
00058     /**
00059      * Constructor
00060      *
00061      * @return  void
00062      */
00063     function tx_lowlevel_versions() {
00064         parent::tx_lowlevel_cleaner_core();
00065 
00066             // Setting up help:
00067         $this->cli_options[] = array('--echotree level', 'When "level" is set to 1 or higher you will see the page of the page tree outputted as it is traversed. A value of 2 for "level" will show even more information.');
00068         $this->cli_options[] = array('--pid id', 'Setting start page in page tree. Default is the page tree root, 0 (zero)');
00069         $this->cli_options[] = array('--depth int', 'Setting traversal depth. 0 (zero) will only analyse start page (see --pid), 1 will traverse one level of subpages etc.');
00070 
00071         $this->cli_options[] = array('--flush-live', 'If set, not only published versions from Live workspace are flushed, but ALL versions from Live workspace (which are offline of course)');
00072 
00073         $this->cli_help['name'] = 'versions -- To find information about versions and workspaces in the system';
00074         $this->cli_help['description'] = trim('
00075 Traversing page tree and finding versions, categorizing them by various properties.
00076 Published versions from the Live workspace are registered. So are all offline versions from Live workspace in general. Further, versions in non-existing workspaces are found.
00077 
00078 Automatic Repair:
00079 - Deleting (completely) published versions from LIVE workspace OR _all_ offline versions from Live workspace (toogle by --flush-live)
00080 - Resetting workspace for versions where workspace is deleted. (You might want to run this tool again after this operation to clean out those new elements in the Live workspace)
00081 - Deleting unused placeholders
00082 ');
00083 
00084         $this->cli_help['examples'] = '';
00085     }
00086 
00087     /**
00088      * Find orphan records
00089      * VERY CPU and memory intensive since it will look up the whole page tree!
00090      *
00091      * @return  array
00092      */
00093     function main() {
00094         global $TYPO3_DB;
00095 
00096             // Initialize result array:
00097         $resultArray = array(
00098             'message' => $this->cli_help['name'].LF.LF.$this->cli_help['description'],
00099             'headers' => array(
00100                 'versions' => array('All versions','Showing all versions of records found',0),
00101                 'versions_published' => array('All published versions','This is all records that has been published and can therefore be removed permanently',1),
00102                 '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),
00103                 'versions_lost_workspace' => array('Versions outside a workspace','Versions that has lost their connection to a workspace in TYPO3.',3),
00104                 '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),
00105                 'versions_unused_placeholders' => array('Unused placeholder records','Placeholder records which are not used anymore by offline versions.',2),
00106                 'versions_move_placeholders_ok' => array('Move placeholders','Move-to placeholder records which has good integrity',0),
00107                 'versions_move_placeholders_bad' => array('Move placeholders with bad integrity','Move-to placeholder records which has bad integrity',2),
00108                 '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),
00109             ),
00110             'versions' => array(),
00111         );
00112 
00113         $startingPoint = $this->cli_isArg('--pid') ? t3lib_div::intInRange($this->cli_argValue('--pid'),0) : 0;
00114         $depth = $this->cli_isArg('--depth') ? t3lib_div::intInRange($this->cli_argValue('--depth'),0) : 1000;
00115         $this->genTree($startingPoint,$depth,(int)$this->cli_argValue('--echotree'));
00116 
00117         $resultArray['versions'] = $this->recStats['versions'];
00118         $resultArray['versions_published'] = $this->recStats['versions_published'];
00119         $resultArray['versions_liveWS'] = $this->recStats['versions_liveWS'];
00120         $resultArray['versions_lost_workspace'] = $this->recStats['versions_lost_workspace'];
00121         $resultArray['versions_inside_versioned_page'] = $this->recStats['versions_inside_versioned_page'];
00122 
00123             // Finding all placeholders with no records attached!
00124         $resultArray['versions_unused_placeholders'] = array();
00125         foreach($GLOBALS['TCA'] as $table => $cfg)  {
00126             if ($cfg['ctrl']['versioningWS'])   {
00127                 $placeHolders = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,pid',$table,'t3ver_state=1 AND pid>=0'.t3lib_BEfunc::deleteClause($table));
00128                 foreach($placeHolders as $phrec)    {
00129                     if (count(t3lib_BEfunc::selectVersionsOfRecord($table, $phrec['uid'], 'uid'))<=1)   {
00130                         $resultArray['versions_unused_placeholders'][t3lib_div::shortmd5($table.':'.$phrec['uid'])] = $table.':'.$phrec['uid'];
00131                     }
00132                 }
00133             }
00134         }
00135         asort($resultArray['versions_unused_placeholders']);
00136 
00137             // Finding all move placeholders with inconsistencies:
00138         $resultArray['versions_move_placeholders_ok'] = array();
00139         $resultArray['versions_move_placeholders_bad'] = array();
00140         foreach($GLOBALS['TCA'] as $table => $cfg)  {
00141             if ((int)$cfg['ctrl']['versioningWS']>=2)   {
00142                 $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));
00143                 foreach($placeHolders as $phrec)    {
00144                     $shortID = t3lib_div::shortmd5($table.':'.$phrec['uid']);
00145                     if ((int)$phrec['t3ver_wsid']!=0)   {
00146                         $phrecCopy = $phrec;
00147                         if (t3lib_BEfunc::movePlhOL($table,$phrec)) {
00148                             if ($wsAlt = t3lib_BEfunc::getWorkspaceVersionOfRecord($phrecCopy['t3ver_wsid'], $table, $phrec['uid'], 'uid,pid,t3ver_state')) {
00149                                 if ($wsAlt['t3ver_state']!=4)   {
00150                                     $resultArray['versions_move_placeholders_bad'][$shortID] = array($table.':'.$phrec['uid'],'State for version was not "4" as it should be!',$phrecCopy);
00151                                 } else {
00152                                     $resultArray['versions_move_placeholders_ok'][$shortID] = array(
00153                                         $table.':'.$phrec['uid'],
00154                                         'PLH' => $phrecCopy,
00155                                         'online' => $phrec,
00156                                         'PNT' => $wsAlt
00157                                     );
00158                                 }
00159                             } else {
00160                                 $resultArray['versions_move_placeholders_bad'][$shortID] = array($table.':'.$phrec['uid'],'No version was found for online record to be moved. A version must exist.',$phrecCopy);
00161                             }
00162                         } else {
00163                             $resultArray['versions_move_placeholders_bad'][$shortID] = array($table.':'.$phrec['uid'],'Did not find online record for "t3ver_move_id" value '.$phrec['t3ver_move_id'],$phrec);
00164                         }
00165                     } else {
00166                         $resultArray['versions_move_placeholders_bad'][$shortID] = array($table.':'.$phrec['uid'],'Placeholder was not assigned a workspace value in t3ver_wsid.',$phrec);
00167                     }
00168                 }
00169             }
00170         }
00171 
00172         ksort($resultArray['versions_move_placeholders_ok']);
00173         ksort($resultArray['versions_move_placeholders_bad']);
00174 
00175             // Finding move_id_check inconsistencies:
00176         $resultArray['versions_move_id_check'] = array();
00177         foreach($GLOBALS['TCA'] as $table => $cfg)  {
00178             if ((int)$cfg['ctrl']['versioningWS']>=2)   {
00179                 $placeHolders = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,pid,t3ver_move_id,t3ver_wsid,t3ver_state',$table,'t3ver_move_id!=0'.t3lib_BEfunc::deleteClause($table));
00180                 foreach($placeHolders as $phrec)    {
00181                     if ((int)$phrec['t3ver_state']==3)  {
00182                         if ($phrec['pid']!=-1)  {
00183                                 // OK
00184                         } else {
00185                             $resultArray['versions_move_id_check'][] = array($table.':'.$phrec['uid'],'Record was offline, must not be!',$phrec);
00186                         }
00187                     } else {
00188                         $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);
00189                     }
00190                 }
00191             }
00192         }
00193 
00194         return $resultArray;
00195     }
00196 
00197     /**
00198      * Mandatory autofix function
00199      * Will run auto-fix on the result array. Echos status during processing.
00200      *
00201      * @param   array       Result array from main() function
00202      * @return  void
00203      */
00204     function main_autoFix($resultArray) {
00205 
00206         $kk = $this->cli_isArg('--flush-live') ? 'versions_liveWS' : 'versions_published';
00207 
00208             // Putting "pages" table in the bottom:
00209         if (isset($resultArray[$kk]['pages']))  {
00210             $_pages = $resultArray[$kk]['pages'];
00211             unset($resultArray[$kk]['pages']);
00212             $resultArray[$kk]['pages'] = $_pages;
00213         }
00214 
00215             // Traversing records:
00216         foreach($resultArray[$kk] as $table => $list)   {
00217             echo 'Flushing published records from table "'.$table.'":'.LF;
00218             foreach($list as $uid)  {
00219                 echo '  Flushing record "'.$table.':'.$uid.'": ';
00220 
00221                 if ($bypass = $this->cli_noExecutionCheck($table.':'.$uid)) {
00222                     echo $bypass;
00223                 } else {
00224 
00225                         // Execute CMD array:
00226                     $tce = t3lib_div::makeInstance('t3lib_TCEmain');
00227                     $tce->stripslashes_values = FALSE;
00228                     $tce->start(array(),array());
00229                     $tce->deleteEl($table,$uid, TRUE, TRUE);
00230 
00231                         // Return errors if any:
00232                     if (count($tce->errorLog))  {
00233                         echo '  ERROR from "TCEmain":'.LF.'TCEmain:'.implode(LF.'TCEmain:',$tce->errorLog);
00234                     } else echo 'DONE';
00235                 }
00236                 echo LF;
00237             }
00238         }
00239 
00240             // Traverse workspace:
00241         foreach($resultArray['versions_lost_workspace'] as $table => $list) {
00242             echo 'Resetting workspace to zero for records from table "'.$table.'":'.LF;
00243             foreach($list as $uid)  {
00244                 echo '  Flushing record "'.$table.':'.$uid.'": ';
00245                 if ($bypass = $this->cli_noExecutionCheck($table.':'.$uid)) {
00246                     echo $bypass;
00247                 } else {
00248                     $fields_values = array(
00249                         't3ver_wsid' => 0
00250                     );
00251                     $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table,'uid='.intval($uid),$fields_values);
00252                     echo 'DONE';
00253                 }
00254                 echo LF;
00255             }
00256         }
00257 
00258             // Delete unused placeholders
00259         foreach($resultArray['versions_unused_placeholders'] as $recID) {
00260             list($table,$uid)   = explode(':',$recID);
00261             echo 'Deleting unused placeholder (soft) "'.$table.':'.$uid.'": ';
00262             if ($bypass = $this->cli_noExecutionCheck($table.':'.$uid)) {
00263                 echo $bypass;
00264             } else {
00265 
00266                     // Execute CMD array:
00267                 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
00268                 $tce->stripslashes_values = FALSE;
00269                 $tce->start(array(),array());
00270                 $tce->deleteAction($table, $uid);
00271 
00272                     // Return errors if any:
00273                 if (count($tce->errorLog))  {
00274                     echo '  ERROR from "TCEmain":'.LF.'TCEmain:'.implode(LF.'TCEmain:',$tce->errorLog);
00275                 } else echo 'DONE';
00276             }
00277             echo LF;
00278         }
00279     }
00280 }
00281 
00282 ?>