Fixed: publishing many records may cause PHP timeout and leave workspace in half...
authorDmitry Dulepov <dmitry.dulepov@gmail.com>
Wed, 3 Jan 2007 14:27:47 +0000 (14:27 +0000)
committerDmitry Dulepov <dmitry.dulepov@gmail.com>
Wed, 3 Jan 2007 14:27:47 +0000 (14:27 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@1893 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/mod/user/ws/.htaccess [new file with mode: 0644]
typo3/mod/user/ws/index.php
typo3/mod/user/ws/progress.gif [new file with mode: 0644]
typo3/mod/user/ws/publish.php [new file with mode: 0644]
typo3/mod/user/ws/workspaceforms.php

index 8b33d30..e63010d 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 2006-01-03  Dmitry Dulepov  <dmitry@typo3.org>
 
        * Fixed bugs 3254, 3872, 4345: hide workspace selector if (1) no access to workspace module, or (2) only one workspace is available to user
+       * Fixed: publishing many records may cause PHP timeout and leave workspace in half-published state
 
 2006-12-27  Dmitry Dulepov  <dmitry@typo3.org>
 
diff --git a/typo3/mod/user/ws/.htaccess b/typo3/mod/user/ws/.htaccess
new file mode 100644 (file)
index 0000000..0127abe
--- /dev/null
@@ -0,0 +1,7 @@
+<FilesMatch "\.(gif|png)">\r
+    <IfModule mod_expires.c>\r
+        ExpiresActive on\r
+        ExpiresDefault "access plus 7 days"\r
+    </IfModule>\r
+       FileETag MTime Size\r
+</FilesMatch>\r
index 9ab8fc0..d454661 100755 (executable)
@@ -83,9 +83,6 @@
  * 1964:     function versionsInOtherWS($table,$uid)
  * 1994:     function showStageChangeLog($table,$id,$stageCommands)
  *
- *              SECTION: Processing
- * 2055:     function publishAction()
- *
  * TOTAL FUNCTIONS: 37
  * (This index is automatically created/updated by the extension "extdeveval")
  *
@@ -291,9 +288,6 @@ class SC_mod_user_ws_index extends t3lib_SCbase {
                        $this->content .= $this->doc->wrapScriptTags('top.location.href="' . $BACK_PATH . 'alt_main.php";');
                }
                else {
-                               // Perform workspace publishing action if buttons are pressed:
-                       $errors = $this->publishAction();
-
                                // Starting page:
                        $this->content.=$this->doc->startPage($LANG->getLL('title'));
                        $this->content.=$this->doc->header($LANG->getLL('title'));
@@ -303,7 +297,7 @@ class SC_mod_user_ws_index extends t3lib_SCbase {
                        $menuItems = array();
                        $menuItems[] = array(
                                'label' => $LANG->getLL('menuitem_review'),
-                               'content' => (count($errors) ? '<h3>' . $LANG->getLL('label_errors') . '</h3><br/>'.implode('<br/>',$errors).'<hr/>' : '').$this->moduleContent_publish()
+                               'content' => $this->moduleContent_publish()
                        );
                        $menuItems[] = array(
                                'label' => $LANG->getLL('menuitem_workspaces'),
@@ -397,10 +391,10 @@ class SC_mod_user_ws_index extends t3lib_SCbase {
                if ($GLOBALS['BE_USER']->workspace!==0) {
                        if ($this->publishAccess)       {
                                $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_publish_workspace_confirmation_1' :  'submit_publish_workspace_confirmation_2'));
-                               $actionLinks.= '<input type="submit" name="_publish" value="' . $LANG->getLL('submit_publish_workspace') . '" onclick="return confirm(' . $confirmation . ');"/>';
+                               $actionLinks.= '<input type="submit" name="_publish" value="' . $LANG->getLL('submit_publish_workspace') . '" onclick="if (confirm(' . $confirmation . ')) window.location.href=\'publish.php?swap=0\';return false"/>';
                                if ($GLOBALS['BE_USER']->workspaceSwapAccess()) {
                                        $confirmation = $LANG->JScharCode($LANG->getLL(($GLOBALS['BE_USER']->workspaceRec['publish_access'] & 1) ? 'submit_swap_workspace_confirmation_1' :  'submit_swap_workspace_confirmation_2'));
-                                       $actionLinks.= '<input type="submit" name="_swap" value="' . $LANG->getLL('submit_swap_workspace') . '" onclick="return confirm(' . $confirmation . ');" />';
+                                       $actionLinks.= '<input type="submit" name="_swap" value="' . $LANG->getLL('submit_swap_workspace') . '" onclick="if (confirm(' . $confirmation . ')) window.location.href=\'publish.php?swap=1\';return false ;" />';
                                }
                        } else {
                                $actionLinks.= $this->doc->icons(1) . $LANG->getLL('no_publish_permission');
@@ -2042,36 +2036,6 @@ class SC_mod_user_ws_index extends t3lib_SCbase {
 
 
 
-
-       /**********************************
-        *
-        * Processing
-        *
-        **********************************/
-
-       /**
-        * Will publish workspace if buttons are pressed
-        *
-        * @return      void
-        */
-       function publishAction()        {
-
-                       // If "Publish" or "Swap" buttons are pressed:
-               if (t3lib_div::_POST('_publish') || t3lib_div::_POST('_swap'))  {
-
-                               // Initialize workspace object and request all pending versions:
-                       $wslibObj = t3lib_div::makeInstance('wslib');
-                       $cmd = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, t3lib_div::_POST('_swap'));
-
-                               // Execute the commands:
-                       $tce = t3lib_div::makeInstance('t3lib_TCEmain');
-                       $tce->stripslashes_values = 0;
-                       $tce->start(array(), $cmd);
-                       $tce->process_cmdmap();
-
-                       return $tce->errorLog;
-               }
-       }
 }
 
 // Include extension?
diff --git a/typo3/mod/user/ws/progress.gif b/typo3/mod/user/ws/progress.gif
new file mode 100644 (file)
index 0000000..d9a0a6f
Binary files /dev/null and b/typo3/mod/user/ws/progress.gif differ
diff --git a/typo3/mod/user/ws/publish.php b/typo3/mod/user/ws/publish.php
new file mode 100644 (file)
index 0000000..402c494
--- /dev/null
@@ -0,0 +1,264 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Workspace publisher
+ *
+ * $Id: index.php 1613 2006-07-10 09:42:27Z liels_bugs $
+ *
+ * @author     Dmitry Dulepov <typo3@accio.lv>
+ */
+/**
+ * [CLASS/FUNCTION INDEX of SCRIPT]
+ *
+ *
+ *
+ *   70: class SC_mod_user_ws_publish extends t3lib_SCbase
+ *   83:     function init()
+ *   95:     function closeAndReload()
+ *  106:     function nextPortion(val)
+ *  127:     function main()
+ *  142:     function printContent()
+ *  151:     function getContent()
+ *  227:     function getRecords()
+ *  243:     function formatProgressBlock($messageLabel)
+ *
+ * TOTAL FUNCTIONS: 8
+ * (This index is automatically created/updated by the extension "extdeveval")
+ *
+ */
+
+
+// Initialize module:
+unset($MCONF);
+require('conf.php');
+require($BACK_PATH . 'init.php');
+require($BACK_PATH . 'template.php');
+$BE_USER->modAccess($MCONF, 1);
+
+// Include libraries of various kinds used inside:
+$LANG->includeLLFile('EXT:lang/locallang_mod_user_ws.xml');
+require_once(PATH_t3lib . 'class.t3lib_scbase.php');
+require_once(PATH_typo3 . 'mod/user/ws/class.wslib.php');
+require_once(PATH_t3lib . 'class.t3lib_tcemain.php');
+
+define('MAX_RECORDS_TO_PUBLISH', 30);
+
+class SC_mod_user_ws_publish extends t3lib_SCbase {
+
+       var     $isSwap;
+       var     $title;
+       var     $nextRecordNumber;
+       var     $publishData;
+       var     $recordCount;
+
+       /**
+        * Initializes the module. See <code>t3lib_SCbase::init()</code> for more information.
+        *
+        * @return      void
+        */
+       function init() {
+               // Setting module configuration:
+               $this->MCONF = $GLOBALS['MCONF'];
+
+               $this->isSwap = t3lib_div::_GP('swap');
+               $this->nextRecordNumber = t3lib_div::_GP('continue_publish');
+
+               // Initialize Document Template object:
+               $this->doc = t3lib_div::makeInstance('mediumDoc');
+               $this->doc->backPath = $GLOBALS['BACK_PATH'];
+               $this->doc->docType = 'xhtml_trans';
+               $this->doc->JScode = '<script type="text/javascript">/*<![CDATA[*/
+                       function closeAndReload() {
+                               //window.opener.location.reload(); window.close();
+                               window.location.href = \'index.php\';
+                       }
+
+                       function nextPortion(val) {
+                               setTimeout(\'window.location.href = "publish.php?continue_publish=\' + val + \'&swap=' . ($this->isSwap ? 1 : 0) . '"\', 750);
+                       }
+               /*]]>*/</script>
+               ';
+               $this->doc->inDocStyles = '
+               #progress-block { width: 450px; margin: 50px auto; text-align: center; }
+               H3 { margin-bottom: 20px; }
+               P, IMG { margin-bottom: 20px; }
+               #progress-block A { text-decoration: underline; }
+';
+
+               // Parent initialization:
+               t3lib_SCbase::init();
+       }
+
+       /**
+        * Creates module content.
+        *
+        * @return      void
+        */
+       function main() {
+               $this->title = $GLOBALS['LANG']->getLL($this->isSwap ? 'swap_title' : 'publish_title');
+
+               $content = $this->getContent(); // sets body parts to doc!
+
+               $this->content .= $this->doc->startPage($this->title);
+               $this->content .= $content;
+               $this->content .= $this->doc->endPage();
+       }
+
+       /**
+        * Outputs content.
+        *
+        * @return      void
+        */
+       function printContent() {
+               echo $this->content;
+       }
+
+       /**
+        * Performs action and generates content.
+        *
+        * @return      string          Generated content
+        */
+       function getContent() {
+               $content = '';
+               if ($this->nextRecordNumber) {
+                       // Prepare limited set of records
+                       $this->publishData = $GLOBALS['BE_USER']->getSessionData('workspacePublisher');
+                       $this->recordCount = $GLOBALS['BE_USER']->getSessionData('workspacePublisher_count');
+                       $limitedCmd = array(); $numRecs = 0;
+                       foreach ($this->publishData as $table => $recs) {
+                               foreach ($recs as $key => $value) {
+                                       $numRecs++;
+                                       $limitedCmd[$table][$key] = $value;
+                                       //$this->content .= $table.':'.$key.'<br />';
+                                       if ($numRecs == MAX_RECORDS_TO_PUBLISH) {
+                                               break;
+                                       }
+                               }
+                               if ($numRecs == MAX_RECORDS_TO_PUBLISH) {
+                                       break;
+                               }
+                       }
+
+                       if ($numRecs == 0) {
+                               // All done
+                               $GLOBALS['BE_USER']->setAndSaveSessionData('workspacePublisher', null);
+                               $GLOBALS['BE_USER']->setAndSaveSessionData('workspacePublisher_count', 0);
+                               $content .= '<div id="progress-block"><h3>' . $this->title . '</h3><p>';
+                               $content .= $GLOBALS['LANG']->getLL($this->isSwap ? 'workspace_swapped' : 'workspace_published');
+                               $content .= '</p><p><a href="index.php">' . $GLOBALS['LANG']->getLL('return_to_index') . '</a>';
+                               $content .= '</p></div>';
+                       }
+                       else {
+                               // Execute the commands:
+                               $tce = t3lib_div::makeInstance('t3lib_TCEmain');
+                               $tce->stripslashes_values = 0;
+                               $tce->start(array(), $limitedCmd);
+                               $tce->process_cmdmap();
+
+                               $errors = $tce->errorLog;
+                               if (count($errors) > 0) {
+                                       $content .= '<h3>' . $LANG->getLL('label_errors') . '</h3><br/>' . implode('<br/>',$errors);
+                                       $content .= '<br /><br /><a href="index.php">' . $GLOBALS['LANG']->getLL('return_to_index') . '</a>';
+                               }
+                               else {
+
+                                       // Unset processed records
+                                       foreach ($limitedCmd as $table => $recs) {
+                                               foreach ($recs as $key => $value) {
+                                                       unset($this->publishData[$table][$key]);
+                                               }
+                                       }
+                                       $GLOBALS['BE_USER']->setAndSaveSessionData('workspacePublisher', $this->publishData);
+                                       $content .= $this->formatProgressBlock($this->isSwap ? 'swap_status' : 'publish_status');
+                                       $this->doc->bodyTagAdditions = 'onload="nextPortion(' . ($this->nextRecordNumber + MAX_RECORDS_TO_PUBLISH) . ')"';
+                               }
+                       }
+               }
+               else {
+                       $this->getRecords();
+                       if ($this->recordCount > 0) {
+                               $GLOBALS['BE_USER']->setAndSaveSessionData('workspacePublisher', $this->publishData);
+                               $GLOBALS['BE_USER']->setAndSaveSessionData('workspacePublisher_count', $this->recordCount);
+                               $content .= $this->formatProgressBlock($this->isSwap ? 'swap_prepare' : 'publish_prepare');
+                               $this->doc->bodyTagAdditions = 'onload="nextPortion(1)"';
+                       }
+                       else {
+                               $this->doc->bodyTagAdditions = 'onload="closeAndReload()"';
+                       }
+               }
+               return $content;
+       }
+
+       /**
+        * Fetches command array for publishing and calculates number of records in it. Sets class members accordingly.
+        *
+        * @return      void
+        */
+       function getRecords() {
+               $wslibObj = t3lib_div::makeInstance('wslib');
+               $this->publishData = $wslibObj->getCmdArrayForPublishWS($GLOBALS['BE_USER']->workspace, $this->isSwap);
+
+               $this->recordCount = 0;
+               foreach ($this->publishData as $table => $recs) {
+                       $this->recordCount += count($recs);
+               }
+       }
+
+       /**
+        * Creates block with progress bar
+        *
+        * @param       string          $messageLabel Message label to display
+        * @return      string          Generated content
+        */
+       function formatProgressBlock($messageLabel) {
+               return '<div id="progress-block"><h3>' . $this->title . '</h3><p>' .
+                               sprintf($GLOBALS['LANG']->getLL($messageLabel),
+                               $this->nextRecordNumber,
+                               min($this->recordCount, $this->nextRecordNumber - 1 + MAX_RECORDS_TO_PUBLISH),
+                               $this->recordCount) . '<br />' .
+                               $GLOBALS['LANG']->getLL('please_wait') .
+                               '</p><img src="progress.gif" width="225" height="20" alt="" />' .
+                               '<p>' .
+                               $GLOBALS['LANG']->getLL('do_not_interrupt_publishing_1') .
+                               '<br />' .
+                               $GLOBALS['LANG']->getLL('do_not_interrupt_publishing_2') .
+                               '</p></div>';
+       }
+}
+
+
+// Include extension?
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/publish.php'])  {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/publish.php']);
+}
+
+// Make instance:
+$SOBE = t3lib_div::makeInstance('SC_mod_user_ws_publish');
+$SOBE->init();
+$SOBE->main();
+$SOBE->printContent();
+?>
\ No newline at end of file
index 7c5c11d..c754251 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2005 Dmitry Dulepov (typo3@accio.lv)
+*  (c) 1999-2006 Kasper Skaarhoj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -645,8 +645,8 @@ class user_SC_mod_user_ws_workspaceForms {
 }
 
 // Include extension?
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/class.mod_user_ws_workspaceForms.php']) {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/class.mod_user_ws_workspaceForms.php']);
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/workspaceforms.php'])   {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/user/ws/workspaceforms.php']);
 }
 
 // Make instance: