|
View:
New views
8 Messages
—
Rating Filter:
Alert me
|
|
|
#539 - Delete (Copy / Move) localized recordsHi,
I wanted to offer my help regarding the (very) old problems within the copy / move / delete operations in TCEmain for localized versions of records. I already provided a patch for #2314 (moving records with L10n-records) but in regards to handle delete and copy actions it's a bit more complicated and before I start spending time on that I'd like to get some input/confirmation from some of the Core members. So the basic "problem" is that whenever someone performs an action (copy,move,delete) TCEmain doesn't update the related l10n-records. The result is that the localizations are either "lost" because their parent record is missing in some way, or the system is messed up because l10n-records are not deleted. The "solution" sounds easy - just perform the same action with the l10n-records - but it isn't that easy because: 1) The user might not have the right to modify the other languages 2) The user might not want to perform the action (especially Copy) for the l10n-records Suggestions: Deleting and moving records is really "easy" because the l10n-records are useless without their parent anyways and therefore we could just perform the actions for all the l10n-records too. If the user has no right to do this then it's not a problem because we could just leave the "useless" l10n-records in place and wait for a system-cleanup (lowlevel-cleaner) to carry them away. For the Copy-mode I'd suggest to either - provide an additional "Copy with L10n-records" mode (side-by-side with the normal Copy-mode) or to provide a TSConfig setting where the behavior can be configured. Other concerns: In #539 Uschi brought up that it might be a problem if the new page doesn't provide all languages. Imho that's no "real" problem because if we would just leave this single record behind then it would be lost anyways and if we just copy it over to the new page there's a chance that the content is used again as soon as someone creates the page_language_overlay record for that language. Overall the user might just not be aware of the l10n-records and therefore he might mess up content in other languages by mistake. Imho this can't be solved within TCEmain - but as soon as the technical base is working the GUI should also be improved so that users get some informations whenever more than one record is updated. Looking forward to get some feedback - do you agree to my proposed solutions or how would just resolve them? These issues are very old, they cause lot's of confusion and especially in regards to have a clean system I hope to get rid of them soon :) Regards, Tolleiv ------------------------------------------------- bugs.typo3.org references: http://bugs.typo3.org/view.php?id=539 (delete issues) http://bugs.typo3.org/view.php?id=2314 (move issues) http://bugs.typo3.org/view.php?id=9566 (copy issues) there are also lot's of related issues (very often people's complains where posted in relation to TemplaVoila e.g. #2314 I guess because with TV it's not that obvious that localizations are also organized as records) --- www.tolleiv.de _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsTolleiv.Nietsch wrote:
Hi Tolleiv, > Deleting and moving records is really "easy" because the l10n-records > are useless without their parent anyways and therefore we could just > perform the actions for all the l10n-records too. If the user has no > right to do this then it's not a problem because we could just leave the > "useless" l10n-records in place and wait for a system-cleanup > (lowlevel-cleaner) to carry them away. Well, with leaving the translations behind you produce the same effect as before - lost translation records. Thus, for the case where a user doesn't have the right to move the records I would simply not move any of the records (including the original language record). > For the Copy-mode I'd suggest to either - provide an additional "Copy > with L10n-records" mode (side-by-side with the normal Copy-mode) or to > provide a TSConfig setting where the behavior can be configured. That would IMO just overcomplicate everything, I would simply do it like with moving: all or nothing. > Other concerns: > In #539 Uschi brought up that it might be a problem if the new page > doesn't provide all languages. Imho that's no "real" problem because if > we would just leave this single record behind then it would be lost > anyways and if we just copy it over to the new page there's a chance > that the content is used again as soon as someone creates the > page_language_overlay record for that language. agreed, just move everything. best Ingo -- Ingo Renner TYPO3 Core Developer, Release Manager TYPO3 4.2 _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsHi Tolleiv
> I wanted to offer my help regarding the (very) old problems within the > copy / move / delete operations in TCEmain for localized versions of > records. I'm stumbling over this again, I wanted to answer you at the time, but totally forgot. I have no time to look into this at the moment, sorry. Cheers -- Francois Suter Cobweb Development Sarl - http://www.cobweb.ch _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsFrancois Suter schrieb:
> Hi Tolleiv > >> I wanted to offer my help regarding the (very) old problems within the >> copy / move / delete operations in TCEmain for localized versions of >> records. > > I'm stumbling over this again, I wanted to answer you at the time, but > totally forgot. I have no time to look into this at the moment, sorry. > > Cheers > Just to keep you up-to-date. I plan to get some first patches ready until mid. October. I know that this is far too late for 4.3 but I think that's not so important since it seems that most parts of the community aren't really interested to get it soon. And the agencies should be able to apply the relevant patches manually anyways. Nevertheless I share Ingo's opinion that either everything or nothing should be moved. I also discussed it (offline) with Oliver Hader and he agreed too. Looking forward to get some more input :) Cheers -- Tolleiv Nietsch www.tolleiv.de - www.aoemedia.de _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsHi Tolleiv,
> I plan to get some first patches ready until mid. October. I know that > this is far too late for 4.3 but I think that's not so important since > it seems that most parts of the community aren't really interested to > get it soon. And the agencies should be able to apply the relevant > patches manually anyways. Great news, thanks for the update. Looking forward to testing your patches. Cheers -- Francois Suter Cobweb Development Sarl - http://www.cobweb.ch _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsHi,
as promised I've kind of a first version for these issues. The attached patch should resolve the problems with copying, moving and deleting records with l10n-overlays. I know that some stuff within the patch is not CGL-conform yet and I guess it wouldn't be a good idea to send it to the Core list within one chunk (it's more or less at least 4 chunks). But before I start to "decompose" everything again I'd like to get some feedback on it. The attach patch contains fixes for all three actions within any workspace. Whenever one of the actions is performed on a record it checks whether the user has the right to modify all related l10n-records and after the action was performed on the requested record it "just" reperforms the same action on the l10n-records as well. Maybe someone could do some functional checks and maybe someone from the Core-team could check whether the way how I knitted everything into the tcemain is fine (has a chance to be commited one day). Just to point out the relevance - if commited this resolves the issues #539, #2314, #4442, #4762, #8817, #9566 and a couple of duplicates :P In addition to these issues I've also "fixed" a small GUI problem - the Copy and the Cut icons within the list module should not be visible for l10n-records because it doesn't make sense at all to copy these records on their own. Therefore they're at least not visible within the "Localization view" of the the list-module. This is included in the patch - I'll open a new ticket on that as soon as the Copy/Move/Delete stuff made it to the Core. It would also be interesting if you could let me know whether this would be a "Bugfix" or a "Feature request" ;) Looking forward to get some feedback. Best regards, Tolleiv -- Tolleiv Nietsch www.tolleiv.de - www.aoemedia.de Index: t3lib/class.t3lib_tcemain.php =================================================================== --- t3lib/class.t3lib_tcemain.php (revision 6108) +++ t3lib/class.t3lib_tcemain.php (working copy) @@ -2731,100 +2731,109 @@ } // Now, the $uid is the actual record we will copy while $origUid is the record we asked to get copied - but that could be a live version. */ + + if ($this->doesRecordExist($table,$uid,'show')) { // This checks if the record can be selected which is all that a copy action requires. - $data = Array(); + if( $this->BE_USER->recordEditAccessInternals($table,$uid, false, false, true ) ) { //Used to check language and general editing rights + $data = Array(); - $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_wsid,t3ver_id,t3ver_label,t3ver_state,t3ver_swapmode,t3ver_count,t3ver_stage,t3ver_tstamp,'.$excludeFields,1)); + $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_wsid,t3ver_id,t3ver_label,t3ver_state,t3ver_swapmode,t3ver_count,t3ver_stage,t3ver_tstamp,'.$excludeFields,1)); - // $row = $this->recordInfo($table,$uid,'*'); - $row = t3lib_BEfunc::getRecordWSOL($table,$uid); // So it copies (and localized) content from workspace... - if (is_array($row)) { + // $row = $this->recordInfo($table,$uid,'*'); + $row = t3lib_BEfunc::getRecordWSOL($table,$uid); // So it copies (and localized) content from workspace... + if (is_array($row)) { - // Initializing: - $theNewID = uniqid('NEW'); - $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : ''; - $headerField = $TCA[$table]['ctrl']['label']; + // Initializing: + $theNewID = uniqid('NEW'); + $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : ''; + $headerField = $TCA[$table]['ctrl']['label']; - // Getting default data: - $defaultData = $this->newFieldArray($table); + // Getting default data: + $defaultData = $this->newFieldArray($table); - // Getting "copy-after" fields if applicable: - $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array(); + // Getting "copy-after" fields if applicable: + $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array(); - // Page TSconfig related: - $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid); // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the ID of a page, if the input is a page... - $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); - $tE = $this->getTableEntries($table,$TSConfig); + // Page TSconfig related: + $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid); // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the ID of a page, if the input is a page... + $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); + $tE = $this->getTableEntries($table,$TSConfig); - // Traverse ALL fields of the selected record: - foreach($row as $field => $value) { - if (!in_array($field,$nonFields)) { + // Traverse ALL fields of the selected record: + foreach($row as $field => $value) { + if (!in_array($field,$nonFields)) { - // Get TCA configuration for the field: - $conf = $TCA[$table]['columns'][$field]['config']; + // Get TCA configuration for the field: + $conf = $TCA[$table]['columns'][$field]['config']; - // Preparation/Processing of the value: - if ($field=='pid') { // "pid" is hardcoded of course: - $value = $destPid; - } elseif (isset($overrideValues[$field])) { // Override value... - $value = $overrideValues[$field]; - } elseif (isset($copyAfterFields[$field])) { // Copy-after value if available: - $value = $copyAfterFields[$field]; - } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) { // Revert to default for some fields: - $value = $defaultData[$field]; - } else { - // Hide at copy may override: - if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) { - $value=1; + // Preparation/Processing of the value: + if ($field=='pid') { // "pid" is hardcoded of course: + $value = $destPid; + } elseif (isset($overrideValues[$field])) { // Override value... + $value = $overrideValues[$field]; + } elseif (isset($copyAfterFields[$field])) { // Copy-after value if available: + $value = $copyAfterFields[$field]; + } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) { // Revert to default for some fields: + $value = $defaultData[$field]; + } else { + // Hide at copy may override: + if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) { + $value=1; + } + // Prepend label on copy: + if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) { + $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0); + } + // Processing based on the TCA config field type (files, references, flexforms...) + $value = $this->copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $row, $conf, $tscPID, $language); } - // Prepend label on copy: - if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) { - $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0); - } - // Processing based on the TCA config field type (files, references, flexforms...) - $value = $this->copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $row, $conf, $tscPID, $language); + + // Add value to array. + $data[$table][$theNewID][$field] = $value; } + } + // Overriding values: + if ($TCA[$table]['ctrl']['editlock']) { + $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0; + } - // Add value to array. - $data[$table][$theNewID][$field] = $value; + // Setting original UID: + if ($TCA[$table]['ctrl']['origUid']) { + $data[$table][$theNewID][$TCA[$table]['ctrl']['origUid']] = $uid; } - } - // Overriding values: - if ($TCA[$table]['ctrl']['editlock']) { - $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0; - } + // Do the copy by simply submitting the array through TCEmain: + $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain'); + /* @var $copyTCE t3lib_TCEmain */ + $copyTCE->stripslashes_values = 0; + $copyTCE->copyTree = $this->copyTree; + $copyTCE->cachedTSconfig = $this->cachedTSconfig; // Copy forth the cached TSconfig + $copyTCE->dontProcessTransformations=1; // Transformations should NOT be carried out during copy - // Setting original UID: - if ($TCA[$table]['ctrl']['origUid']) { - $data[$table][$theNewID][$TCA[$table]['ctrl']['origUid']] = $uid; - } + $copyTCE->start($data,'',$this->BE_USER); + $copyTCE->process_datamap(); - // Do the copy by simply submitting the array through TCEmain: - $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain'); - /* @var $copyTCE t3lib_TCEmain */ - $copyTCE->stripslashes_values = 0; - $copyTCE->copyTree = $this->copyTree; - $copyTCE->cachedTSconfig = $this->cachedTSconfig; // Copy forth the cached TSconfig - $copyTCE->dontProcessTransformations=1; // Transformations should NOT be carried out during copy + // Getting the new UID: + $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID]; + if ($theNewSQLID) { + $this->copyRecord_fixRTEmagicImages($table,t3lib_BEfunc::wsMapId($table,$theNewSQLID)); + $this->copyMappingArray[$table][$origUid] = $theNewSQLID; + } - $copyTCE->start($data,'',$this->BE_USER); - $copyTCE->process_datamap(); + // Copy back the cached TSconfig + $this->cachedTSconfig = $copyTCE->cachedTSconfig; + $this->errorLog = array_merge($this->errorLog,$copyTCE->errorLog); + unset($copyTCE); - // Getting the new UID: - $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID]; - if ($theNewSQLID) { - $this->copyRecord_fixRTEmagicImages($table,t3lib_BEfunc::wsMapId($table,$theNewSQLID)); - $this->copyMappingArray[$table][$origUid] = $theNewSQLID; - } + if($language == 0) { + //repointing the new translation records to the parent record we just created + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = $theNewSQLID; + $this->copyL10nOverlayRecords($table, $uid, $destPid, $first, $overrideValues, $excludeFields=''); + } - // Copy back the cached TSconfig - $this->cachedTSconfig = $copyTCE->cachedTSconfig; - $this->errorLog = array_merge($this->errorLog,$copyTCE->errorLog); - unset($copyTCE); - - return $theNewSQLID; - } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!'); + return $theNewSQLID; + } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!'); + } else $this->log($table,$uid,3,0,1,'Attempt to copy record without having permissions to do so. ['.$this->BE_USER->errorMsg.'].'); } else $this->log($table,$uid,3,0,1,'Attempt to copy record without permission'); } } @@ -3367,7 +3376,26 @@ + /** + * Find l10n-overlay records and perform the requested move action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @param string $destPid: Position to move to + * @return void + */ + function copyL10nOverlayRecords($table, $uid, $destPid, $first=0, $overrideValues=array(), $excludeFields='') { + //there's no need to perform this for page-records + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->copyRecord($table, $record['uid'], $destPid, $first, $overrideValues, $excludeFields, $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); + } + } + } @@ -3377,6 +3405,7 @@ + /********************************************* * * Cmd: Moving, Localizing @@ -3424,7 +3453,7 @@ } // Checking if there is anything else disallowing moving the record by checking if editing is allowed - $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table,$uid); + $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table,$uid, false, false, true ); // If moving is allowed, begin the processing: if ($mayEditAccess) { @@ -3539,6 +3568,14 @@ $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.']'; + // moving localized records requires to keep localization-settings for the placeholder too + if( array_key_exists('languageField', $GLOBALS['TCA'][$table]['ctrl']) && array_key_exists('transOrigPointerField', $GLOBALS['TCA'][$table]['ctrl']) ) { + $l10nParentRec = t3lib_BEfunc::getRecord($table,$uid); + $newVersion_placeholderFieldArray[ $GLOBALS['TCA'][$table]['ctrl']['languageField'] ] = $l10nParentRec[ $GLOBALS['TCA'][$table]['ctrl']['languageField'] ]; + $newVersion_placeholderFieldArray[ $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ] = $l10nParentRec[ $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ]; + unset($l10nParentRec); + } + $newVersion_placeholderFieldArray['pid'] = 0; // Initially, create at root level. $id = 'NEW_MOVE_PLH'; $this->insertDB($table,$id,$newVersion_placeholderFieldArray,FALSE); // Saving placeholder as 'original' @@ -3551,6 +3588,9 @@ $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); } + + //check for the localizations of that element and move them as well + $this->moveL10nOverlayRecords($table,$uid,$destPid); } /** @@ -3608,6 +3648,8 @@ $this->moveRecord_procFields($table,$uid,$destPid); // Create query for update: $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + // check for the localizations of that element + $this->moveL10nOverlayRecords($table,$uid,$destPid); // Call post processing hooks: foreach($hookObjectsArr as $hookObj) { @@ -3651,6 +3693,8 @@ $this->moveRecord_procFields($table,$uid,$destPid); // Create query for update: $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + // check for the localizations of that element + $this->moveL10nOverlayRecords($table,$uid,$destPid); // Call post processing hooks: foreach($hookObjectsArr as $hookObj) { @@ -3749,6 +3793,27 @@ } /** + * Find l10n-overlay records and perform the requested move action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @param string $destPid: Position to move to + * @return void + */ + function moveL10nOverlayRecords($table,$uid,$destPid) { + //there's no need to perform this for page-records + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->moveRecord( $table, $record['uid'], $destPid ); + } + } + } + + /** * Localizes a record to another system language * In reality it only works if transOrigPointerTable is not set. For "pages" the implementation is hardcoded * @@ -4013,6 +4078,7 @@ } else { // Otherwise, try to delete by versioning: $this->versionizeRecord($table,$id,'DELETED!',TRUE); + $this->deleteL10nOverlayRecords($table,$id); } } } @@ -4088,7 +4154,7 @@ global $TCA; // Checking if there is anything else disallowing deleting the record by checking if editing is allowed - $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, FALSE, $undeleteRecord); + $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, FALSE, $undeleteRecord, TRUE ); $uid = intval($uid); if ($TCA[$table] && $uid) { @@ -4114,10 +4180,14 @@ if ($TCA[$table]['ctrl']['sortby'] && !$undeleteRecord) { $updateFields[$TCA[$table]['ctrl']['sortby']] = 1000000000; } - // before (un-)deleting this record, check for child records or references $this->deleteRecord_procFields($table, $uid, $undeleteRecord); $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + + // delete all l10n records aswell, impossible during undelete because it might bring too many records back to life + if( !$undeleteRecord ) { + $this->deleteL10nOverlayRecords($table, $uid); + } } else { // Fetches all fields with flexforms and look for files to delete: @@ -4149,6 +4219,8 @@ // Delete the hard way...: $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid='.intval($uid)); + + $this->deleteL10nOverlayRecords($table, $uid); } $state = $undeleteRecord ? 1 : 3; // 1 means insert, 3 means delete @@ -4413,13 +4485,33 @@ } } + /** + * Find l10n-overlay records and perform the requested delete action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @param string $destPid: Position to move to + * @return void + */ + function deleteL10nOverlayRecords($table, $uid) { + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->deleteAction($table, intval($record['t3ver_oid'])>0?intval($record['t3ver_oid']):intval($record['uid'])); + } + } + } + + /********************************************* * * Cmd: Versioning @@ -4620,6 +4712,10 @@ if ($TCA[$table]['ctrl']['sortby']) { $keepFields[] = $TCA[$table]['ctrl']['sortby']; } + // l10n-fields must be kept otherwise the localization will be lost during the publishing + if ( $TCA[$table]['ctrl']['transOrigPointerField'] ) { + $keepFields[] = $TCA[$table]['ctrl']['transOrigPointerField']; + } // Swap "keepfields" foreach($keepFields as $fN) { Index: t3lib/class.t3lib_userauthgroup.php =================================================================== --- t3lib/class.t3lib_userauthgroup.php (revision 6108) +++ t3lib/class.t3lib_userauthgroup.php (working copy) @@ -538,6 +538,39 @@ } /** + * Check if user has access to all existing localizations for a certain record + * + * @param array $record + * @return boolean + */ + function checkFullLanguagesAccess( $table, $record ) { + $recordLocalizationAccess = $this->checkLanguageAccess(0); + if ($recordLocalizationAccess && t3lib_BEfunc::isTableLocalizable($table) ) { + + $pointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; + + $recordLocalizations = t3lib_BEfunc::getRecordsByField( + $table, + $pointerField, + $record[$pointerField]>0 ? $record[$pointerField] : $record['uid'], + '', //AND '.$GLOBALS['TCA'][$table]['ctrl']['languageField'].'>0 '.($andWhereClause ? ' '.$andWhereClause : ''), + '', + '', + '1' + ); + + if(is_array($recordLocalizations)) { + foreach($recordLocalizations as $localization) { + $recordLocalizationAccess = $recordLocalizationAccess && $this->checkLanguageAccess( $localization[$GLOBALS['TCA'][$table]['ctrl']['languageField']] ); + if(!$recordLocalizationAccess) break; + } + } + + } + return $recordLocalizationAccess; + } + + /** * Checking if a user has editing access to a record from a $TCA table. * The checks does not take page permissions and other "environmental" things into account. It only deal with record internals; If any values in the record fields disallows it. * For instance languages settings, authMode selector boxes are evaluated (and maybe more in the future). @@ -550,7 +583,7 @@ * @param boolean Set, if testing a deleted record array. * @return boolean True if OK, otherwise false */ - function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE) { + function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE, $checkFullLanguageAccess = FALSE) { global $TCA; if (isset($TCA[$table])) { @@ -578,6 +611,9 @@ if (!$this->checkLanguageAccess($idOrRow[$TCA[$table]['ctrl']['languageField']])) { $this->errorMsg = 'ERROR: Language was not allowed.'; return FALSE; + } elseif( $checkFullLanguageAccess && !$this->checkFullLanguagesAccess($table, $idOrRow ) ) { + $this->errorMsg = 'ERROR: Related/affected language was not allowed.'; + return FALSE; } } else { $this->errorMsg = 'ERROR: The "languageField" field named "'.$TCA[$table]['ctrl']['languageField'].'" was not found in testing record!'; Index: typo3/class.db_list_extra.inc =================================================================== --- typo3/class.db_list_extra.inc (revision 6108) +++ typo3/class.db_list_extra.inc (working copy) @@ -1322,17 +1322,17 @@ $cells=array(); $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon; - + $isL10nOverlay = $this->localizationView && $row[$TCA[$table]['ctrl']['transOrigPointerField']]!=0; // Return blank, if disabled: // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel: if ($this->clipObj->current=='normal') { // For the "Normal" pad: // Show copy/cut icons: $isSel = (string)$this->clipObj->isSelected($table,$row['uid']); - $cells['copy']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'. + $cells['copy']= $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'. '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy'.($isSel=='copy'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.copy',1).'" alt="" />'. '</a>'; - $cells['cut']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'. + $cells['cut']= $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'. '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_cut'.($isSel=='cut'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.cut',1).'" alt="" />'. '</a>'; @@ -1355,7 +1355,7 @@ } // Adding the checkbox to the panel: - $cells['select']='<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />'; + $cells['select']= $isL10nOverlay ? $this->spaceIcon : '<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />'; } // Now, looking for selected elements from the current table: _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsHi Tolleiv,
> as promised I've kind of a first version for these issues. > The attached patch should resolve the problems with copying, moving and > deleting records with l10n-overlays. Thanks for this patch. I don't have time to test it right now, but I hope I'll be able to by the end of the week. Cheers -- Francois Suter Cobweb Development Sarl - http://www.cobweb.ch _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
|
|
Re: #539 - Delete (Copy / Move) localized recordsFrancois Suter schrieb:
> > Thanks for this patch. I don't have time to test it right now, but I > hope I'll be able to by the end of the week. > Great - take your time - we at AOE are testing this internally within the next days too... I've attached a new (AllInOne) version of the patch which fixes one more issue within the List-Module. Cheers, Tolleiv -- Tolleiv Nietsch www.tolleiv.de - www.aoemedia.de Index: t3lib/class.t3lib_tcemain.php =================================================================== --- t3lib/class.t3lib_tcemain.php (revision 6145) +++ t3lib/class.t3lib_tcemain.php (working copy) @@ -2733,99 +2733,106 @@ // Now, the $uid is the actual record we will copy while $origUid is the record we asked to get copied - but that could be a live version. */ if ($this->doesRecordExist($table,$uid,'show')) { // This checks if the record can be selected which is all that a copy action requires. - $data = Array(); + if( $this->BE_USER->recordEditAccessInternals($table,$uid, false, false, true ) ) { //Used to check language and general editing rights + $data = Array(); - $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_wsid,t3ver_id,t3ver_label,t3ver_state,t3ver_swapmode,t3ver_count,t3ver_stage,t3ver_tstamp,'.$excludeFields,1)); + $nonFields = array_unique(t3lib_div::trimExplode(',','uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_wsid,t3ver_id,t3ver_label,t3ver_state,t3ver_swapmode,t3ver_count,t3ver_stage,t3ver_tstamp,'.$excludeFields,1)); - // $row = $this->recordInfo($table,$uid,'*'); - $row = t3lib_BEfunc::getRecordWSOL($table,$uid); // So it copies (and localized) content from workspace... - if (is_array($row)) { + // $row = $this->recordInfo($table,$uid,'*'); + $row = t3lib_BEfunc::getRecordWSOL($table,$uid); // So it copies (and localized) content from workspace... + if (is_array($row)) { - // Initializing: - $theNewID = uniqid('NEW'); - $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : ''; - $headerField = $TCA[$table]['ctrl']['label']; + // Initializing: + $theNewID = uniqid('NEW'); + $enableField = isset($TCA[$table]['ctrl']['enablecolumns']) ? $TCA[$table]['ctrl']['enablecolumns']['disabled'] : ''; + $headerField = $TCA[$table]['ctrl']['label']; - // Getting default data: - $defaultData = $this->newFieldArray($table); + // Getting default data: + $defaultData = $this->newFieldArray($table); - // Getting "copy-after" fields if applicable: - $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array(); + // Getting "copy-after" fields if applicable: + $copyAfterFields = $destPid<0 ? $this->fixCopyAfterDuplFields($table,$uid,abs($destPid),0) : array(); - // Page TSconfig related: - $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid); // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the ID of a page, if the input is a page... - $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); - $tE = $this->getTableEntries($table,$TSConfig); + // Page TSconfig related: + $tscPID = t3lib_BEfunc::getTSconfig_pidValue($table,$uid,$destPid); // NOT using t3lib_BEfunc::getTSCpid() because we need the real pid - not the ID of a page, if the input is a page... + $TSConfig = $this->getTCEMAIN_TSconfig($tscPID); + $tE = $this->getTableEntries($table,$TSConfig); - // Traverse ALL fields of the selected record: - foreach($row as $field => $value) { - if (!in_array($field,$nonFields)) { + // Traverse ALL fields of the selected record: + foreach($row as $field => $value) { + if (!in_array($field,$nonFields)) { - // Get TCA configuration for the field: - $conf = $TCA[$table]['columns'][$field]['config']; + // Get TCA configuration for the field: + $conf = $TCA[$table]['columns'][$field]['config']; - // Preparation/Processing of the value: - if ($field=='pid') { // "pid" is hardcoded of course: - $value = $destPid; - } elseif (isset($overrideValues[$field])) { // Override value... - $value = $overrideValues[$field]; - } elseif (isset($copyAfterFields[$field])) { // Copy-after value if available: - $value = $copyAfterFields[$field]; - } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) { // Revert to default for some fields: - $value = $defaultData[$field]; - } else { - // Hide at copy may override: - if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) { - $value=1; + // Preparation/Processing of the value: + if ($field=='pid') { // "pid" is hardcoded of course: + $value = $destPid; + } elseif (isset($overrideValues[$field])) { // Override value... + $value = $overrideValues[$field]; + } elseif (isset($copyAfterFields[$field])) { // Copy-after value if available: + $value = $copyAfterFields[$field]; + } elseif ($TCA[$table]['ctrl']['setToDefaultOnCopy'] && t3lib_div::inList($TCA[$table]['ctrl']['setToDefaultOnCopy'],$field)) { // Revert to default for some fields: + $value = $defaultData[$field]; + } else { + // Hide at copy may override: + if ($first && $field==$enableField && $TCA[$table]['ctrl']['hideAtCopy'] && !$this->neverHideAtCopy && !$tE['disableHideAtCopy']) { + $value=1; + } + // Prepend label on copy: + if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) { + $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0); + } + // Processing based on the TCA config field type (files, references, flexforms...) + $value = $this->copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $row, $conf, $tscPID, $language); } - // Prepend label on copy: - if ($first && $field==$headerField && $TCA[$table]['ctrl']['prependAtCopy'] && !$tE['disablePrependAtCopy']) { - $value = $this->getCopyHeader($table,$this->resolvePid($table,$destPid),$field,$this->clearPrefixFromValue($table,$value),0); - } - // Processing based on the TCA config field type (files, references, flexforms...) - $value = $this->copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $row, $conf, $tscPID, $language); + + // Add value to array. + $data[$table][$theNewID][$field] = $value; } + } + // Overriding values: + if ($TCA[$table]['ctrl']['editlock']) { + $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0; + } - // Add value to array. - $data[$table][$theNewID][$field] = $value; + // Setting original UID: + if ($TCA[$table]['ctrl']['origUid']) { + $data[$table][$theNewID][$TCA[$table]['ctrl']['origUid']] = $uid; } - } - // Overriding values: - if ($TCA[$table]['ctrl']['editlock']) { - $data[$table][$theNewID][$TCA[$table]['ctrl']['editlock']] = 0; - } + // Do the copy by simply submitting the array through TCEmain: + $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain'); + /* @var $copyTCE t3lib_TCEmain */ + $copyTCE->stripslashes_values = 0; + $copyTCE->copyTree = $this->copyTree; + $copyTCE->cachedTSconfig = $this->cachedTSconfig; // Copy forth the cached TSconfig + $copyTCE->dontProcessTransformations=1; // Transformations should NOT be carried out during copy - // Setting original UID: - if ($TCA[$table]['ctrl']['origUid']) { - $data[$table][$theNewID][$TCA[$table]['ctrl']['origUid']] = $uid; - } + $copyTCE->start($data,'',$this->BE_USER); + $copyTCE->process_datamap(); - // Do the copy by simply submitting the array through TCEmain: - $copyTCE = t3lib_div::makeInstance('t3lib_TCEmain'); - /* @var $copyTCE t3lib_TCEmain */ - $copyTCE->stripslashes_values = 0; - $copyTCE->copyTree = $this->copyTree; - $copyTCE->cachedTSconfig = $this->cachedTSconfig; // Copy forth the cached TSconfig - $copyTCE->dontProcessTransformations=1; // Transformations should NOT be carried out during copy + // Getting the new UID: + $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID]; + if ($theNewSQLID) { + $this->copyRecord_fixRTEmagicImages($table,t3lib_BEfunc::wsMapId($table,$theNewSQLID)); + $this->copyMappingArray[$table][$origUid] = $theNewSQLID; + } - $copyTCE->start($data,'',$this->BE_USER); - $copyTCE->process_datamap(); + // Copy back the cached TSconfig + $this->cachedTSconfig = $copyTCE->cachedTSconfig; + $this->errorLog = array_merge($this->errorLog,$copyTCE->errorLog); + unset($copyTCE); - // Getting the new UID: - $theNewSQLID = $copyTCE->substNEWwithIDs[$theNewID]; - if ($theNewSQLID) { - $this->copyRecord_fixRTEmagicImages($table,t3lib_BEfunc::wsMapId($table,$theNewSQLID)); - $this->copyMappingArray[$table][$origUid] = $theNewSQLID; - } + if($language == 0) { + //repointing the new translation records to the parent record we just created + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = $theNewSQLID; + $this->copyL10nOverlayRecords($table, $uid, $destPid, $first, $overrideValues, $excludeFields=''); + } - // Copy back the cached TSconfig - $this->cachedTSconfig = $copyTCE->cachedTSconfig; - $this->errorLog = array_merge($this->errorLog,$copyTCE->errorLog); - unset($copyTCE); - - return $theNewSQLID; - } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!'); + return $theNewSQLID; + } else $this->log($table,$uid,3,0,1,'Attempt to copy record that did not exist!'); + } else $this->log($table,$uid,3,0,1,'Attempt to copy record without having permissions to do so. ['.$this->BE_USER->errorMsg.'].'); } else $this->log($table,$uid,3,0,1,'Attempt to copy record without permission'); } } @@ -3368,7 +3375,26 @@ + /** + * Find l10n-overlay records and perform the requested move action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @param string $destPid: Position to move to + * @return void + */ + function copyL10nOverlayRecords($table, $uid, $destPid, $first=0, $overrideValues=array(), $excludeFields='') { + //there's no need to perform this for page-records + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->copyRecord($table, $record['uid'], $destPid, $first, $overrideValues, $excludeFields, $record[$GLOBALS['TCA'][$table]['ctrl']['languageField']]); + } + } + } @@ -3378,6 +3404,7 @@ + /********************************************* * * Cmd: Moving, Localizing @@ -3425,7 +3452,7 @@ } // Checking if there is anything else disallowing moving the record by checking if editing is allowed - $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table,$uid); + $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, false, false, true ); // If moving is allowed, begin the processing: if ($mayEditAccess) { @@ -3540,6 +3567,14 @@ $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.']'; + // moving localized records requires to keep localization-settings for the placeholder too + if( array_key_exists('languageField', $GLOBALS['TCA'][$table]['ctrl']) && array_key_exists('transOrigPointerField', $GLOBALS['TCA'][$table]['ctrl']) ) { + $l10nParentRec = t3lib_BEfunc::getRecord( $table, $uid ); + $newVersion_placeholderFieldArray[ $GLOBALS['TCA'][$table]['ctrl']['languageField'] ] = $l10nParentRec[ $GLOBALS['TCA'][$table]['ctrl']['languageField'] ]; + $newVersion_placeholderFieldArray[ $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ] = $l10nParentRec[ $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ]; + unset( $l10nParentRec ); + } + $newVersion_placeholderFieldArray['pid'] = 0; // Initially, create at root level. $id = 'NEW_MOVE_PLH'; $this->insertDB($table,$id,$newVersion_placeholderFieldArray,FALSE); // Saving placeholder as 'original' @@ -3552,6 +3587,9 @@ $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); } + + //check for the localizations of that element and move them as well + $this->moveL10nOverlayRecords( $table, $uid, $destPid ); } /** @@ -3609,6 +3647,8 @@ $this->moveRecord_procFields($table,$uid,$destPid); // Create query for update: $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + // check for the localizations of that element + $this->moveL10nOverlayRecords( $table, $uid, $destPid ); // Call post processing hooks: foreach($hookObjectsArr as $hookObj) { @@ -3652,6 +3692,8 @@ $this->moveRecord_procFields($table,$uid,$destPid); // Create query for update: $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + // check for the localizations of that element + $this->moveL10nOverlayRecords( $table, $uid, $destPid ); // Call post processing hooks: foreach($hookObjectsArr as $hookObj) { @@ -3750,6 +3792,27 @@ } /** + * Find l10n-overlay records and perform the requested move action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @param string $destPid: Position to move to + * @return void + */ + function moveL10nOverlayRecords( $table, $uid, $destPid ) { + //there's no need to perform this for page-records + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->moveRecord( $table, $record['uid'], $destPid ); + } + } + } + + /** * Localizes a record to another system language * In reality it only works if transOrigPointerTable is not set. For "pages" the implementation is hardcoded * @@ -4014,6 +4077,7 @@ } else { // Otherwise, try to delete by versioning: $this->versionizeRecord($table,$id,'DELETED!',TRUE); + $this->deleteL10nOverlayRecords( $table, $id ); } } } @@ -4089,7 +4153,7 @@ global $TCA; // Checking if there is anything else disallowing deleting the record by checking if editing is allowed - $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, FALSE, $undeleteRecord); + $mayEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, FALSE, $undeleteRecord, TRUE ); $uid = intval($uid); if ($TCA[$table] && $uid) { @@ -4119,6 +4183,11 @@ // before (un-)deleting this record, check for child records or references $this->deleteRecord_procFields($table, $uid, $undeleteRecord); $GLOBALS['TYPO3_DB']->exec_UPDATEquery($table, 'uid='.intval($uid), $updateFields); + + // delete all l10n records aswell, impossible during undelete because it might bring too many records back to life + if( !$undeleteRecord ) { + $this->deleteL10nOverlayRecords( $table, $uid ); + } } else { // Fetches all fields with flexforms and look for files to delete: @@ -4150,6 +4219,8 @@ // Delete the hard way...: $GLOBALS['TYPO3_DB']->exec_DELETEquery($table, 'uid='.intval($uid)); + + $this->deleteL10nOverlayRecords( $table, $uid ); } $state = $undeleteRecord ? 1 : 3; // 1 means insert, 3 means delete @@ -4414,13 +4485,32 @@ } } + /** + * Find l10n-overlay records and perform the requested delete action for these records. + * + * @param string $table: Record Table + * @param string $uid: Record UID + * @return void + */ + function deleteL10nOverlayRecords( $table, $uid ) { + if( $table == 'pages' ) return; + t3lib_div::loadTCA( $table ); + $l10nRecords = t3lib_BEfunc::getRecordsByField( $table, $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $uid ); + if( is_array($l10nRecords) ) { + foreach( $l10nRecords as $record ) { + $this->deleteAction( $table, intval($record['t3ver_oid'])>0?intval($record['t3ver_oid']):intval($record['uid']) ); + } + } + } + + /********************************************* * * Cmd: Versioning @@ -4621,6 +4711,10 @@ if ($TCA[$table]['ctrl']['sortby']) { $keepFields[] = $TCA[$table]['ctrl']['sortby']; } + // l10n-fields must be kept otherwise the localization will be lost during the publishing + if ( $TCA[$table]['ctrl']['transOrigPointerField'] ) { + $keepFields[] = $TCA[$table]['ctrl']['transOrigPointerField']; + } // Swap "keepfields" foreach($keepFields as $fN) { Index: t3lib/class.t3lib_userauthgroup.php =================================================================== --- t3lib/class.t3lib_userauthgroup.php (revision 6145) +++ t3lib/class.t3lib_userauthgroup.php (working copy) @@ -538,6 +538,39 @@ } /** + * Check if user has access to all existing localizations for a certain record + * + * @param array $record + * @return boolean + */ + function checkFullLanguagesAccess( $table, $record ) { + $recordLocalizationAccess = $this->checkLanguageAccess(0); + if ($recordLocalizationAccess && t3lib_BEfunc::isTableLocalizable($table) ) { + + $pointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; + + $recordLocalizations = t3lib_BEfunc::getRecordsByField( + $table, + $pointerField, + $record[$pointerField]>0 ? $record[$pointerField] : $record['uid'], + '', //AND '.$GLOBALS['TCA'][$table]['ctrl']['languageField'].'>0 '.($andWhereClause ? ' '.$andWhereClause : ''), + '', + '', + '1' + ); + + if( is_array($recordLocalizations) ) { + foreach( $recordLocalizations as $localization ) { + $recordLocalizationAccess = $recordLocalizationAccess && $this->checkLanguageAccess( $localization[$GLOBALS['TCA'][$table]['ctrl']['languageField']] ); + if( !$recordLocalizationAccess ) break; + } + } + + } + return $recordLocalizationAccess; + } + + /** * Checking if a user has editing access to a record from a $TCA table. * The checks does not take page permissions and other "environmental" things into account. It only deal with record internals; If any values in the record fields disallows it. * For instance languages settings, authMode selector boxes are evaluated (and maybe more in the future). @@ -548,9 +581,10 @@ * @param mixed If integer, then this is the ID of the record. If Array this just represents fields in the record. * @param boolean Set, if testing a new (non-existing) record array. Will disable certain checks that doesn't make much sense in that context. * @param boolean Set, if testing a deleted record array. + * @param boolean Set, whenever access to all translations of the record is required * @return boolean True if OK, otherwise false */ - function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE) { + function recordEditAccessInternals($table, $idOrRow, $newRecord = FALSE, $deletedRecord = FALSE, $checkFullLanguageAccess = FALSE) { global $TCA; if (isset($TCA[$table])) { @@ -578,6 +612,9 @@ if (!$this->checkLanguageAccess($idOrRow[$TCA[$table]['ctrl']['languageField']])) { $this->errorMsg = 'ERROR: Language was not allowed.'; return FALSE; + } elseif( $checkFullLanguageAccess && !$this->checkFullLanguagesAccess($table, $idOrRow ) ) { + $this->errorMsg = 'ERROR: Related/affected language was not allowed.'; + return FALSE; } } else { $this->errorMsg = 'ERROR: The "languageField" field named "'.$TCA[$table]['ctrl']['languageField'].'" was not found in testing record!'; Index: typo3/class.db_list_extra.inc =================================================================== --- typo3/class.db_list_extra.inc (revision 6145) +++ typo3/class.db_list_extra.inc (working copy) @@ -551,6 +551,11 @@ // For each available translation, render the record: if (is_array($this->translations)) { foreach ($this->translations as $lRow) { + // $lRow isn't always what we want - if record was moved we've to work with the placeholder records otherwise the list is messed up a bit + if($row['t3ver_state'] == 3 && $row['t3ver_wsid'] != 0) { + $tmpRow = t3lib_BEfunc::getRecordRaw($table, 't3ver_state=3 and t3ver_move_id="'.intval( $lRow['uid']).'"', $selFieldList); + $lRow = is_array($tmpRow)?$tmpRow:$lRow; + } // 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']])) { @@ -1322,17 +1327,18 @@ $cells=array(); $cells['pasteAfter'] = $cells['pasteInto'] = $this->spaceIcon; - + //enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them + $isL10nOverlay = $this->localizationView && $row[$TCA[$table]['ctrl']['transOrigPointerField']]!=0; // Return blank, if disabled: // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel: if ($this->clipObj->current=='normal') { // For the "Normal" pad: // Show copy/cut icons: $isSel = (string)$this->clipObj->isSelected($table,$row['uid']); - $cells['copy']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'. + $cells['copy']= $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],1,($isSel=='copy'),array('returnUrl'=>'')).'\');').'">'. '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_copy'.($isSel=='copy'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.copy',1).'" alt="" />'. '</a>'; - $cells['cut']='<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'. + $cells['cut']= $isL10nOverlay ? $this->spaceIcon : '<a href="#" onclick="'.htmlspecialchars('return jumpSelf(\''.$this->clipObj->selUrlDB($table,$row['uid'],0,($isSel=='cut'),array('returnUrl'=>'')).'\');').'">'. '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_cut'.($isSel=='cut'?'_h':'').'.gif','width="12" height="12"').' title="'.$LANG->sL('LLL:EXT:lang/locallang_core.php:cm.cut',1).'" alt="" />'. '</a>'; @@ -1355,13 +1361,13 @@ } // Adding the checkbox to the panel: - $cells['select']='<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />'; + $cells['select']= $isL10nOverlay ? $this->spaceIcon : '<input type="hidden" name="CBH['.$n.']" value="0" /><input type="checkbox" name="CBC['.$n.']" value="1" class="smallCheckboxes"'.$checked.' />'; } // Now, looking for selected elements from the current table: $elFromTable = $this->clipObj->elFromTable($table); if (count($elFromTable) && $TCA[$table]['ctrl']['sortby']) { // IF elements are found and they can be individually ordered, then add a "paste after" icon: - $cells['pasteAfter']='<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'. + $cells['pasteAfter']= $isL10nOverlay ? $this->spaceIcon : '<a href="'.htmlspecialchars($this->clipObj->pasteUrl($table,-$row['uid'])).'" onclick="'.htmlspecialchars('return '.$this->clipObj->confirmMsg($table,$row,'after',$elFromTable)).'">'. '<img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/clip_pasteafter.gif','width="12" height="12"').' title="'.$LANG->getLL('clip_pasteAfter',1).'" alt="" />'. '</a>'; } _______________________________________________ TYPO3-dev mailing list TYPO3-dev@... http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev |
| Free embeddable forum powered by Nabble | Forum Help |