Added feature #13170: Workspace Owners should be manageable with groups as well ...
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / updates / class.tx_coreupdates_migrateworkspaces.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Tolleiv Nietsch <info@tolleiv.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28
29 /**
30 * Migrates workspaces from TYPO3 versions below 4.5.
31 *
32 * @author Tolleiv Nietsch <info@tolleiv.de>
33 * @version $Id$
34 */
35 class tx_coreupdates_migrateworkspaces extends tx_coreupdates_installsysexts {
36 public $versionNumber; // version number coming from t3lib_div::int_from_ver()
37
38 /**
39 * parent object
40 *
41 * @var tx_install
42 */
43 public $pObj;
44 public $userInput; // user input
45 public $sqlQueries;
46
47 /**
48 * Checks if an update is needed
49 *
50 * @param string &$description: The description for the update, which will be updated with a description of the script's purpose
51 * @return boolean whether an update is needed (true) or not (false)
52 */
53 public function checkForUpdate(&$description) {
54 $result = FALSE;
55 $description = 'Migrates the old hardcoded draft workspace to be a real workspace element and update workspace owner fields to support either users or groups.';
56
57 // TYPO3 version 4.5 and above
58 if ($this->versionNumber >= 4005000) {
59 $tables = array_keys($GLOBALS['TYPO3_DB']->admin_get_tables());
60 // sys_workspace table might not exists if version extension was never installed
61 if (in_array('sys_workspace', $tables)) {
62 $result = $this->isOldStyleAdminFieldUsed();
63 }
64
65 if (!$result) {
66 $this->includeTCA();
67 $result = $this->isDraftWorkspaceUsed();
68 }
69 }
70
71 return $result;
72 }
73
74 /**
75 * If there's any user-input which we'd love to process, this method allows to specify what
76 * kind of input we need.
77 *
78 * Since we don't need input this is left empty. It's still here to avoid that this is inherited.
79 *
80 * @param string $inputPrefix
81 * @return void
82 */
83 public function getUserInput($inputPrefix) {
84 return;
85 }
86
87 /**
88 * Performs the database update. Changes existing workspaces to use the new custom workspaces
89 *
90 * @param array &$databaseQueries: queries done in this update
91 * @param mixed &$customMessages: custom messages
92 * @return boolean whether it worked (true) or not (false)
93 */
94 public function performUpdate(array &$databaseQueries, &$customMessages) {
95 $result = TRUE;
96
97 // TYPO3 version below 4.5
98 if ($this->versionNumber < 4005000) {
99 return FALSE;
100 }
101
102 // There's no TCA available yet
103 $this->includeTCA();
104
105 // install version extension (especially when updating from very old TYPO3 versions
106 $this->installExtensions(array('version'));
107
108 // migrate all workspaces to support groups and be_users
109 if ($this->isOldStyleAdminFieldUsed()) {
110 $this->migrateAdminFieldToNewStyle();
111 }
112
113 // create a new dedicated "Draft" workspace and move all records to that new workspace
114 if ($this->isDraftWorkspaceUsed()) {
115 $draftWorkspaceId = $this->createWorkspace();
116 if (is_integer($draftWorkspaceId)) {
117 $this->migrateDraftWorkspaceRecordsToWorkspace($draftWorkspaceId);
118 }
119 }
120
121 if (is_array($this->sqlQueries) && is_array($databaseQueries)) {
122 $databaseQueries = array_merge($databaseQueries, $this->sqlQueries);
123 }
124
125 return $result;
126 }
127
128 /**
129 * Install a extensions
130 *
131 * @param array List of extension keys
132 * @return boolean Determines whether this was successful or not
133 */
134 protected function installExtensions($extensionKeys) {
135 if (!is_array($extensionKeys)) {
136 return FALSE;
137 }
138
139 $result = FALSE;
140 $extList = $this->addExtToList($extensionKeys);
141 if ($extList) {
142 $this->writeNewExtensionList($extList);
143 $result = TRUE;
144 }
145 return $result;
146 }
147
148 /**
149 * Check if any table contains draft-workspace records
150 *
151 * @return bool
152 */
153 protected function isDraftWorkspaceUsed() {
154 $foundDraftRecords = FALSE;
155
156 $tables = array_keys($GLOBALS['TCA']);
157 foreach ($tables as $table) {
158 $versioningVer = t3lib_div::intInRange($GLOBALS['TCA'][$table]['ctrl']['versioningWS'], 0, 2, 0);
159 if ($versioningVer > 0) {
160 if ($this->hasElementsOnWorkspace($table, -1)) {
161 $foundDraftRecords = TRUE;
162 break;
163 }
164 }
165 }
166
167 return $foundDraftRecords;
168 }
169
170 /**
171 * Check if there's any workspace which doesn't support the new admin-field format yet
172 * @return bool
173 */
174 protected function isOldStyleAdminFieldUsed() {
175 $where = 'adminusers != "" AND adminusers NOT LIKE "%be_users%" AND adminusers NOT LIKE "%be_groups%" AND deleted=0';
176 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'sys_workspace', $where);
177 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
178 return $count > 0;
179 }
180
181 /**
182 * Create a real workspace named "Draft"
183 *
184 * @return integer
185 */
186 protected function createWorkspace() {
187 // @todo who are the reviewers and owners for this workspace?
188 // In previous versions this was defined in be_groups/be_users with the setting "Edit in Draft"
189 $data = array(
190 'title' => 'Draft'
191 );
192 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_workspace', $data);
193 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
194 return $GLOBALS['TYPO3_DB']->sql_insert_id();
195 }
196
197 /**
198 * Migrates all elements from the old draft workspace to the new one.
199 *
200 * @param integer $wsId
201 * @return void
202 */
203 protected function migrateDraftWorkspaceRecordsToWorkspace($wsId) {
204 $tables = array_keys($GLOBALS['TCA']);
205 $where = 't3ver_wsid=-1';
206 $values = array(
207 't3ver_wsid' => intval($wsId)
208 );
209 foreach($tables as $table) {
210 $versioningVer = t3lib_div::intInRange($GLOBALS['TCA'][$table]['ctrl']['versioningWS'], 0, 2, 0);
211 if ($versioningVer > 0 && $this->hasElementsOnWorkspace($table, -1)) {
212 $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, $where, $values);
213 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
214 }
215 }
216 }
217
218 /**
219 * Migrate all workspace adminusers fields to support groups aswell,
220 * this means that the old comma separated list of uids (referring to be_users)
221 * is updated to be a list of uids with the tablename as prefix
222 *
223 * @return void
224 */
225 protected function migrateAdminFieldToNewStyle() {
226 $where = 'adminusers != "" AND adminusers NOT LIKE "%be_users%" AND adminusers NOT LIKE "%be_groups%" AND deleted=0';
227 $workspaces = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid, adminusers', 'sys_workspace', $where);
228 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
229 foreach ($workspaces as $workspace) {
230 $updateArray = array(
231 'adminusers' => 'be_users_' . implode(',be_users_', t3lib_div::trimExplode(',', $workspace['adminusers'], TRUE)),
232 );
233 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(
234 'sys_workspace',
235 'uid = "' . $workspace['uid'] . '"',
236 $updateArray
237 );
238 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
239 }
240 }
241
242 /**
243 * Includes the TCA definition of installed extensions.
244 *
245 * This method is used because usually the TCA is included within the init.php script, this doesn't happen
246 * if the install-tool is used, therefore this has to be done by hand.
247 *
248 * @return void
249 */
250 protected function includeTCA() {
251 global $TCA; // this is relevant because it's used within the included ext_tables.php files - do NOT remove it
252
253 include_once(TYPO3_tables_script ? PATH_typo3conf . TYPO3_tables_script : PATH_t3lib . 'stddb/tables.php');
254 // Extension additions
255 if ($GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE']) {
256 include_once(PATH_typo3conf . $GLOBALS['TYPO3_LOADED_EXT']['_CACHEFILE'] . '_ext_tables.php');
257 } else {
258 include_once(PATH_t3lib . 'stddb/load_ext_tables.php');
259 }
260 }
261
262 /**
263 * Determines whether a table has elements in a particular workspace.
264 *
265 * @param string $table Name of the table
266 * @param integer $workspaceId Id of the workspace
267 * @return boolean
268 */
269 protected function hasElementsOnWorkspace($table, $workspaceId) {
270 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
271 'uid',
272 $table,
273 't3ver_wsid=' . intval($workspaceId)
274 );
275
276 $this->sqlQueries[] = $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
277
278 return ($count > 0);
279 }
280 }
281 ?>