]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Import/ImportFileSplitter.php
Release 6.5.0
[Github/sugarcrm.git] / modules / Import / ImportFileSplitter.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
4 /*********************************************************************************
5  * SugarCRM Community Edition is a customer relationship management program developed by
6  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
7  * 
8  * This program is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Affero General Public License version 3 as published by the
10  * Free Software Foundation with the addition of the following permission added
11  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
12  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
13  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14  * 
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
18  * details.
19  * 
20  * You should have received a copy of the GNU Affero General Public License along with
21  * this program; if not, see http://www.gnu.org/licenses or write to the Free
22  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301 USA.
24  * 
25  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
26  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27  * 
28  * The interactive user interfaces in modified source and object code versions
29  * of this program must display Appropriate Legal Notices, as required under
30  * Section 5 of the GNU Affero General Public License version 3.
31  * 
32  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
33  * these Appropriate Legal Notices must retain the display of the "Powered by
34  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
35  * technical reasons, the Appropriate Legal Notices must display the words
36  * "Powered by SugarCRM".
37  ********************************************************************************/
38
39 /*********************************************************************************
40
41  * Description:  Class to handle splitting a file into separate parts
42  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
43  * All Rights Reserved.
44  ********************************************************************************/
45
46 class ImportFileSplitter
47 {
48     /**
49      * Filename of file we are splitting
50      */
51     private $_sourceFile;
52
53     /**
54      * Count of files that we split the $_sourceFile into
55      */
56     private $_fileCount;
57
58     /**
59      * Count of records in $_sourceFile
60      */
61     private $_recordCount;
62
63      /**
64      * Maximum number of records per file
65      */
66     private $_recordThreshold;
67
68     /**
69      * Constructor
70      *
71      * @param string $source filename we are splitting
72      */
73     public function __construct(
74         $source = null,
75         $recordThreshold = 1000
76         )
77     {
78             // sanitize crazy values to the default value
79         if ( !is_int($recordThreshold) || $recordThreshold < 1 ){
80                 //if this is not an int but is still a
81                 //string representation of a number, then cast to an int
82                 if(!is_int($recordThreshold) && is_numeric($recordThreshold)){
83                         //cast the string to an int
84                         $recordThreshold = (int)$recordThreshold;
85                 }else{
86                         //if not a numeric string, or less than 1, then default to 100
87                 $recordThreshold = 100;
88                 }
89         }
90         $this->_recordThreshold = $recordThreshold;
91         $this->_sourceFile      = $source;
92     }
93
94     /**
95      * Returns true if the filename given exists and is readable
96      *
97      * @return bool
98      */
99     public function fileExists()
100     {
101         if ( !is_file($this->_sourceFile) || !is_readable($this->_sourceFile)) {
102            return false;
103         }
104
105         return true;
106     }
107
108     /**
109      * Actually split the file into parts
110      *
111      * @param string $delimiter
112      * @param string $enclosure
113      * @param bool $has_header true if file has a header row
114      */
115     public function splitSourceFile(
116         $delimiter = ',',
117         $enclosure = '"',
118         $has_header = false
119         )
120     {
121         if (!$this->fileExists())
122             return false;
123         $importFile = new ImportFile($this->_sourceFile,$delimiter,$enclosure,false);
124         $filecount = 0;
125         $fw = sugar_fopen("{$this->_sourceFile}-{$filecount}","w");
126         $count = 0;
127         // skip first row if we have a header row
128         if ( $has_header && $importFile->getNextRow() ) {
129             // mark as duplicate to stick header row in the dupes file
130             $importFile->markRowAsDuplicate();
131             // same for error records file
132             $importFile->writeErrorRecord();
133         }
134         while ( $row = $importFile->getNextRow() ) {
135             // after $this->_recordThreshold rows, close this import file and goto the next one
136             if ( $count >= $this->_recordThreshold ) {
137                 fclose($fw);
138                 $filecount++;
139                 $fw = sugar_fopen("{$this->_sourceFile}-{$filecount}","w");
140                 $count = 0;
141             }
142             // Bug 25119: Trim the enclosure string to remove any blank spaces that may have been added.
143             $enclosure = trim($enclosure);
144                         if(!empty($enclosure)) {
145                                 foreach($row as $key => $v){
146                                         $row[$key] =preg_replace("/$enclosure/","$enclosure$enclosure", $v);
147                                 }
148                         }
149             $line = $enclosure.implode($enclosure.$delimiter.$enclosure, $row).$enclosure.PHP_EOL;
150                         //Would normally use fputcsv() here. But when enclosure character is used and the field value doesn't include delimiter, enclosure, escape character, "\n", "\r", "\t", or " ", php default function 'fputcsv' will not use enclosure for this string.
151                          fputs($fw, $line);
152             $count++;
153         }
154
155         fclose($fw);
156         $this->_fileCount   = $filecount;
157         $this->_recordCount = ($filecount * $this->_recordThreshold) + $count;
158         // increment by one to get true count of files created
159         ++$this->_fileCount;
160     }
161
162     /**
163      * Return the count of records in the file, if it's been processed with splitSourceFile()
164      *
165      * @return int count of records in the file
166      */
167     public function getRecordCount()
168     {
169         if ( !isset($this->_recordCount) )
170             return false;
171
172         return $this->_recordCount;
173     }
174
175     /**
176      * Return the count of files created by the split, if it's been processed with splitSourceFile()
177      *
178      * @return int count of files created by the split
179      */
180     public function getFileCount()
181     {
182         if ( !isset($this->_fileCount) )
183             return false;
184
185         return $this->_fileCount;
186     }
187
188     /**
189      * Return file name of one of the split files
190      *
191      * @param int $filenumber which split file we want
192      *
193      * @return string filename
194      */
195     public function getSplitFileName(
196         $filenumber = 0
197         )
198     {
199         if ( $filenumber >= $this->getFileCount())
200             return false;
201
202         return "{$this->_sourceFile}-{$filenumber}";
203     }
204
205 }
206