Documentation TYPO3 par Ameos

class.tx_impexp.php

00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2005 Kasper Skaarhoj (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 ***************************************************************/
00174 require_once(PATH_t3lib.'class.t3lib_tcemain.php');
00175 require_once (PATH_t3lib.'class.t3lib_diff.php');
00176 require_once (PATH_t3lib.'class.t3lib_parsehtml.php');
00177 
00178 require_once (PATH_t3lib.'class.t3lib_basicfilefunc.php');
00179 require_once (PATH_t3lib.'class.t3lib_extfilefunc.php');
00180 require_once (PATH_t3lib.'class.t3lib_refindex.php');
00181 
00182 @ini_set('max_execution_time',600);
00183 @ini_set('memory_limit','256m');
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00198 class tx_impexp {
00199 
00200                 // Configuration, general
00201         var $showStaticRelations = FALSE;               // If set, static relations (not exported) will be shown in overview as well
00202         var $fileadminFolderName = 'fileadmin'; // Name of the "fileadmin" folder where files for export/import should be located
00203 
00204         var $mode = '';                                                 // Whether "import" or "export" mode of object. Set through init() function
00205         var $update = FALSE;                                    // Updates all records that has same UID instead of creating new!
00206         var $doesImport = FALSE;                                // Is set by importData() when an import has been done.
00207 
00208                 // Configuration, import
00209         var $display_import_pid_record = '';            // If set to a page-record, then the preview display of the content will expect this page-record to be the target for the import and accordingly display validation information. This triggers the visual view of the import/export memory to validate if import is possible
00210         var $suggestedInsertUids = array();             // Used to register the forged UID values for imported records that we want to create with the same UIDs as in the import file. Admin-only feature.
00211         var $import_mode = array();                             // Setting import modes during update state: as_new, exclude, force_uid
00212         var $global_ignore_pid = FALSE;                 // If set, PID correct is ignored globally
00213         var $force_all_UIDS = FALSE;                    // If set, all UID values are forced! (update or import)
00214         var $showDiff = FALSE;                                  // If set, a diff-view column is added to the overview.
00215         var $allowPHPScripts = FALSE;                   // If set, and if the user is admin, allow the writing of PHP scripts to fileadmin/ area.
00216         var $enableLogging = FALSE;                             // Disable logging when importing
00217         var $softrefInputValues = array();              // Array of values to substitute in editable softreferences.
00218         var $fileIDMap = array();                               // Mapping between the fileID from import memory and the final filenames they are written to.
00219 
00220                 // Configuration, export
00221         var $maxFileSize = 1000000;             // 1MB max file size
00222         var $maxRecordSize = 1000000;   // 1MB max record size
00223         var $maxExportSize = 10000000;  // 10MB max export size
00224         var $relOnlyTables = array();   // add table names here which are THE ONLY ones which will be included into export if found as relations. '_ALL' will allow all tables.
00225         var $relStaticTables = array(); // add tables names here which should not be exported with the file. (Where relations should be mapped to same UIDs in target system).
00226         var $excludeMap = array();              // Exclude map. Keys are table:uid  pairs and if set, records are not added to the export.
00227         var $softrefCfg = array();              // Soft Reference Token ID modes.
00228         var $extensionDependencies = array();           // Listing extension dependencies.
00229         var $dontCompress = 0;                  // Set  by user: If set, compression in t3d files is disabled
00230         var $includeExtFileResources = 0;       // Boolean, if set, HTML file resources are included.
00231         var $extFileResourceExtensions = 'html,htm,css';        // Files with external media (HTML/css style references inside)
00232 
00233                 // Internal, dynamic:
00234         var $import_mapId = array();            // After records are written this array is filled with [table][original_uid] = [new_uid]
00235         var $import_newId = array();            // Keys are [tablename]:[new NEWxxx ids (or when updating it is uids)] while values are arrays with table/uid of the original record it is based on. By the array keys the new ids can be looked up inside tcemain
00236         var $import_newId_pids = array();       // Page id map for page tree (import)
00237         var $import_data = array();                     // Internal data accumulation for writing records during import
00238         var $errorLog = array();                        // Error log.
00239         var $cache_getRecordPath = array();     // Cache for record paths
00240         var $checkPID_cache = array();          // Cache of checkPID values.
00241 
00242         var $compress = 0;                                      // Set internally if the gzcompress function exists
00243         var $dat = array();                                     // Internal import/export memory
00244         var $fileProcObj = '';                          // File processing object
00245 
00246 
00247 
00248         /**************************
00249          *
00250          * Initialize
00251          *
00252          *************************/
00253 
00261         function init($dontCompress=0,$mode='') {
00262                 $this->compress = function_exists('gzcompress');
00263                 $this->dontCompress = $dontCompress;
00264 
00265                 $this->mode = $mode;
00266         }
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281         /**************************
00282          *
00283          * Export / Init + Meta Data
00284          *
00285          *************************/
00286 
00292         function setHeaderBasics()      {
00293 
00294                         // Initializing:
00295                 if (is_array($this->softrefCfg))        {
00296                         foreach($this->softrefCfg as $key => $value)    {
00297                                 if (!strlen($value['mode']))    unset($this->softrefCfg[$key]);
00298                         }
00299                 }
00300 
00301                         // Setting in header memory:
00302                 $this->dat['header']['XMLversion'] = '1.0';             // Version of file format
00303                 $this->dat['header']['meta'] = array();                 // Initialize meta data array (to put it in top of file)
00304                 $this->dat['header']['relStaticTables'] = $this->relStaticTables;       // Add list of tables to consider static
00305                 $this->dat['header']['excludeMap'] = $this->excludeMap;                         // The list of excluded records
00306                 $this->dat['header']['softrefCfg'] = $this->softrefCfg;                 // Soft Reference mode for elements
00307                 $this->dat['header']['extensionDependencies'] = $this->extensionDependencies;           // List of extensions the import depends on.
00308         }
00309 
00316         function setCharset($charset)   {
00317                 $this->dat['header']['charset'] = $charset;
00318         }
00319 
00331         function setMetaData($title,$description,$notes,$packager_username,$packager_name,$packager_email)      {
00332                 $this->dat['header']['meta'] = array(
00333                         'title' => $title,
00334                         'description' => $description,
00335                         'notes' => $notes,
00336                         'packager_username' => $packager_username,
00337                         'packager_name' => $packager_name,
00338                         'packager_email' => $packager_email,
00339                         'TYPO3_version' => TYPO3_version,
00340 #                       'loaded_extensions' => $GLOBALS['TYPO3_CONF_VARS']['EXT']['extList'],
00341                         'created' => strftime('%A %e. %B %Y', time())
00342                 );
00343         }
00344 
00351         function addThumbnail($imgFilepath)     {
00352                 if (@is_file($imgFilepath))     {
00353                         $imgInfo = @getimagesize($imgFilepath);
00354                         if (is_array($imgInfo)) {
00355                                 $fileContent = t3lib_div::getUrl($imgFilepath);
00356                                 $this->dat['header']['thumbnail'] = array(
00357                                         'imgInfo' => $imgInfo,
00358                                         'content' => $fileContent,
00359                                         'filesize' => strlen($fileContent),
00360                                         'filemtime' => filemtime($imgFilepath),
00361                                         'filename' => basename($imgFilepath)
00362                                 );
00363                         }
00364                 }
00365         }
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377         /**************************
00378          *
00379          * Export / Init Page tree
00380          *
00381          *************************/
00382 
00389         function setPageTree($idH)      {
00390                 $this->dat['header']['pagetree'] = $this->unsetExcludedSections($idH);
00391                 return $this->flatInversePageTree($this->dat['header']['pagetree']);
00392         }
00393 
00402         function unsetExcludedSections($idH)    {
00403                 if (is_array($idH))     {
00404                         reset($idH);
00405                         while(list($k,$v) = each($idH)) {
00406                                 if ($this->excludeMap['pages:'.$idH[$k]['uid']])        {
00407                                         unset($idH[$k]);
00408                                 } elseif (is_array($idH[$k]['subrow'])) {
00409                                         $idH[$k]['subrow'] = $this->unsetExcludedSections($idH[$k]['subrow']);
00410                                 }
00411                         }
00412                 }
00413                 return $idH;
00414         }
00415 
00424         function flatInversePageTree($idH,$a=array())   {
00425                 if (is_array($idH))     {
00426                         $idH = array_reverse($idH);
00427                         reset($idH);
00428                         while(list($k,$v) = each($idH)) {
00429                                 $a[$v['uid']] = $v['uid'];
00430                                 if (is_array($v['subrow']))     {
00431                                         $a = $this->flatInversePageTree($v['subrow'],$a);
00432                                 }
00433                         }
00434                 }
00435                 return $a;
00436         }
00437 
00447         function flatInversePageTree_pid($idH,$a=array(),$pid=-1)       {
00448                 if (is_array($idH))     {
00449                         $idH = array_reverse($idH);
00450                         reset($idH);
00451                         while(list($k,$v) = each($idH)) {
00452                                 $a[$v['uid']] = $pid;
00453                                 if (is_array($v['subrow']))     {
00454                                         $a = $this->flatInversePageTree_pid($v['subrow'],$a,$v['uid']);
00455                                 }
00456                         }
00457                 }
00458                 return $a;
00459         }
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471         /**************************
00472          *
00473          * Export
00474          *
00475          *************************/
00476 
00486         function export_addRecord($table,$row,$relationLevel=0) {
00487 
00488                 t3lib_BEfunc::workspaceOL($table,$row);
00489 
00490                 if (strcmp($table,'') && is_array($row) && $row['uid']>0 && !$this->excludeMap[$table.':'.$row['uid']]) {
00491                         if ($this->checkPID($table==='pages' ? $row['uid'] : $row['pid']))      {
00492                                 if (!isset($this->dat['records'][$table.':'.$row['uid']]))      {
00493 
00494                                                 // Prepare header info:
00495                                         $headerInfo = array();
00496                                         $headerInfo['uid'] = $row['uid'];
00497                                         $headerInfo['pid'] = $row['pid'];
00498                                         $headerInfo['title'] = t3lib_div::fixed_lgd_cs(t3lib_BEfunc::getRecordTitle($table,$row),40);
00499                                         $headerInfo['size'] = strlen(serialize($row));
00500                                         if ($relationLevel)     {
00501                                                 $headerInfo['relationLevel'] = $relationLevel;
00502                                         }
00503 
00504                                                 // If record content is not too large in size, set the header content and add the rest:
00505                                         if ($headerInfo['size']<$this->maxRecordSize)   {
00506 
00507                                                         // Set the header summary:
00508                                                 $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
00509 
00510                                                         // Create entry in the PID lookup:
00511                                                 $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']]=1;
00512 
00513                                                         // Initialize reference index object:
00514                                                 $refIndexObj = t3lib_div::makeInstance('t3lib_refindex');
00515                                                 $refIndexObj->WSOL = TRUE;      // Yes to workspace overlays for exporting....
00516 
00517                                                         // Data:
00518                                                 $this->dat['records'][$table.':'.$row['uid']] = array();
00519                                                 $this->dat['records'][$table.':'.$row['uid']]['data'] = $row;
00520                                                 $this->dat['records'][$table.':'.$row['uid']]['rels'] = $refIndexObj->getRelations($table,$row);
00521                                                 $this->errorLog = array_merge($this->errorLog,$refIndexObj->errorLog);  // Merge error logs.
00522 
00523                                                         // Add information about the relations in the record in the header:
00524                                                 $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->flatDBrels($this->dat['records'][$table.':'.$row['uid']]['rels']);
00525 
00526                                                         // Add information about the softrefs to header:
00527                                                 $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->flatSoftRefs($this->dat['records'][$table.':'.$row['uid']]['rels']);
00528 
00529                                         } else $this->error('Record '.$table.':'.$row['uid'].' was larger than maxRecordSize ('.t3lib_div::formatSize($this->maxRecordSize).')');
00530                                 } else $this->error('Record '.$table.':'.$row['uid'].' already added.');
00531                         } else $this->error('Record '.$table.':'.$row['uid'].' was outside your DB mounts!');
00532                 }
00533         }
00534 
00544         function export_addDBRelations($relationLevel=0)        {
00545                 global $TCA;
00546 
00547                         // Initialize:
00548                 $addR = array();
00549 
00550                         // Traverse all "rels" registered for "records"
00551                 if (is_array($this->dat['records']))    {
00552                         reset($this->dat['records']);
00553                         while(list($k) = each($this->dat['records']))   {
00554                                 if (is_array($this->dat['records'][$k]))        {
00555                                         reset($this->dat['records'][$k]['rels']);
00556                                         while(list($fieldname,$vR) = each($this->dat['records'][$k]['rels']))   {
00557 #debug($vR);
00558                                                         // For all DB types of relations:
00559                                                 if ($vR['type']=='db')  {
00560                                                         foreach($vR['itemArray'] as $fI)        {
00561                                                                 $this->export_addDBRelations_registerRelation($fI, $addR);
00562                                                         }
00563                                                 }
00564 
00565                                                         // For all flex/db types of relations:
00566                                                 if ($vR['type']=='flex')        {
00567                                                                 // DB relations in flex form fields:
00568                                                         if (is_array($vR['flexFormRels']['db']))        {
00569                                                                 foreach($vR['flexFormRels']['db'] as $subList)  {
00570                                                                         foreach($subList as $fI)        {
00571                                                                                 $this->export_addDBRelations_registerRelation($fI, $addR);
00572                                                                         }
00573                                                                 }
00574                                                         }
00575                                                                 // DB oriented soft references in flex form fields:
00576                                                         if (is_array($vR['flexFormRels']['softrefs']))  {
00577                                                                 foreach($vR['flexFormRels']['softrefs'] as $subList)    {
00578                                                                         foreach($subList['keys'] as $spKey => $elements)        {
00579                                                                                 foreach($elements as $el)       {
00580                                                                                         if ($el['subst']['type'] === 'db' && $this->includeSoftref($el['subst']['tokenID']))    {
00581                                                                                                 list($tempTable, $tempUid) = explode(':', $el['subst']['recordRef']);
00582                                                                                                 $fI = array(
00583                                                                                                         'table' => $tempTable,
00584                                                                                                         'id' => $tempUid
00585                                                                                                 );
00586                                                                                                 $this->export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
00587                                                                                         }
00588                                                                                 }
00589                                                                         }
00590                                                                 }
00591                                                         }
00592                                                 }
00593 
00594                                                         // In any case, if there are soft refs:
00595                                                 if (is_array($vR['softrefs']['keys']))  {
00596                                                         foreach($vR['softrefs']['keys'] as $spKey => $elements) {
00597                                                                 foreach($elements as $el)       {
00598                                                                         if ($el['subst']['type'] === 'db' && $this->includeSoftref($el['subst']['tokenID']))    {
00599                                                                                 list($tempTable, $tempUid) = explode(':', $el['subst']['recordRef']);
00600                                                                                 $fI = array(
00601                                                                                         'table' => $tempTable,
00602                                                                                         'id' => $tempUid
00603                                                                                 );
00604                                                                                 $this->export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
00605                                                                         }
00606                                                                 }
00607                                                         }
00608                                                 }
00609                                         }
00610                                 }
00611                         }
00612                 } else $this->error('There were no records available.');
00613 
00614                         // Now, if there were new records to add, do so:
00615                 if (count($addR))       {
00616                         foreach($addR as $fI)   {
00617 
00618                                         // Get and set record:
00619                                 $row = t3lib_BEfunc::getRecord($fI['table'],$fI['id']);
00620                                 if (is_array($row))     {
00621                                         $this->export_addRecord($fI['table'],$row,$relationLevel+1);
00622                                 }
00623 
00624                                         // Set status message
00625                                 if ($fI['id']>0)        {       // Relation pointers always larger than zero except certain "select" types with negative values pointing to uids - but that is not supported here.
00626                                         $rId = $fI['table'].':'.$fI['id'];
00627                                         if (!isset($this->dat['records'][$rId]))        {
00628                                                 $this->dat['records'][$rId] = 'NOT_FOUND';
00629                                                 $this->error('Relation record '.$rId.' was not found!');
00630                                         }
00631                                 }
00632                         }
00633                 }
00634 
00635                         // Return overview of relations found and added
00636                 return $addR;
00637         }
00638 
00648         function export_addDBRelations_registerRelation($fI, &$addR, $tokenID='')       {
00649                 global $TCA;
00650 
00651                 $rId = $fI['table'].':'.$fI['id'];
00652                 if (isset($TCA[$fI['table']])
00653                                 && !$this->isTableStatic($fI['table'])
00654                                 && !$this->isExcluded($fI['table'],$fI['id'])
00655                                 && (!$tokenID || $this->includeSoftref($tokenID))
00656                                 && $this->inclRelation($fI['table'])
00657                                 )       {
00658                         if (!isset($this->dat['records'][$rId]))        {
00659                                         // Set this record to be included since it is not already.
00660                                 $addR[$rId] = $fI;
00661                         }
00662                 }
00663         }
00664 
00672         function export_addFilesFromRelations() {
00673 
00674                         // Traverse all "rels" registered for "records"
00675                 if (is_array($this->dat['records']))    {
00676                         reset($this->dat['records']);
00677                         while(list($k)=each($this->dat['records']))     {
00678                                 if (is_array($this->dat['records'][$k]['rels']))        {
00679                                         reset($this->dat['records'][$k]['rels']);
00680                                         while(list($fieldname,$vR)=each($this->dat['records'][$k]['rels']))     {
00681 
00682                                                         // For all file type relations:
00683                                                 if ($vR['type']=='file')        {
00684                                                         foreach($vR['newValueFiles'] as $key => $fI)    {
00685                                                                 $this->export_addFile($fI, $k, $fieldname);
00686                                                                         // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
00687                                                                 unset($this->dat['records'][$k]['rels'][$fieldname]['newValueFiles'][$key]['ID_absFile']);
00688                                                         }
00689                                                 }
00690 
00691                                                         // For all flex type relations:
00692                                                 if ($vR['type']=='flex')        {
00693                                                         if (is_array($vR['flexFormRels']['file']))      {
00694                                                                 foreach($vR['flexFormRels']['file'] as $key => $subList)        {
00695                                                                         foreach($subList as $subKey => $fI)     {
00696                                                                                 $this->export_addFile($fI, $k, $fieldname);
00697                                                                                         // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
00698                                                                                 unset($this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['file'][$key][$subKey]['ID_absFile']);
00699                                                                         }
00700                                                                 }
00701                                                         }
00702 
00703                                                                 // DB oriented soft references in flex form fields:
00704                                                         if (is_array($vR['flexFormRels']['softrefs']))  {
00705                                                                 foreach($vR['flexFormRels']['softrefs'] as $key => $subList)    {
00706                                                                         foreach($subList['keys'] as $spKey => $elements)        {
00707                                                                                 foreach($elements as $subKey => $el)    {
00708                                                                                         if ($el['subst']['type'] === 'file' && $this->includeSoftref($el['subst']['tokenID']))  {
00709 
00710                                                                                                         // Create abs path and ID for file:
00711                                                                                                 $ID_absFile = t3lib_div::getFileAbsFileName(PATH_site.$el['subst']['relFileName']);
00712                                                                                                 $ID = md5($ID_absFile);
00713 
00714                                                                                                 if ($ID_absFile)        {
00715                                                                                                         if (!$this->dat['files'][$ID])  {
00716                                                                                                                 $fI = array(
00717                                                                                                                         'filename' => basename($ID_absFile),
00718                                                                                                                         'ID_absFile' => $ID_absFile,
00719                                                                                                                         'ID' => $ID,
00720                                                                                                                         'relFileName' => $el['subst']['relFileName']
00721                                                                                                                 );
00722                                                                                                                 $this->export_addFile($fI, '_SOFTREF_');
00723                                                                                                         }
00724                                                                                                         $this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['softrefs'][$key]['keys'][$spKey][$subKey]['file_ID'] = $ID;
00725                                                                                                 }
00726                                                                                         }
00727                                                                                 }
00728                                                                         }
00729                                                                 }
00730                                                         }
00731                                                 }
00732 
00733                                                         // In any case, if there are soft refs:
00734                                                 if (is_array($vR['softrefs']['keys']))  {
00735                                                         foreach($vR['softrefs']['keys'] as $spKey => $elements) {
00736                                                                 foreach($elements as $subKey => $el)    {
00737                                                                         if ($el['subst']['type'] === 'file' && $this->includeSoftref($el['subst']['tokenID']))  {
00738 
00739                                                                                         // Create abs path and ID for file:
00740                                                                                 $ID_absFile = t3lib_div::getFileAbsFileName(PATH_site.$el['subst']['relFileName']);
00741                                                                                 $ID = md5($ID_absFile);
00742 
00743                                                                                 if ($ID_absFile)        {
00744                                                                                         if (!$this->dat['files'][$ID])  {
00745                                                                                                 $fI = array(
00746                                                                                                         'filename' => basename($ID_absFile),
00747                                                                                                         'ID_absFile' => $ID_absFile,
00748                                                                                                         'ID' => $ID,
00749                                                                                                         'relFileName' => $el['subst']['relFileName']
00750                                                                                                 );
00751                                                                                                 $this->export_addFile($fI, '_SOFTREF_');
00752                                                                                         }
00753                                                                                         $this->dat['records'][$k]['rels'][$fieldname]['softrefs']['keys'][$spKey][$subKey]['file_ID'] = $ID;
00754                                                                                 }
00755                                                                         }
00756                                                                 }
00757                                                         }
00758                                                 }
00759                                         }
00760                                 }
00761                         }
00762                 } else $this->error('There were no records available.');
00763         }
00764 
00773         function export_addFile($fI, $recordRef='', $fieldname='')      {
00774                 if (@is_file($fI['ID_absFile']))        {
00775                         if (filesize($fI['ID_absFile']) < $this->maxFileSize)   {
00776                                 $fileRec = array();
00777                                 $fileRec['filesize'] = filesize($fI['ID_absFile']);
00778                                 $fileRec['filename'] = basename($fI['ID_absFile']);
00779                                 $fileRec['filemtime'] = filemtime($fI['ID_absFile']);
00780                                 if ($recordRef) {
00781                                         $fileRec['record_ref'] = $recordRef.'/'.$fieldname;
00782                                 }
00783                                 if ($fI['relFileName']) {
00784                                         $fileRec['relFileName'] = $fI['relFileName'];
00785                                 }
00786 
00787                                         // Setting this data in the header
00788                                 $this->dat['header']['files'][$fI['ID']] = $fileRec;
00789 
00790                                         // ... and for the recordlisting, why not let us know WHICH relations there was...
00791                                 if ($recordRef && $recordRef!=='_SOFTREF_')     {
00792                                         $refParts = explode(':',$recordRef,2);
00793                                         if (!is_array($this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'])) {
00794                                                 $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'] = array();
00795                                         }
00796                                         $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'][] = $fI['ID'];
00797                                 }
00798 
00799                                         // ... and finally add the heavy stuff:
00800                                 $fileRec['content'] = t3lib_div::getUrl($fI['ID_absFile']);
00801                                 $fileRec['content_md5'] = md5($fileRec['content']);
00802                                 $this->dat['files'][$fI['ID']] = $fileRec;
00803 
00804 
00805                                         // For soft references, do further processing:
00806                                 if ($recordRef === '_SOFTREF_') {
00807 
00808                                                 // RTE files?
00809                                         if ($RTEoriginal = $this->getRTEoriginalFilename(basename($fI['ID_absFile'])))  {
00810                                                 $RTEoriginal_absPath = dirname($fI['ID_absFile']).'/'.$RTEoriginal;
00811                                                 if (@is_file($RTEoriginal_absPath))     {
00812 
00813                                                         $RTEoriginal_ID = md5($RTEoriginal_absPath);
00814 
00815                                                         $fileRec = array();
00816                                                         $fileRec['filesize'] = filesize($RTEoriginal_absPath);
00817                                                         $fileRec['filename'] = basename($RTEoriginal_absPath);
00818                                                         $fileRec['filemtime'] = filemtime($RTEoriginal_absPath);
00819                                                         $fileRec['record_ref'] = '_RTE_COPY_ID:'.$fI['ID'];
00820                                                         $this->dat['header']['files'][$fI['ID']]['RTE_ORIG_ID'] = $RTEoriginal_ID;
00821 
00822                                                                 // Setting this data in the header
00823                                                         $this->dat['header']['files'][$RTEoriginal_ID] = $fileRec;
00824 
00825                                                                 // ... and finally add the heavy stuff:
00826                                                         $fileRec['content'] = t3lib_div::getUrl($RTEoriginal_absPath);
00827                                                         $fileRec['content_md5'] = md5($fileRec['content']);
00828                                                         $this->dat['files'][$RTEoriginal_ID] = $fileRec;
00829                                                 } else {
00830                                                         $this->error('RTE original file "'.substr($RTEoriginal_absPath,strlen(PATH_site)).'" was not found!');
00831                                                 }
00832                                         }
00833 
00834                                                 // Files with external media?
00835                                                 // This is only done with files grabbed by a softreference parser since it is deemed improbable that hard-referenced files should undergo this treatment.
00836                                         $html_fI = pathinfo(basename($fI['ID_absFile']));
00837                                         if ($this->includeExtFileResources && t3lib_div::inList($this->extFileResourceExtensions,strtolower($html_fI['extension'])))    {
00838                                                 $uniquePrefix = '###'.md5(time()).'###';
00839 
00840                                                 if (strtolower($html_fI['extension'])==='css')  {
00841                                                         $prefixedMedias = explode($uniquePrefix, eregi_replace('(url[[:space:]]*\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\))', '\1'.$uniquePrefix.'\2'.$uniquePrefix.'\3', $fileRec['content']));
00842                                                 } else {        // html, htm:
00843                                                         $htmlParser = t3lib_div::makeInstance('t3lib_parsehtml');
00844                                                         $prefixedMedias = explode($uniquePrefix, $htmlParser->prefixResourcePath($uniquePrefix,$fileRec['content'],array(),$uniquePrefix));
00845                                                 }
00846 
00847                                                 $htmlResourceCaptured = FALSE;
00848                                                 foreach($prefixedMedias as $k => $v)    {
00849                                                         if ($k%2)       {
00850                                                                 $EXTres_absPath = t3lib_div::resolveBackPath(dirname($fI['ID_absFile']).'/'.$v);
00851                                                                 $EXTres_absPath = t3lib_div::getFileAbsFileName($EXTres_absPath);
00852                                                                 if ($EXTres_absPath && t3lib_div::isFirstPartOfStr($EXTres_absPath,PATH_site.$this->fileadminFolderName.'/') && @is_file($EXTres_absPath))      {
00853 
00854                                                                         $htmlResourceCaptured = TRUE;
00855                                                                         $EXTres_ID = md5($EXTres_absPath);
00856                                                                         $this->dat['header']['files'][$fI['ID']]['EXT_RES_ID'][] = $EXTres_ID;
00857                                                                         $prefixedMedias[$k] = '{EXT_RES_ID:'.$EXTres_ID.'}';
00858 
00859                                                                                 // Add file to memory if it is not set already:
00860                                                                         if (!isset($this->dat['header']['files'][$EXTres_ID]))          {
00861                                                                                 $fileRec = array();
00862                                                                                 $fileRec['filesize'] = filesize($EXTres_absPath);
00863                                                                                 $fileRec['filename'] = basename($EXTres_absPath);
00864                                                                                 $fileRec['filemtime'] = filemtime($EXTres_absPath);
00865                                                                                 $fileRec['record_ref'] = '_EXT_PARENT_:'.$fI['ID'];
00866 
00867                                                                                 $fileRec['parentRelFileName'] = $v;             // Media relative to the HTML file.
00868 
00869                                                                                         // Setting this data in the header
00870                                                                                 $this->dat['header']['files'][$EXTres_ID] = $fileRec;
00871 
00872                                                                                         // ... and finally add the heavy stuff:
00873                                                                                 $fileRec['content'] = t3lib_div::getUrl($EXTres_absPath);
00874                                                                                 $fileRec['content_md5'] = md5($fileRec['content']);
00875                                                                                 $this->dat['files'][$EXTres_ID] = $fileRec;
00876                                                                         }
00877                                                                 }
00878                                                         }
00879                                                 }
00880 
00881                                                 if ($htmlResourceCaptured)      {
00882                                                         $this->dat['files'][$fI['ID']]['tokenizedContent'] = implode('', $prefixedMedias);
00883                                                 }
00884                                         }
00885                                 }
00886 
00887                         } else  $this->error($fI['ID_absFile'].' was larger ('.t3lib_div::formatSize(filesize($fI['ID_absFile'])).') than the maxFileSize ('.t3lib_div::formatSize($this->maxFileSize).')! Skipping.');
00888                 } else $this->error($fI['ID_absFile'].' was not a file! Skipping.');
00889         }
00890 
00898         function flatDBrels($dbrels)    {
00899                 $list = array();
00900 
00901                 foreach($dbrels as $dat)        {
00902                         if ($dat['type']=='db') {
00903                                 foreach($dat['itemArray'] as $i)        {
00904                                         $list[$i['table'].':'.$i['id']] = $i;
00905                                 }
00906                         }
00907                         if ($dat['type']=='flex' && is_array($dat['flexFormRels']['db']))       {
00908                                 foreach($dat['flexFormRels']['db'] as $subList) {
00909                                         foreach($subList as $i) {
00910                                                 $list[$i['table'].':'.$i['id']] = $i;
00911                                         }
00912                                 }
00913                         }
00914                 }
00915                 return $list;
00916         }
00917 
00924         function flatSoftRefs($dbrels)  {
00925                 $list = array();
00926 #debug($dbrels);
00927                 foreach($dbrels as $field => $dat)      {
00928                         if (is_array($dat['softrefs']['keys'])) {
00929                                 foreach($dat['softrefs']['keys'] as $spKey => $elements)        {
00930                                         if (is_array($elements))        {
00931                                                 foreach($elements as $subKey => $el)    {
00932                                                         $lKey = $field.':'.$spKey.':'.$subKey;
00933                                                         $list[$lKey] = array_merge(array('field' => $field, 'spKey' => $spKey),$el);
00934 
00935                                                                 // Add file_ID key to header - slightly "risky" way of doing this because if the calculation changes for the same value in $this->records[...] this will not work anymore!
00936                                                         if ($el['subst'] && $el['subst']['relFileName'])        {
00937                                                                 $list[$lKey]['file_ID'] = md5(PATH_site.$el['subst']['relFileName']);
00938                                                         }
00939                                                 }
00940                                         }
00941                                 }
00942                         }
00943                         if ($dat['type']=='flex' && is_array($dat['flexFormRels']['softrefs'])) {
00944                                 foreach($dat['flexFormRels']['softrefs'] as $structurePath => $subSoftrefs)     {
00945                                         if (is_array($subSoftrefs['keys']))     {
00946                                                 foreach($subSoftrefs['keys'] as $spKey => $elements)    {
00947                                                         foreach($elements as $subKey => $el)    {
00948                                                                 $lKey = $field.':'.$structurePath.':'.$spKey.':'.$subKey;
00949                                                                 $list[$lKey] = array_merge(array('field' => $field, 'spKey' => $spKey, 'structurePath' => $structurePath),$el);
00950 
00951                                                                         // Add file_ID key to header - slightly "risky" way of doing this because if the calculation changes for the same value in $this->records[...] this will not work anymore!
00952                                                                 if ($el['subst'] && $el['subst']['relFileName'])        {
00953                                                                         $list[$lKey]['file_ID'] = md5(PATH_site.$el['subst']['relFileName']);
00954                                                                 }
00955                                                         }
00956                                                 }
00957                                         }
00958                                 }
00959                         }
00960                 }
00961 
00962 #debug($list);
00963                 return $list;
00964         }
00965 
00966 
00967 
00968 
00969 
00970 
00971 
00972 
00973 
00974 
00975 
00976         /**************************
00977          *
00978          * File Output
00979          *
00980          *************************/
00981 
00988         function compileMemoryToFileContent($type='')   {
00989 
00990                 if ($type=='xml')       {
00991                         $out = $this->createXML();
00992                 } else {
00993                         $compress = $this->doOutputCompress();
00994                         $out = '';
00995 
00996                         // adding header:
00997                         $out.= $this->addFilePart(serialize($this->dat['header']),$compress);
00998 
00999                         // adding records:
01000                         $out.= $this->addFilePart(serialize($this->dat['records']),$compress);
01001 
01002                         // adding files:
01003                         $out.= $this->addFilePart(serialize($this->dat['files']),$compress);
01004                 }
01005 
01006                 return $out;
01007         }
01008 
01014         function createXML()    {
01015 
01016                         // Options:
01017                 $options = array(
01018                         'alt_options' => array(
01019                                 '/header' => array(
01020                                         'disableTypeAttrib' => TRUE,
01021                                         'clearStackPath' => TRUE,
01022                                         'parentTagMap' => array(
01023                                                 'files' => 'file',
01024                                                 'records' => 'table',
01025                                                 'table' => 'rec',
01026                                                 'rec:rels' => 'relations',
01027                                                 'relations' => 'element',
01028                                                 'filerefs' => 'file',
01029                                                 'pid_lookup' => 'page_contents',
01030                                                 'header:relStaticTables' => 'static_tables',
01031                                                 'static_tables' => 'tablename',
01032                                                 'excludeMap' => 'item',
01033                                                 'softrefCfg' => 'softrefExportMode',
01034                                                 'extensionDependencies' => 'extkey',
01035                                                 'softrefs' => 'softref_element',
01036                                         ),
01037                                         'alt_options' => array(
01038                                                 '/pagetree' => array(
01039                                                         'disableTypeAttrib' => TRUE,
01040                                                         'useIndexTagForNum' => 'node',
01041                                                         'parentTagMap' => array(
01042                                                                 'node:subrow' => 'node'
01043                                                         )
01044                                                 ),
01045                                                 '/pid_lookup/page_contents' => array(
01046                                                         'disableTypeAttrib' => TRUE,
01047                                                         'parentTagMap' => array(
01048                                                                 'page_contents' => 'table'
01049                                                         ),
01050                                                         'grandParentTagMap' => array(
01051                                                                 'page_contents/table' => 'item'
01052                                                         )
01053                                                 )
01054                                         )
01055                                 ),
01056                                 '/records' => array(
01057                                         'disableTypeAttrib' => TRUE,
01058                                         'parentTagMap' => array(
01059                                                 'records' => 'tablerow',
01060                                                 'tablerow:data' => 'fieldlist',
01061                                                 'tablerow:rels' => 'related',
01062                                                 'related' => 'field',
01063                                                 'field:itemArray' => 'relations',
01064                                                 'field:newValueFiles' => 'filerefs',
01065                                                 'field:flexFormRels' => 'flexform',
01066                                                 'relations' => 'element',
01067                                                 'filerefs' => 'file',
01068                                                 'flexform:db' => 'db_relations',
01069                                                 'flexform:file' => 'file_relations',
01070                                                 'flexform:softrefs' => 'softref_relations',
01071                                                 'softref_relations' => 'structurePath',
01072                                                 'db_relations' => 'path',
01073                                                 'file_relations' => 'path',
01074                                                 'path' => 'element',
01075                                                 'keys' => 'softref_key',
01076                                                 'softref_key' => 'softref_element',
01077                                         ),
01078                                         'alt_options' => array(
01079                                                 '/records/tablerow/fieldlist' => array(
01080                                                         'useIndexTagForAssoc' => 'field',
01081                                                 )
01082                                         )
01083                                 ),
01084                                 '/files' => array(
01085                                         'disableTypeAttrib' => TRUE,
01086                                         'parentTagMap' => array(
01087                                                 'files' => 'file',
01088                                         ),
01089                                 ),
01090                         )
01091                 );
01092 
01093                         // Creating XML file from $outputArray:
01094                 $charset = $this->dat['header']['charset'] ? $this->dat['header']['charset'] : 'iso-8859-1';
01095                 $XML = '<?xml version="1.0" encoding="'.$charset.'" standalone="yes" ?>'.chr(10);
01096                 $XML.= t3lib_div::array2xml($this->dat,'',0,'T3RecordDocument',0,$options);
01097 
01098                 return $XML;
01099         }
01100 
01106         function doOutputCompress()     {
01107                 return $this->compress && !$this->dontCompress;
01108         }
01109 
01117         function addFilePart($data, $compress=FALSE)    {
01118                 if ($compress)  $data = gzcompress($data);
01119                 return md5($data).':'.
01120                                 ($compress?'1':'0').':'.
01121                                 str_pad(strlen($data),10,'0',STR_PAD_LEFT).':'.
01122                                 $data.':';
01123         }
01124 
01125 
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138         /***********************
01139          *
01140          * Import
01141          *
01142          ***********************/
01143 
01150         function importData($pid)       {
01151 
01152                         // Set this flag to indicate that an import is being/has been done.
01153                 $this->doesImport = 1;
01154 
01155                         // Initialize:
01156                         // These vars MUST last for the whole section not being cleared. They are used by the method setRelations() which are called at the end of the import session.
01157                 $this->import_mapId = array();
01158                 $this->import_newId = array();
01159                 $this->import_newId_pids = array();
01160 
01161                         // Temporary files stack initialized:
01162                 $this->unlinkFiles = array();
01163                 $this->alternativeFileName = array();
01164 
01165                         // Write records, first pages, then the rest
01166                         // Fields with "hard" relations to database, files and flexform fields are kept empty during this run
01167                 $this->writeRecords_pages($pid);
01168                 $this->writeRecords_records($pid);
01169 
01170                         // Finally all the file and DB record references must be fixed. This is done after all records have supposedly been written to database:
01171                         // $this->import_mapId will indicate two things: 1) that a record WAS written to db and 2) that it has got a new id-number.
01172                 $this->setRelations();
01173 
01174                         // And when all DB relations are in place, we can fix file and DB relations in flexform fields (since data structures often depends on relations to a DS record):
01175                 $this->setFlexFormRelations();
01176 
01177                         // Unlink temporary files:
01178                 $this->unlinkTempFiles();
01179 
01180                         // Finally, traverse all records and process softreferences with substitution attributes.
01181                 $this->processSoftReferences();
01182         }
01183 
01191         function writeRecords_pages($pid)       {
01192 
01193                         // First, write page structure if any:
01194                 if (is_array($this->dat['header']['records']['pages'])) {
01195 
01196                                 // $pageRecords is a copy of the pages array in the imported file. Records here are unset one by one when the addSingle function is called.
01197                         $pageRecords = $this->dat['header']['records']['pages'];
01198                         $this->import_data = array();
01199 #debug($pageRecords);
01200                                 // First add page tree if any
01201                         if (is_array($this->dat['header']['pagetree'])) {
01202                                 $pagesFromTree = $this->flatInversePageTree($this->dat['header']['pagetree']);
01203                                 foreach($pagesFromTree as $uid) {
01204                                         $thisRec = $this->dat['header']['records']['pages'][$uid];
01205                                                 // PID: Set the main $pid, unless a NEW-id is found
01206                                         $setPid = isset($this->import_newId_pids[$thisRec['pid']])      ? $this->import_newId_pids[$thisRec['pid']] : $pid;
01207                                         $this->addSingle('pages',$uid,$setPid);
01208                                         unset($pageRecords[$uid]);
01209                                 }
01210                         }
01211 #debug($pageRecords);
01212                                 // Then add all remaining pages not in tree on root level:
01213                         if (count($pageRecords))        {
01214                                 $remainingPageUids = array_keys($pageRecords);
01215                                 foreach($remainingPageUids as $pUid)    {
01216                                         $this->addSingle('pages',$pUid,$pid);
01217                                 }
01218                         }
01219 
01220                                 // Now write to database:
01221                         $tce = $this->getNewTCE();
01222                         $tce->suggestedInsertUids = $this->suggestedInsertUids;
01223                         $tce->start($this->import_data,Array());
01224                         $tce->process_datamap();
01225 #debug($this->import_data,'PAGES');
01226 
01227                                 // post-processing: Registering new ids (end all tcemain sessions with this)
01228                         $this->addToMapId($tce->substNEWwithIDs);
01229 
01230                                 // In case of an update, order pages from the page tree correctly:
01231                         if ($this->update && is_array($this->dat['header']['pagetree']))        {
01232                                 $this->writeRecords_pages_order($pid);
01233                         }
01234                 }
01235         }
01236 
01246         function writeRecords_pages_order($pid) {
01247                 $cmd_data = array();
01248 
01249                         // Get uid-pid relations and traverse them in order to map to possible new IDs
01250                 $pidsFromTree = $this->flatInversePageTree_pid($this->dat['header']['pagetree']);
01251 #debug($this->dat['header']['pagetree'],'pagetree');
01252 #debug($pidsFromTree,'$pidsFromTree');
01253 #debug($this->import_newId_pids,'import_newId_pids');
01254                 foreach($pidsFromTree as $origPid => $newPid)   {
01255                         if ($newPid>=0 && $this->dontIgnorePid('pages', $origPid))      {
01256                                 if (substr($this->import_newId_pids[$origPid],0,3)==='NEW')     {       // If the page had a new id (because it was created) use that instead!
01257 
01258                                         if ($this->import_mapId['pages'][$origPid])     {
01259                                                 $mappedPid = $this->import_mapId['pages'][$origPid];
01260                                                 $cmd_data['pages'][$mappedPid]['move'] = $newPid;
01261                                         }
01262                                 } else {
01263                                         $cmd_data['pages'][$origPid]['move'] = $newPid;
01264                                 }
01265                         }
01266                 }
01267 
01268                         // Execute the move commands if any:
01269                 if (count($cmd_data))   {
01270                         $tce = $this->getNewTCE();
01271                         $tce->start(Array(),$cmd_data);
01272                         $tce->process_cmdmap();
01273                 }
01274 #debug($cmd_data,'$cmd_data');
01275         }
01276 
01284         function writeRecords_records($pid)     {
01285                 global $TCA;
01286 
01287                         // Write the rest of the records
01288                 $this->import_data = array();
01289                 if (is_array($this->dat['header']['records']))  {
01290                         reset($this->dat['header']['records']);
01291                         while(list($table,$recs) = each($this->dat['header']['records']))       {
01292                                 if ($table!='pages')    {
01293                                         reset($recs);
01294                                         while(list($uid,$thisRec)=each($recs))  {
01295                                                         // PID: Set the main $pid, unless a NEW-id is found
01296                                                 $setPid = isset($this->import_mapId['pages'][$thisRec['pid']]) ? $this->import_mapId['pages'][$thisRec['pid']] : $pid;
01297                                                 if (is_array($TCA[$table]) && $TCA[$table]['ctrl']['rootLevel'])        {
01298                                                         $setPid = 0;
01299                                                 }
01300 
01301                                                         // Add record:
01302                                                 $this->addSingle($table,$uid,$setPid);
01303                                         }
01304                                 }
01305                         }
01306                 } else $this->error('Error: No records defined in internal data array.');
01307 
01308                         // Now write to database:
01309                 $tce = $this->getNewTCE();
01310                 $tce->suggestedInsertUids = $this->suggestedInsertUids;
01311                 $tce->reverseOrder=1;   // Because all records are being submitted in their correct order with positive pid numbers - and so we should reverse submission order internally.
01312                 $tce->start($this->import_data,Array());
01313                 $tce->process_datamap();
01314 #debug($this->import_data,'RECORDS');
01315 
01316                         // post-processing: Removing files and registering new ids (end all tcemain sessions with this)
01317                 $this->addToMapId($tce->substNEWwithIDs);
01318 
01319                         // In case of an update, order pages from the page tree correctly:
01320                 if ($this->update)      {
01321                         $this->writeRecords_records_order($pid);
01322                 }
01323         }
01324 
01334         function writeRecords_records_order($mainPid)   {
01335                 $cmd_data = array();
01336 
01337                 if (is_array($this->dat['header']['pagetree'])) {
01338                         $pagesFromTree = $this->flatInversePageTree($this->dat['header']['pagetree']);
01339                 } else $pagesFromTree = array();
01340 
01341 #debug($this->dat['header']['pid_lookup'],'pid_lookup');
01342                 if (is_array($this->dat['header']['pid_lookup']))       {
01343                         foreach($this->dat['header']['pid_lookup'] as $pid => $recList) {
01344                                 $newPid = isset($this->import_mapId['pages'][$pid]) ? $this->import_mapId['pages'][$pid] : $mainPid;
01345 #debug(array($pid,$newPid),'$pid / $newPid');
01346 
01347                                 if (t3lib_div::testInt($newPid))        {
01348                                         foreach($recList as $tableName => $uidList)     {
01349